Frage

Ich verwende die Schienen-Einstellungen Juwel, und ich versuche zu verstehen, wie Sie Funktionen Active Klassen hinzufügen (ich bin meine eigene Bibliothek für Kartenspiele Gebäude), und ich bemerkte, dass dieses Juwel einer der Meta-Programmiertechniken verwendet die Funktion der Activerecord :: Base-Klasse (ich bin weit davon hinzufügen aus Meta-Programmierung Master in ruby, aber ich versuche, es zu lernen)

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

Was ich nicht verstehe ist, warum er verwendet class_eval auf Activerecord :: Base, wurde es nicht leichter, wenn er nur die Active öffnen :: Basisklasse und die Funktionen definieren? Speziell, dass es dynamische nichts im Block (Was ich damit meine ist dynamisch, wenn Sie tun class_eval oder instance_eval auf einem String-Variablen enthält)

so etwas wie folgt aus:

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

verstehe ich die zweite class_eval (vor den def Einstellungen) ist Funktionen im laufenden Betrieb auf jeder Klasse zu definieren, dass ‚has_settings‘ richtig? Gleiche Frage hier, glaube ich, dass er „def self.settings“ statt „class_eval .... def Einstellungen“ verwenden könnte, nicht wahr?

War es hilfreich?

Lösung

Was Schienen-Einstellungen Code hat sich als gute Praxis: es nur Verwirrungen mit Module von Drittanbietern, wenn es ausdrücklich darum gebeten. Auf diese Weise können auch die Namensräume halten säuberlich getrennt und alle Ihren Code bleibt in Ihrer Module.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top