Reputation: 131
grateful to have you guys as a resource! I think this should be a simple question but haven't been able to find a simple answer through searching yet, any help/guidance would be appreciated!! I have a "subdomain" controller which is setup in the following way:
get 'subdomain/:store' => 'subdomain#index'
get 'subdomain/:store/products' => 'subdomain#product_index'
get 'subdomain/:store/products/:id' => 'subdomain#products_show'
As you can see, the subdomain controller matches the request with a Store ID and can also get an index of all the associated products with the Store ID. I'd like to somehow convert each of these requests into a subdomain rather than a path. Each Store has a "subdomain" attribute (in the example below, one of the Store records has a subdomain value of "nike").
For example
host.com/subdomain/nike => nike.host.com
host.com/subdomain/nike/products => nike.host.com/products
host.com/subdomain/nike/products/5 => nike.host.com/products/5
Notice the controller "subdomain" was removed from the path. Any help? I looked into gems such as apartment but they look like they are way too complex for this. Also subdomain-fu but it looks like it's outdated for Rails 4. Thoughts? THANKS!
Upvotes: 1
Views: 1321
Reputation: 34135
For this, you can add routing Constraint.
Add the file to lib/subdomain_required.rb
class SubdomainRequired
def self.matches?(request)
request.subdomain.present? && request.subdomain != 'www'
end
end
Then, in your routes.rb
, you can enclose your routes into a contraint block, somewhat like this:
constraints(SubdomainRequired) do
get '/' => 'subdomain#index'
get '/products' => 'subdomain#product_index'
get '/products/:id' => 'subdomain#products_show'
end
Now the last step is to load the store based on subdomain which can be done using a before_action
like this
class SubdomainController < ActionController::Base
before_action :ensure_store!
def index
@products = current_store.products.all
end
def ensure_store!
@store ||= Store.find_by subdomain: request.subdomain
head(:not_found) if @store.nil?
@store
end
def current_store
@store
end
end
now anywhere you want to get the store, you can use current_store
helper method.
Hope it helps
Upvotes: 3