Forum: Ruby on Rails Default value for scope in multi-account App, best way

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
F1dd1d0fabf86b25b1f72836ad6c44f4?d=identicon&s=25 Olaf S. (olafson)
on 2009-04-27 09:17
Hi,

I'm working on a multi-user, multi-account App where 1 account can have
n users. It is very important that every user can only access info from
its account. My approach is to add an account_id to every model in the
DB and than add a filter in every controller to only select objects with
the current account_id. I will use the authorization plugin.

Is this approach a good idea?

What is the best way to always set the account_id for every object that
is created without writing

object.account = @current_account

in every CREATE action? Maybe a filter?

Also I'm not sure about the best way to implement the filter for the
select options. I need something like a general condition: No matter
what else appears in the SQL statement, there should always be a "WHERE
account_id = XY".

Thanks for your help!
F1dd1d0fabf86b25b1f72836ad6c44f4?d=identicon&s=25 Olaf S. (olafson)
on 2009-04-27 09:59
I know, I know, if you access Session-variables or Instance variables in
your Model you didn't understand the MVC pattern and "should go back to
PHP". But still, this could be very useful if you have - like us - a lot
of controllers and actions where you don't always want to write
@current_account.object.do_something (not very DRY).

The solution I found is very easy:

Step 1: Add your current_account to Thread.current, so for example

class ApplicationController < ActionController::Base
  before_filter :get_current_account

  protected
   def get_current_account
     # somehow get the current account, depends on your approach
     Thread.current[:account] = @account
   end
end

Step 2: Add a current_account method to all your models

   #/lib/ar_current_account.rb
   ActiveRecord::Base.class_eval do
     def current_account
      Thread.current[:account]
     end
   end

Step 3: Voilá, in your Models you can do something like this:

class MyModel < ActiveRecord::Base

  belongs_to :account

  # Set the default values
  def initialize(params = nil)
    super
      self.account_id ||= current_account.id
  end

end

You could also work with something like the before_validation callback
in active_record and then make with a validation sure the account is
always set.

The same approach could be used if you always want to add the
current_user to every created object.

What do you think?
F1dd1d0fabf86b25b1f72836ad6c44f4?d=identicon&s=25 Olaf S. (olafson)
on 2009-04-27 10:20
Sorry, it has to be

   #/lib/ar_current_account.rb
   ActiveRecord::Base.class_eval do
     def self.current_account
      Thread.current[:account]
     end
   end

of course!
This topic is locked and can not be replied to.