【问题标题】:Are class variables a good way to set the context for a class instance in a Rails application?类变量是在 Rails 应用程序中为类实例设置上下文的好方法吗?
【发布时间】:2012-01-27 02:47:07
【问题描述】:

类变量是在 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方法时,模型中的@@current_club属性(Member.current_club)总是为nil。换句话说,没有证据表明 current_club 在为新请求提供服务时受到先前请求的影响。所以我认为我们没问题,并且从应用程序控制器设置模型类变量的范围仅限于用户会话。但在继续采用这种方法之前,我想确定一下。”

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    如果你有 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
    

    您无需担心竞争条件、由于价值悬而未决的怪异以及所有这些废话。

    【讨论】:

    • 是的,这是可能的,但这正是我们试图避免的方法类型:每次更新操作都必须将俱乐部传递给成员。这看起来很尴尬。
    • 如果一个会员只属于一个俱乐部会很尴尬。但是,对于多个俱乐部的要求,您需要一种方法来挑选一个特定的俱乐部。是的,类变量是另一种方式,但你真的在为一个受伤的世界敞开心扉。共享数据最终会咬你一口。
    • Rails 应用程序不是单线程的吗?这将消除竞争条件的机会,否则会踩踏共享数据,不是吗?
    • @DaveIsaacs 虽然现在大多数 Rails 应用程序都关闭了线程安全(今天),但 JRuby 的常见做法是打开它。您今天可能不会针对 jruby 或线程安全,但在 2 年内您可能会。此外,这些类是缓存的,我预计一旦投入生产,就会出现重大问题。
    猜你喜欢
    • 2011-02-05
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 2012-01-07
    • 1970-01-01
    • 2017-02-15
    • 1970-01-01
    • 2014-03-12
    相关资源
    最近更新 更多