2009/10/3 Martin Aceto <[email protected]>:
>
>
>> 2009/10/3 Martin Aceto <[email protected]>:
>> >
>> >
>> > 2009/10/3 Nelson Fernandez <[email protected]>
>> >>
>> >> 2009/10/3 Martin Aceto <[email protected]>
>> >>>
>> >>> 2009/10/3 Nelson Fernandez <[email protected]>
>> >>>>
>> >>>> Martin !
>> >>>>
>> >>>> 2009/10/2 Martin Aceto <[email protected]>
>> >>>>>
>> >>>>> Hola, como estan
>> >>>>>
>> >>>>> estoy tratando de extender activerecord para poder sacar de un
>> >>>>> modelo
>> >>>>> logica que no pertenece a ese modelo sino que engloba varios
>> >>>>> modelos, logica
>> >>>>> de negocio bastante complicada que desearia separar.
>> >>>>>
>> >>>>> Me encuentro con la pregunta de cual es la forma correcta de hacerlo
>> >>>>> ?
>> >>>>>
>> >>>>> Lo que pense fue crear un archivo en /lib y dentro definir esos
>> >>>>> metodos
>> >>>>> que necesito, este ejemplo de abajo es correcto ? o estoy equivocado
>> >>>>> en mi
>> >>>>> concepto ?
>> >>>>>
>> >>>>> module Test
>> >>>>>   module ClassMethods
>> >>>>>     def test
>> >>>>>       puts "Test"
>> >>>>>     end
>> >>>>>   end
>> >>>>> end
>> >>>>>
>> >>>>> ActiveRecord::Base.send(:extend, Test::ClassMethods)
>> >>>>
>> >>>>
>> >>>> Comparto con Emanuel de usar la menos magia posible .. quizás otra
>> >>>> solución simple sea usar mixins [1] ?.
>> >>>>
>> >>>> [1] http://www.rubycentral.com/pickaxe/tut_modules.html#S2
>> >>>>
>> >>>>
>> >>>> --
>> >>>> :: nelson ::
>> >>>> [ artesano de software & software craftsman ]
>> >>>> http://netflux.com.ar
>> >>>>
>> >>>>
>> >>>>
>> >>>
>> >>> Leí el enlace que mandaste Nelson, si es mas simple, esta bueno. Pero
>> >>> quiero extender ActiveRecord para poder tener esos metodos en todas
>> >>> las
>> >>> clases, estoy intentando hacer esto como dijo Emmanuel
>> >>>
>> >>> module Test
>> >>>
>> >>>   module ClassMethods
>> >>>
>> >>>     def test
>> >>>       puts "Test"
>> >>>     end
>> >>>
>> >>>   end
>> >>>
>> >>> end
>> >>>
>> >>> ActiveRecord::Base.extend, Test::ClassMethods
>> >>> ActiveRecord::Base.class_eval do
>> >>>   include Test::InstanceMethods
>> >>> end
>> >>>
>> >>> pero no me funciona, y no entiendo porque, pero si incluyo
>> >>> directamente
>> >>> en una clase de esta manera
>> >>>
>> >>
>> >>
>> >> "extend" es para agregar los métodos de un modulo a una "instancia", no
>> >> a
>> >> una clase.
>> >> Lo que está haciendo "ActiveRecord::Base.extend Test::ClassMethods" es
>> >> extender el objeto que implementa Class... en el caso práctico estás
>> >> agregando métodos de clase, es decir que lo que va a funcionar es
>> >>
>> >> ActiveRecord::Base.test
>> >> o
>> >> MyModelo.test
>> >>
>> >> que no es lo que estas buscando, creo... sino que las instancias de
>> >> ActiveRecord tengan tus nuevos métodos.
>> >>
>> >> Para mí la forma más simple y clara nuevamente es usar mixins y de esa
>> >> forma queda muy claro que modelos van a tener esa funcionalidad
>> >> agregada.
>> >>
>> >>
>> >>
>> >> PD: Te recomiendo ver este video donde Dave Thomas explica el modelo de
>> >> objetos de Ruby
>> >>
>> >> http://scotland-on-rails.s3.amazonaws.com/2A04_DaveThomas-SOR.mp4
>> >>
>> >> y este muy gracioso cuando Joe OBrian quiere usar metaprograming a toda
>> >> costa ;)
>> >>
>> >>
>> >> http://scotland-on-rails.s3.amazonaws.com/2A08_JoeOBrianJimWeirich-SOR.mp4
>> >>
>> >>
>> >
>> > Nelson, lo que estoy intentando hacer, como vos dijiste,  es extender el
>> > objeto que implementa Class y poder hacer
>> >
>> > ActiveRecord::Base.test
>> > o
>> > MyModelo.test
>> > pero no se porque no me funciona.
>> >
>> > Gracias
>> >
>>
> 2009/10/3 Nicolás Sanguinetti <[email protected]>
>
> Primero (y hago top posting porque recien me levante, tengo sueño, y
> soy re heavy re jodido :P) lo que decía Emmanuel sobre "clases
> específicas" no es que si lo vas a usar en *una sola clase*, sino en
> *algunas* clases especificas. Ponele que tenés una aplicación chica,
> con no sé, 10 modelos.
>
> Si vos querés extraer una funcionalidad a algo que se comparte entre 4
> o 5 de ellos, hacer ActiveRecord::Base.extend(MyAwesomeMixin) es chancho. Le
> estás encajando métodos a 5 o 6 modelos que no tienen nada
>>
>> que ver con eso.
>>
>> Entonces lo prolijo sería hacer el "include" o "extend" en cada uno de
>> los 4 o 5 modelos que necesitan MyAwesomeMixin.
>>
>> class User < AR::B
>>  include Foo
>> end
>>
>> class Thing < AR::B
>>  include Foo
>> end
>>
>> etc.
>>
>> Segundo, si vos lo que querés es agregar métodos de clase compartidos
>> entre varios modelos (por ejemplo, finders, métodos de search, etc),
>> lo que querés hacer es extend, sí.
>>
>> class User < AR::B
>>  extend FooBar
>> end
>>
>> Si estás haciendo esto (como entiendo de tu primer post) y no
>> funciona, entonces va a ser mejor que hagas un paste con código "más
>> de verdad" para entender dónde está el problema. Por que lo que vos
>> pegaste arriba, tiene que andar.
>>
>> (Ojo al gol, si vos ponés un 'puts' en un modelo, el output lo vas a
>> ver en el mismo output que tu server si usas mongrel/thin/etc, o no lo
>> vás a ver nada si usás passenger—capaz que el problema es ese? Probá
>> poner Rails.logger.info("---------> test") y fijarte si no aparece en
>> el log)
>>
>> -f
>
>
> Hola Nicolas, entiendo lo que decis de que extender ActiveRecord para todos
> los modelos cuando solo la mitad o menos usaran esos metodos, es chanco, por
> lo cual voy a utilizar include o extend en los modelos que necesito esos
> metodos especificos.
>
> Pero de todas estas preguntas y respuestas me quede con la intriga de como
> hacer para extender ActiveRecord para agregar, finders, metodos de search,
> etc... para toda la aplicación, por eso les comente que no me funcionaba
> esto
>
>
> module Test
>   module ClassMethods
>     def test
>       puts "Test"
>     end
>   end
> end
>
> ActiveRecord::Base.extend, Test::ClassMethods
> ActiveRecord::Base.class_eval do
>   include Test::InstanceMethods
> end
>
> (todo mi codigo se reduce a esto) solo una simple prueba
>
> por lo que yo entendi con ese codigo de arriba podria hacer en una consola
> para cualquier modelo del app, como por ejemplo User
>
> User.test
>
> y me daria el texto "text".
> Esto sin hacer ningún include o extend dentro de User, no es así ?

Ah, pará, vos dijiste que pusiste el código en lib, no?

En dónde estás haciendo los llamados a extend? Si es desde el mismo
archivo, tenés que, en algún lado, requerir ese archivo. Rails no
requiere todos los archivos, los requiere a medida que se necesitan, y
el mecanismo para saber eso es según nombres de constantes.

Si vos pedís Foo en algún lado se va a fijar por app/models/foo.rb,
lib/foo.rb, vendor/gems/*/lib/foo.rb, vendor/plugins/*/lib/foo.rb.
(Creo que en ese orden, pero tampoco es importante).

El tema es que si vos directamente llamás al método en el modelo, sin
haber requerido antes el archivo, no va a andar :)

Si lo vás a extender explicitamente en los modelos, al hacer

class User
  extend MyAwesomeMixin
end

estás referenciando la constante, y por ende haciendo que rails
requiera el archivo (en cuyo caso va a funcionar).

Pero si querés que lo meta en todos los archivos, entonces el
ActiveRecord::Base.extend(MyAwesomeMixin) tendrías que ponerlo en un
initializer, en config/initializers/my_awesome_mixin.rb -- eso se
asegura de que todos los modelos tengan esos métodos cuando inicia el
framework.

Saludos,
-f

>
>
> _______________________________________________
> Ruby mailing list
> [email protected]
> http://lista.rubyargentina.com.ar/listinfo.cgi/ruby-rubyargentina.com.ar
>
>
_______________________________________________
Ruby mailing list
[email protected]
http://lista.rubyargentina.com.ar/listinfo.cgi/ruby-rubyargentina.com.ar

Responder a