【问题标题】:Dynamically define scopes from within class << self从类 << self 中动态定义范围
【发布时间】:2013-10-31 19:02:28
【问题描述】:

如何在 class &lt;&lt; self 上下文中动态分配范围?

class Partner < ActiveRecord::Base

  STATUS = {
    pending: 0,    # 0 account has a pending billing request (but is not yet open)
    active: 1,     # 1 account has an active base subscription
    suspended: 2,  # 2 account has been suspended (e.g. after a base subscription decline)
    expired: 3,    # 3 base subscription has expired
    incomplete: 4, # 4 partner application process incomplete
    closed: 5,     # 5 account has been permanently closed
    cancelled: 6   # 6 account has been cancelled by user (but is still unexpired)
  }

  after_initialize :setup_status_enums

  def status
    STATUS.key(read_attribute(:status))
  end

  def status=(s)
    write_attribute(:status, STATUS[s])
  end

  private

    def setup_status_enums
          class << self
            STATUS.map do |key, val|
              raise "Collision in enum values method #{key}" if respond_to?("#{key.to_s}?") or respond_to?("#{key.to_s}!") or respond_to?("#{key.to_s}")

              define_method "#{key.to_s}?" do
                send("status") == key
              end

              define_method "#{key.to_s}!" do
                send("status=", val)
              end

              scope key.to_sym, lambda { where(:status => val) }
            end
          end
    end

end

【问题讨论】:

    标签: ruby ruby-on-rails-4 rails-activerecord named-scope


    【解决方案1】:

    这样的事情应该可以工作。您可以直接在类定义中遍历您的 STATUS 哈希。

    class Partner < ActiveRecord::Base
      STATUS = {
        pending: 0,    # 0 account has a pending billing request (but is not yet open)
        active: 1,     # 1 account has an active base subscription
        suspended: 2,  # 2 account has been suspended (e.g. after a base subscription decline)
        expired: 3,    # 3 base subscription has expired
        incomplete: 4, # 4 partner application process incomplete
        closed: 5,     # 5 account has been permanently closed
        cancelled: 6   # 6 account has been cancelled by user (but is still unexpired)
      }
    
      STATUS.each do |key, val|
        define_method "#{key.to_s}?" do
          status == key
        end
    
        define_method "#{key.to_s}!" do
          status = val
        end
    
        scope key, lambda { where(status: val) }
      end
    
      ...
    end
    

    【讨论】:

      【解决方案2】:

      您似乎正在寻找状态机。

      在 Ruby 中,查看 state_machineaasm gems。然后,您可以根据state 列定义范围(或者您可以命名为status。)

      状态机还将帮助您管理状态之间的转换,因此您可以仅针对特定转换或状态运行回调或验证。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多