Domanda

Sto usando le rotaie-settings gioiello, e sto cercando di capire come si aggiunge funzioni per le classi ActiveRecord (sto costruendo la mia libreria per giochi di carte), e ho notato che questo gioiello utilizza una delle tecniche Meta-programmazione per aggiungere la funzione al ActiveRecord :: classe base (sono lontano da Meta-programmazione di master in rubino, ma sto cercando di imparare)

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

Quello che non capisco è il motivo per cui egli utilizza class_eval su ActiveRecord :: Base, non è stato più facile se ha appena aperto la classe ActiveRecord :: Base e definire le funzioni? Specialmente che non c'è nulla dinamica del blocco (cosa intendo per dinamica è quando si fa class_eval o instance_eval su una stringa contenente le variabili)

qualcosa di simile:

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

capisco il secondo class_eval (prima che le impostazioni DEF) è quello di definire le funzioni al volo su ogni classe che giusta 'has_settings'? Stessa domanda qui, credo che avrebbe potuto usare "Def self.settings" invece di "class_eval .... def impostazioni", no?

È stato utile?

Soluzione

Cosa Rails-settings codice non è considerata buona pratica: è solo pasticci con moduli di terze parti quando è esplicitamente chiesto di farlo. In questo modo si mantiene anche gli spazi dei nomi ordinatamente separati e tutti i resti di codice nei moduli.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top