Sigh, por que no haces lo de poner el include/extend en cada modelo?
2009/10/3 Martin Aceto <[email protected]>: > > > 2009/10/3 Nicolás Sanguinetti <[email protected]> >> >> 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 >> >> > > Ahi funciono, me faltaba saber eso, no estaba requeriendo el archivo y por > eso no lo tenia disponible en todos los modelos, ahora me quedo > > config/initializers/extend_ar.rb > > ActiveRecord::Base.extend(Test::ClassMethods) > ActiveRecord::Base.class_eval do > include Test::InstanceMethods > end > > y en lib/test.rb > > module Test > module ClassMethods > def test > puts "Test" > end > end > > module InstanceMethods > end > end > > y funciona perfecto ! > > Tenes idea donde esta en la doc de rails esto de que se tiene que requerir > el archivo para que haga el extend ? tendria que leerla. > > Gracias Nicolas > > _______________________________________________ > 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
