Hola gente,
Tengo unos cuantos modelos y controladores que comparten una serie de
metodos y estoy viendo la manera de ser mas DRY y no tener el código
repetido con todos los problemas para mantenerlo que esto acarrea.
Tengo curiosidad por saber que patrones usais vosotros en este tipo de
situaciones.
Tras darle vueltas yo estoy haciendolo de la siguiente manera:
Me creo uno modulo:
module foo
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def my_foo
belongs_to :bar
include foo::InstanceMethods
extend foo::SingletonMethods
end
end
module InstanceMethods
def example_method end
end
module SingletonMethods
def example_method end
end
end
luego con un initializer lo cargo:
ActiveRecord::Base.send(:include, foo)
para luego en el modelo:
class Article < ActiveRecord::Base
my_foo
end
Y bueno lo mismo para los controladores.
El único inconveniente que le encuentro es que cada vez que haces un
cambio tienes que reiniciar el servidor o relanzar el irb.
¿Alguien sabe alguna manera de evitar esto y hacer que se cargen los
cambios en “caliente”?¿ideas para mejorar el patron?
saludos
Felipe
On Sun, Sep 21, 2008 at 9:39 PM, Felipe T. Armero <
[email protected]> wrote:
module SingletonMethods
def example_method end
end
end
luego con un initializer lo cargo:
ActiveRecord::Base.send(:include, foo)
A mi no me gusta ese modelo, entre otros, por el hecho de usar send, que
si
mal no recuerdo, en ruby 1.9, send no es capaz de llamar a métodos
privados
como include.
Personalmente, prefiero algo parecido, pero que no toque activerecord:
class User < AR::Base
include my_module
end
Me gusta también más por lo que se me pega de Merb. Un modelo de
datamaper:
class User
include DM::Resource
include my_module
end
El único inconveniente que le encuentro es que cada vez que haces un
cambio tienes que reiniciar el servidor o relanzar el irb.
¿Alguien sabe alguna manera de evitar esto y hacer que se cargen los
cambios en “caliente”?¿ideas para mejorar el patron?
Mira si te puede ser útil el reload_application
http://github.com/rails/rails/tree/master/actionpack/lib/action_controller/dispatcher.rb
saludos
Felipe
saludos
On 21 Sep 2008, at 22:26, Guillermo wrote:
luego con un initializer lo cargo:
ActiveRecord::Base.send(:include, foo)
A mi no me gusta ese modelo, entre otros, por el hecho de usar send,
que si mal no recuerdo, en ruby 1.9, send no es capaz de llamar a
métodos privados como include.
Es cierto que ‘send’ no es capaz de llamar a métodos privados en Ruby
1.9.
La alternativa (la que usan en Rails, si no me equivoco) es:
ActiveRecord::Base.class_eval { include Foo }
-christos
Hubo un tiempo en el que #send se quito en el desarrollo de Ruby 1.9,
pero regreso:
Mon Nov 5 00:32:32 2007 Yukihiro M. [email protected]
* eval.c (rb_f_send): allow send/__send__ to call methods of all
visibility again. we no longer provide __send, __send!.
¡Ah!
Esto explica porque hay commits como estos:
http://github.com/rails/acts_as_list/tree/master/init.rb
pero no en todos lo sitios donde deberia:
http://github.com/rails/acts_as_tree/tree/master/init.rb
-christos
2008/9/21 Guillermo [email protected]:
A mi no me gusta ese modelo, entre otros, por el hecho de usar send, que si
mal no recuerdo, en ruby 1.9, send no es capaz de llamar a métodos privados
como include.
#send se usa sin reparos en Rails:
fxn@feynman:~/prj/rails$ ack ‘.send(’ | wc -l
465
Hubo un tiempo en el que #send se quito en el desarrollo de Ruby 1.9,
pero regreso:
Mon Nov 5 00:32:32 2007 Yukihiro M. [email protected]
* eval.c (rb_f_send): allow send/__send__ to call methods of all
visibility again. we no longer provide __send, __send!.
En 1.9 finalmente #send sigue ahi como en 1.8, y se añade #public_send
por si el caller quiere respetar visibilidad a proposito.
Dicho esto, para una cuestion asi los cambios de API que pudieran
haber en la 1.9 en general no me parecerian muy relevantes con
respecto al diseño en si de la solucion.