When implementing new features, it should not depend on current
RAILS_ENV
value, but environment variable(s) specific to the
feature.
- Avoid modifying
config/environments/*.rb
, and keep default Rails configuration (this will also help when updating Rails) - Avoid testing:
Rails.env.development?
Rails.env.production?
Rails.env.test?
Examples:
# bad:
module MyRailsApp
class Application < Rails::Application
if Rails.env.production?
config.middleware.use Rack::Attack
end
end
end
# good:
module MyRailsApp
class Application < Rails::Application
if ENV.key? "RACK_ATTACK_ENABLED"
config.middleware.use Rack::Attack
end
end
end
Actual format segregation should be performed based on the HTTP Accept
header
(Accept: application/json
), not based on a URL suffix (/resource.json
).
A unique resource should only be requested on a unique URL, which is why we should avoid extension-based routing as much as possible.
# bad
GET /resources.html
GET /resources.json
# bad
GET /resources [Accept: text/html]
GET /api/resources [Accept: application/json]
# good
GET /resources [Accept: text/html]
GET /resources [Accept: application/json]
This can be achieved in Rails using the following router configuration:
Rails.application.routes.draw do
concern :resources do
resources :posts
resources :comments
end
scope format: ENV.key?("ALLOW_FORMAT_FROM_URL") ? nil : false do
scope module: :api, constraints: ->(req) { req.format == :json } do
concerns :resources
end
concerns :resources
end
end