I am creating an multitenant app based on ideas from Ryan Bigg's book "Multitenancy with Rails". In this book, the tenants has their own subdomain. This approach is not applicable in my case, so I'm trying to scope by a slug of the account's name instead.
So instead of URLs like http://account-name.myapp.com
, i want http://myapp.mydomain.com/account-name/
. The subdomain is reserved for the app itself, because I want to be able to have more than one app on my domain.
Here's a piece of my routes.rb:
scope module: 'accounts' do
resources :customers do
resources :notes
end
end
To achieve my goal, i try to follow the routing guide on rubyonrails.com (the last code snippet in chapter 4.5), and change the above code to:
scope ':slug', module: 'accounts' do
resources :customers do
resources :notes
end
end
slug
is an attribute in the accounts
table in the database, so if an account is called "My Business", the slug will typically be "my-business".
This change seems to correct my routes:
customers GET /:slug/customers(.:format)
.. but it also seems to break my site, as the slug is not fetched from the database. I can't seem to wrap my mind around how this scope':slug', module: 'accounts'
works. Is Rails supposed to automatically recognize :slug as an attribute of the Accoounts table? If not, can anyone please help me find a way to use the account's slug in my URLs?
I have googled around for a couple of days now, and read numerous answers here on Stackoverflow. Nothing helped, so any pointers is greatly appreciated. :-)
EDIT:
The relevant controllers are set up like this:
controllers/accounts/base_controller.rb
controllers/accounts/customers_controller.rb
controllers/accounts/products_controlelr.rb
controllers/accounts_controller.rb
controllers/application_controller.rb
The accounts_controller.rb only has actions for new and create at this point.
The accounts/base_controller.rb look like this:
module Accounts
class BaseController < ApplicationController
before_action :authorize_user!
def current_account
@current_account ||= Account.find_by_slug(params[:slug])
end
...
end
end
I addded this to my Account model:
def to_param
slug
end
Before i tried to implement scope ':slug'
in my routes, everyting worked when logged in users where directed to myapp.mydomain.com/dashboard and navigated to i.e. myapp.mydomain.com/customers. Now it works with myapp.mydomain.com/account-name/dashboard, but as soon as I try to navigate to a view that use helpers like new_customer_path
, i get the error:
No route matches {:action=>"show", :controller=>"accounts/customers", :id=>nil, :slug=>#
I hope this makes my issue clearer. :-)
I am not sure whether your routes is set up correctly or not because you didn't post your controller source code, but basically how it works if very simple. If you are using the current routes you set up what you should do is create an account_customers_controller.rb
file in controllers\account\
folder, and it should look like this:
class Accounts::CustomersController < ActionController::Base
def show
@account = Account.find_by_slug(params[:slug])
...
end
end