如何在 Rails 中始终设置帐户范围的值?

发布于 2024-07-18 05:40:22 字数 430 浏览 5 评论 0原文

我正在开发一个多用户、多帐户应用程序,其中 1 个帐户可以有 n 个用户。 每个用户只能访问其帐户中的信息,这一点非常重要。 我的方法是向数据库中的每个模型添加一个 account_id,然后在每个控制器中添加一个过滤器以仅选择具有当前 account_id 的对象。 我将使用授权插件。

这种方法是个好主意吗?

始终为创建的每个对象设置 account_id 而无需写入

object.account = @current_account

每个 CREATE 操作的最佳方法是什么? 也许是一个过滤器?

另外,我不确定实现选择选项过滤器的最佳方法。 我需要类似一般条件的东西:无论SQL语句中出现什么,总是有一个“WHERE account_id = XY”。

感谢您的帮助!

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 is always a "WHERE account_id = XY".

Thanks for your help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

耀眼的星火 2024-07-25 05:40:22

这类似于 User.has_many :emails 场景。 您不希望用户通过更改 URL 中的 ID 来查看其他人的电子邮件,因此您可以这样做:

@emails = current_user.emails

在您的情况下,您可能可以执行以下操作:

class ApplicationController < ActionController::Base
  def current_account
    @current_account ||= current_user && current_user.account
  end
end

# In an imagined ProjectsController
@projects = current_account.projects
@project = current_account.projects.find(params[:id])

This is similar to a User.has_many :emails scenario. You don't want the user to see other peoples emails by changing the ID in the URL, so you do this:

@emails = current_user.emails

In your case, you can probably do something like this:

class ApplicationController < ActionController::Base
  def current_account
    @current_account ||= current_user && current_user.account
  end
end

# In an imagined ProjectsController
@projects = current_account.projects
@project = current_account.projects.find(params[:id])
巾帼英雄 2024-07-25 05:40:22

我知道,我知道,如果您在模型中访问会话变量或实例变量,您不理解 MVC 模式并且“应该回到 PHP”。 但是,如果您像我们一样有很多控制器和操作,而您并不总是想编写 @current_account.object.do_something (不是很干),那么这仍然非常有用。

我找到的解决方案非常简单:

第一步:
将您的 current_account 添加到 Thread.current,例如

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

步骤 2:
将 current_account 方法添加到所有模型

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

第 3 步:瞧,在模型中,您可以执行以下操作:

class MyModel < ActiveRecord::Base

  belongs_to :account

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

end

您还可以使用 active_record 中的 before_validation 回调之类的操作,然后进行验证以确保始终设置帐户。

如果您总是想将 current_user 添加到每个创建的对象中,则可以使用相同的方法。

你怎么认为?

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 self.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?

决绝 2024-07-25 05:40:22

要回答第二个问题,请查看新的 default_scope Rails 2.3 中的 功能。

To answer your second question, check out the new default_scope feature in Rails 2.3.

南冥有猫 2024-07-25 05:40:22

我理解您不想一直为确定帐户范围而烦恼。 老实说,这是一种痛苦。

要添加一点魔力并无缝地完成此范围界定,请查看以下 gem

http://gemcutter.org/ gems/account_scopper

希望这会有所帮助,

--
塞巴斯蒂安·格罗斯让 - ZenCocoon

I understand that you don't want to bother about scoping you account all time. Lets be honest, it's a pain in the a**.

To add a bit magic and have this scoping done seamlessly give a look at the following gem

http://gemcutter.org/gems/account_scopper

Hope this helps,

--
Sebastien Grosjean - ZenCocoon

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文