ErwinM / acts_as_tenant

Easy multi-tenancy for Rails in a shared database setup.
MIT License
1.53k stars 263 forks source link

Basecamp like tenants from params #265

Closed tommasongr closed 2 years ago

tommasongr commented 2 years ago

Hi everyone! I'm new to Rails and I have a possibly stupid question.

I wanted to configure this gem to follow a Basecamp like scoping of the tenants: example.com/123/projects. I've been able to get it working but I'm not sure if I followed any best pratice...


This is my current configuration:

TenantController (I don't want to use the ApplicationController since not all the routes will be scoped)

class TenantController < ApplicationController
  set_current_tenant_through_filter
  before_action :find_current_tenant

  def find_current_tenant
    current_account = Account.find(params[:account_id])
    set_current_tenant(current_account)
  end
end

routes.rb (I used a scope parameter but I'm not sure is the proper way of doing it)

Rails.application.routes.draw do
  root to: 'pages#home'
  resources :accounts

  scope '/:account_id' do
    resources :calendars
  end

  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end

And here it is my main doubt...

In the views I had to change the urls to use current tenant. Is not a main issue but it seems odd to me that there is not a way, if I'm already on example.com/123/..., to tell all the urls to keep that prefix. I would much rather prefer to simply pass <%= link_to 'Show', calendar %>.

<% @calendars.each do |calendar| %>
  <tr>
    <td><%= calendar.account_id %></td>
    <td><%= calendar.name %></td>
    <td><%= calendar %></td>

    <td><%= link_to 'Show', calendar_path(ActsAsTenant.current_tenant, calendar) %></td>
    <td><%= link_to 'Edit', edit_calendar_path(ActsAsTenant.current_tenant, calendar) %></td>
    <td><%= link_to 'Destroy', calendar_path(ActsAsTenant.current_tenant, calendar), method: :delete, data: { confirm: 'Are you sure?' } %></td>
  </tr>
<% end %>

Is this the proper way of doing it? Is there a way fix the urls situation?

Thanks and sorry for the silly question but I haven't been able to find the answer anywhere 😅

excid3 commented 2 years ago

It's better to use a Rack middleware that sets the tenant and SCRIPT_NAME so that Rails does not need to know about it. If you use the scope, every single URL helper in your Rails app needs to include the current tenant which is going to get annoying real fast. With the middleware, the ID is automatically included.

I did a screencast on it here: https://gorails.com/episodes/rails-active-support-current-attributes And source code: https://github.com/gorails-screencasts/gorails-episode-234

tommasongr commented 2 years ago

Oh wow! It seems exactly what I was looking for 😅 I'll definitely take a look at the screencast.

Thanks!