Hola megas,
respuesta de Michael Papile es esencialmente correcta. Sin embargo, me gustaría detallarlo un poco, ya que hay algunos matices técnicos que quizás desee conocer. Miré el código para Railscasts y factory_girl y creo que hay algunas piezas extra para el rompecabezas que explican cómo la : termina arg admin => true hasta la creación de la administrador atributo de la fábrica de usuario. La adición del atributo en realidad no ocurre por medio del método de fábrica initialize(), aunque como Michael señaló que efectivamente se está llamando al método en servicio para construir el nuevo objeto de fábrica del usuario.
Voy a incluir en esta explicación todos los pasos que tomé en caso de que quiera ver cómo investigar las preguntas similares que pueda tener.
Dado que su publicación original está fechada en feb.17th miré a la versión de railscasts que coincide estrechamente con esa fecha.
Miré en su Gemfile:
https://github.com/ryanb/railscasts/blob/d124319f4ca2a2367c1fa705f5c8229cce70921d/Gemfile
Línea 18:
gem "factory_girl_rails"
entonces Fui a ver el compromiso de factory_girl_rails que la mayor parte estrecha similitud, la fecha 17o Feb.
https://github.com/thoughtbot/factory_girl_rails/blob/544868740c3e26d8a5e8337940f9de4990b1cd0b/factory_girl_rails.gemspec
Línea 16:
s.add_runtime_dependency('factory_girl', '~> 2.0.0.beta')
factory_girl versión 2.0.0.beta no era realmente tan fácil de encontrar. No hay etiquetas github con ese nombre, así que acabo de ver el más cercano en términos de fecha de confirmación.
https://thoughtbot/factory_girl/blob/9fb8a3b40f24f0c8477776133a2f9cd654ca1c8c/lib/factory_girl/syntax/vintage.rb
Líneas 122-128:
# Shortcut for Factory.default_strategy.
#
# Example:
# Factory(:user, :name => 'Joe')
def Factory(name, attrs = {})
Factory.default_strategy(name, attrs)
end
Así que la invocaciónfábrica en Railscasts es en realidad llamar a un método de conveniencia que invoca la "estrategia por defecto", que se encuentra en el mismo archivo :
Líneas 39-52:
# Executes the default strategy for the given factory. This is usually create,
# but it can be overridden for each factory.
#
# Arguments:
# * name: +Symbol+ or +String+
# The name of the factory that should be used.
# * overrides: +Hash+
# Attributes to overwrite for this instance.
#
# Returns: +Object+
# The result of the default strategy.
def self.default_strategy(name, overrides = {})
self.send(FactoryGirl.find(name).default_strategy, name, overrides)
end
Tenga en cuenta que FactoryGirl.find se invoca para obtener el objeto al que se llama default_strategy. El método encontrar resuelve aquí:
https://thoughtbot/factory_girl/blob/9fb8a3b40f24f0c8477776133a2f9cd654ca1c8c/lib/factory_girl/registry.rb
Líneas 12-14:
def find(name)
@items[name.to_sym] or raise ArgumentError.new("Not registered: #{name.to_s}")
end
Aquí el nombre de usuario es :. Por lo tanto, deseamos invocar default_strategy en la fábrica usuario. Como señaló Michael Papile, esta fábrica de usuarios fue definida y registrada por el código Railscasts que originalmente pensaste que era la definición de clase para Factory.
https://ryanb/railscasts/blob/d124319f4ca2a2367c1fa705f5c8229cce70921d/spec/factories.rb
Líneas 23-25:
Factory.define :user do |f|
f.sequence(:github_username) { |n| "foo#{n}" }
end
Así que en la investigación de lo que es la estrategia por defecto para la fábrica de usuario, que miraron a su alrededor en el proyecto y Railscasts encontraron esta:
https://ryanb/railscasts/blob/d124319f4ca2a2367c1fa705f5c8229cce70921d/spec/factories.rb
Líneas 43-45:
def default_strategy #:nodoc:
@options[:default_strategy] || :create
end
: crear es la estrategia predeterminada. Volvemos a factory_girl para encontrar la def para create.
https://thoughtbot/factory_girl/blob/9fb8a3b40f24f0c8477776133a2f9cd654ca1c8c/lib/factory_girl/syntax/methods.rb
Líneas 37-55:
# Generates, saves, and returns an instance from this factory. Attributes can
# be individually overridden by passing in a Hash of attribute => value
# pairs.
#
# Instances are saved using the +save!+ method, so ActiveRecord models will
# raise ActiveRecord::RecordInvalid exceptions for invalid attribute sets.
#
# Arguments:
# * name: +Symbol+ or +String+
# The name of the factory that should be used.
# * overrides: +Hash+
# Attributes to overwrite for this instance.
#
# Returns: +Object+
# A saved instance of the class this factory generates, with generated
# attributes assigned.
def create(name, overrides = {})
FactoryGirl.find(name).run(Proxy::Create, overrides)
end
La estrategia de crear llama a la plazo método definido aquí:
https://thoughtbot/factory_girl/blob/9fb8a3b40f24f0c8477776133a2f9cd654ca1c8c/lib/factory_girl/factory.rb
Líneas 86-97:
def run(proxy_class, overrides) #:nodoc:
proxy = proxy_class.new(build_class)
overrides = symbolize_keys(overrides)
overrides.each {|attr, val| proxy.set(attr, val) }
passed_keys = overrides.keys.collect {|k| FactoryGirl.aliases_for(k) }.flatten
@attributes.each do |attribute|
unless passed_keys.include?(attribute.name)
attribute.add_to(proxy)
end
end
proxy.result(@to_create_block)
end
Una traducción/resumen de lo que este código está haciendo:
primer lugar, el objetoproxy está construido llamando nueva en el proxy_class, que en este caso es Proxy :: Create , que se define aquí:
https://thoughtbot/factory_girl/blob/9fb8a3b40f24f0c8477776133a2f9cd654ca1c8c/lib/factory_girl/proxy/create.rb
Básicamente todo lo que necesita saber es que proxy está creando un nuevo objeto de fábrica de usuario e invocando devoluciones de llamada antes y después de que se cree el objeto de fábrica.
Volviendo al método plazo, vemos que todos los argumentos adicionales que se aprobaron inicialmente en el método de conveniencia fábrica (en este caso, : admin => true) están siendo etiquetados como reemplaza. El objeto proxy invoca un establece el método, pasando cada par de nombre-valor de atributo como args.
El set() método es parte de la clase Construir, la clase padre de Proxy.
https://thoughtbot/factory_girl/blob/9fb8a3b40f24f0c8477776133a2f9cd654ca1c8c/lib/factory_girl/proxy/build.rb
líneas 12-14:
def set(attribute, value)
@instance.send(:"#{attribute}=", value)
end
Aquí @instance se refiere a los objetos proxy, el objeto de fábrica de usuario.
Esto entonces, es como : admin => true se establece como un atributo en la fábrica del usuario que crea el código de especificaciones de railscasts.
Si lo desea, puede googlear "patrones de diseño de programación" y leer sobre los siguientes patrones: fábrica, apoderado, constructor, estrategia.
Espero que esta publicación sea útil.
==============================
@ Michael Papile:
que iba a agrega un comentario a tu publicación, pero aún no tengo suficientes puntos de reputación de stackoverflow.com para hacerlo.
Usted escribió:
http://www.ruby-doc.org/core/classes/Kernel.html Aviso matriz y cadena etc tienen construcciones similares. Estoy tratando de averiguar cómo lo hicieron ahora .
Si todavía tiene curiosidad, la Matriz y la Cadena que ve en el documento Kernel son en realidad solo métodos de fábrica utilizados para crear nuevos objetos de esos tipos. Es por eso que no se necesita la nueva invocación de método . En realidad, no son llamadas de constructor, sino que asignan e inicializan objetos Array y String, y por lo tanto, bajo el capó están haciendo el equivalente de invocar initialize() en objetos de esos tipos. (En C, sin embargo, por supuesto, no en Ruby)
En segundo lugar el libro Metaprogramming Ruby. Soy nuevo para Ruby y este libro me ha dado una comprensión mucho más profunda de Ruby. –