我正在使用 轨道 GEM,我正在尝试了解您如何在ActivereCord类中添加函数(我正在为纸牌游戏构建库),我注意到这种GEM使用元编程技术之一将功能添加到ActivereCord ::基类(我与Ruby中的元编程大师相去甚远,但我正在尝试学习)

module RailsSettings
  class Railtie < Rails::Railtie

    initializer 'rails_settings.initialize', :after => :after_initialize do
      Railtie.extend_active_record
    end

  end

  class Railtie
    def self.extend_active_record
      ActiveRecord::Base.class_eval do
        def self.has_settings
          class_eval do
            def settings
              RailsSettings::ScopedSettings.for_thing(self)
            end

            scope :with_settings, :joins => "JOIN settings ON (settings.thing_id = #{self.table_name}.#{self.primary_key} AND
                                                               settings.thing_type = '#{self.base_class.name}')",
                                  :select => "DISTINCT #{self.table_name}.*"

            scope :with_settings_for, lambda { |var| { :joins => "JOIN settings ON (settings.thing_id = #{self.table_name}.#{self.primary_key} AND
                                                                                    settings.thing_type = '#{self.base_class.name}') AND
                                                                                    settings.var = '#{var}'" } }

            scope :without_settings, :joins => "LEFT JOIN settings ON (settings.thing_id = #{self.table_name}.#{self.primary_key} AND
                                                                       settings.thing_type = '#{self.base_class.name}')",
                                     :conditions => 'settings.id IS NULL'

            scope :without_settings_for, lambda { |var| { :joins => "LEFT JOIN settings ON (settings.thing_id = #{self.table_name}.#{self.primary_key} AND
                                                                                            settings.thing_type = '#{self.base_class.name}') AND
                                                                                            settings.var = '#{var}'",
                                                          :conditions => 'settings.id IS NULL' } }
          end
        end
      end
    end

  end
end

我不明白的是,为什么他在ActivereCord :: Base上使用class_eval,如果他只是打开ActivereCord :: Base类并定义功能,那就不容易了吗?特别是,块中没有动态(我的含义是当您在包含变量的字符串上进行class_eval或instance_eval时的含义)

这样的事情:

module ActiveRecord
  class Base
    def self.has_settings
      class_eval do
        def settings
          RailsSettings::ScopedSettings.for_thing(self)
        end

        scope :with_settings, :joins => "JOIN settings ON (settings.thing_id = #{self.table_name}.#{self.primary_key} AND
                                                           settings.thing_type = '#{self.base_class.name}')",
                              :select => "DISTINCT #{self.table_name}.*"

        scope :with_settings_for, lambda { |var| { :joins => "JOIN settings ON (settings.thing_id = #{self.table_name}.#{self.primary_key} AND
                                                                                settings.thing_type = '#{self.base_class.name}') AND
                                                                                settings.var = '#{var}'" } }

        scope :without_settings, :joins => "LEFT JOIN settings ON (settings.thing_id = #{self.table_name}.#{self.primary_key} AND
                                                                   settings.thing_type = '#{self.base_class.name}')",
                                 :conditions => 'settings.id IS NULL'

        scope :without_settings_for, lambda { |var| { :joins => "LEFT JOIN settings ON (settings.thing_id = #{self.table_name}.#{self.primary_key} AND
                                                                                        settings.thing_type = '#{self.base_class.name}') AND
                                                                                        settings.var = '#{var}'",
                                                      :conditions => 'settings.id IS NULL' } }
      end
    end
  end
end

我了解第二个class_eval(在def设置之前)是在每个“ has_settings''的类中飞出的函数,对吗?同样的问题,我认为他可以使用“ def self.settings”而不是“ class_eval .... def设置”,不是吗?

有帮助吗?

解决方案

什么 轨道 代码确实被认为是好的练习:明确要求这样做时,它只会与第三方模块混乱。这样,您还将命名空间保持整齐分开,并且所有代码都保留在模块中。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top