我的应用基于子域。每个经理都有自己的子域,只能显示他的拍卖。我有:
class Lot < ActiveRecord::Base
belongs_to :auction
end
class Auction < ActiveRecord::Base
has_many :lots
belongs_to :manager
end
class manager < ActiveRecord::Base
has_many :auctions
end
如果使用子域访问应用程序,我有一个执行以下操作的before_filter:
def load_manager
@loaded_manager = Manager.find_by_subdomain(request.subdomain)
end
在我的Lot的default_scope上,我想做以下事情:
default_scope { @loaded_manager.present? ? where(deleted: false).joins(:auction => :manager).where("auctions.manager_id = ?", @loaded_manager.id) : where(deleted: false) }
这样,只要我在网站上,我就会展示属于经理拍卖的地段。
问题是我无法访问模型上的@loaded_manager。这样做的最佳方式是什么?
http://railscasts.com/episodes/388-multitenancy-with-scopes?view=comments解决了这个问题!
答案 0 :(得分:1)
您可以在过滤器之前将当前经理存储在Manager模型中:
def load_manager
Manager.set_current(request.subdomain)
end
class Manager < ActiveRecord::Base
cattr_accessor :current
def self.set_current(subdomain)
self.current = self.find_by_subdomain(subdomain)
end
end
class Lot < ActiveRecord::Base
default_scope { Manager.current.present? ? where(deleted: false).joins(:auction => :manager).where("auctions.manager_id = ?", Manager.current.id) : where(deleted: false) }
end
<强>更新强>
由于@Mik_Die注意到它不是线程安全的,因此对于线程安全解决方案,读者可以查看railscasts - multitenancy-with-scopes(code here)。我们只在Thread
中存储current_id。
答案 1 :(得分:0)
模型无权访问控制器的实例变量(并且不应该 - 它会破坏MVC原则)
可能在这种情况下使用默认范围是个坏主意。考虑使用像这样的通常范围
scope :for_manager, lambda{ |manager| manager.present? ? where(deleted: false).joins(:auction => :manager).where("auctions.manager_id = ?", manager.id) : where(deleted: false) }
然后在你的控制器中
@lots = Lot.for_manager(@loaded_manager)