Question

J'utilise les petit bijou , et je suis en train de comprendre comment vous ajoutez des fonctions aux classes ActiveRecord (je construis ma propre bibliothèque pour les jeux de cartes), et je remarqué que ce petit bijou utilise l'une des techniques de programmation Meta pour ajouter la fonction à la ActiveRecord :: la classe de base (je suis loin de maître-programmation Meta en ruby, mais je suis en train de l'apprendre)

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

Ce que je ne comprends pas pourquoi il utilise class_eval sur ActiveRecord :: Base, n'a pas été plus facile s'il suffit d'ouvrir la ActiveRecord :: La classe de base et définir les fonctions? Spécialement qu'il n'y a rien de dynamique dans le bloc (Ce que je veux dire par dynamique est quand vous faites class_eval ou instance_eval sur une chaîne contenant des variables)

quelque chose comme ceci:

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

Je comprends la deuxième class_eval (avant que les paramètres def) est de définir des fonctions à la volée sur toutes les classes que de droite « has_settings »? Même question ici, je pense qu'il pourrait utiliser "def self.settings" au lieu de "class_eval .... paramètres def", non?

Était-ce utile?

La solution

Qu'est-ce que rails paramètres code n'est considéré comme une bonne pratique: il ne salit avec des modules tiers quand il est demandé de le faire explicitement ainsi. De cette façon, vous gardez aussi les espaces de noms et tous tidily Séparées vos restes de code dans vos modules.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top