类变量是否是在Rails应用程序中为类实例设置上下文的好方法?
我们正在构建一个管理俱乐部成员的rails应用程序。因此,有会员模型和俱乐部模型。由于会员可以属于许多俱乐部,俱乐部可以有很多会员,因此他们之间有HABTM协会。
我们遇到的困难是确定成员实例存在的俱乐部上下文。例如,要将会员会费状态设置为“付费”,我们需要知道会员已支付会费。我们希望控制器只需设置类似
的内容@member.paid=true
每次我们更新会员时都不必为记得设置俱乐部而烦恼。
我们提出的解决方案在Member中设置了一个类变量。
application_controller.rb
class ApplicationController < ActionController::Base
before_filter :set_current_club
def set_current_club
Member.current_club = current_club
end
...
end
作为一个有点人为的例子,想象一下每个俱乐部都包含一系列缴纳会费的会员。那我们就有了。
member.rb
class Member < ActiveRecord::Base
cattr_accessor :current_club
...
def paid=(status)
if (status)
@@current_club.paid_members << self
else
@@current_club.paid_member.delete(self)
end
end
def paid?
@@current_club.paid_members.include?(self)
end
...
end
担心的是,通过在ApplicationController before_filter中将current_club设置为Member类变量,当多个俱乐部同时访问应用程序时,是否可能存在冲突和竞争条件?
我们在开发环境中进行了一些调试测试,并且在ApplicationController中输入before_filter方法时,模型(Member.current_club)中的@@ current_club属性始终为nil。换句话说,没有证据表明current_club在提供新请求时受到先前请求的影响。所以我认为我们没问题,从Application Controller设置模型类变量的范围是用户的会话。但在继续这种方法之前,我想确定一下。“
答案 0 :(得分:0)
如果你有current_club属性,我假设它是某种形式的会话变量,那么完全不需要上面的代码。
要在拥有current_club变量的同时获取会员的俱乐部记录,只需遍历与该会员相关的所有俱乐部,找到与当前俱乐部相匹配的记录即可。
这样的事情:
class Member < AR::Base
def paid_for(club, status)
if status
club.paid_members << self
else
club.paid_members.delete(self)
end
end
你不需要担心竞争条件,由于价值悬浮而产生的怪异以及所有废话。