Rick
2009-Jan-02 19:46 UTC
How can I use the same model/pojo as both type ActiveRecord and non-ActiveRecord. Doesn''t seem dry to make two identical type objects.
I understand I can just define a class without extending ActiveReord::Base, but what if I want to use the model object sometimes without having the data persist. For example... Let''s say I have an "AutoManufacturer" object it might have name=Mercedes,etc. But AutoManufacturer could contain a collection of "Automobile" objects, (class=CLS, model="CLS350, numberOfDoors=4"). Maybe your db isn''t the one storing ALL the Automobile objects, you might only want to store ''favorite automobiles'' but you still want to collect all the Automobile information (class, model, etc) when you record a favorite. So now what if I go to my DB and get my "AutoManufacturer" objects and for each AutoManufacturer I query some webservice to return a list of Automobiles and I want to then display on a page the AutoManufacturers and a collection of the Automobile objects I returned from my webservice call. If I have "Automobile" defined as an ActiveRecord type when I do something like.... automobiles = getCarsFromWebservice() automobiles.each do |a| car = Automobile.new(); car.class= a.class car.type= a.type autoManufacturer.autos << car end every new car created above and added to the autoManufacturer actually creates a new car in the db, In this case all I want is fully populated list of autos in each autoManufacturer object for use to display on the front end, but I don''t really want the automobile added to the db at this time. (Maybe after they select some, I''ll then query a webservice and populate a real Automobile that I do want to persist in my db.) Currently I''m having to do something really lame. I''m creating basically identical objects - one a model object and one a simple pojo. It doesn''t seem very dry to do it this way though. What''s a better approach? -- Rick --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Florian Aßmann
2009-Jan-03 04:39 UTC
Re: How can I use the same model/pojo as both type ActiveRecord and non-ActiveRecord. Doesn''t seem dry to make two identical type objects.
Hi Rick, hope I got it right: class AutomobileManufacturer < ActiveRecord::Base has_many :automobiles def favorite_automobiles AutomobileCollection.from_association_collection automobiles end def all_automobiles favorite_automobiles | remote_automobiles end def remote_automobiles AutomobileCollection.from_webservice end end class AutomobileCollection def self.from_association_collection(collection) collection = collection.map { |a| AutomobileItem.from_database a } new collection end def self.from_webservice # load collection... or take it as argument collection = collection.map { |a| AutomobileItem.from_webservice a } new collection end # generate a hash to simplify intersect def initialize(collection) @collection_hash = collection.inject({}) { |hash, item| hash.merge item.identifier => item } @collection = collection end # this could possibly be done with ruby stdlib ''Delegate'' def each(&block) @collection.each(&block) end # intersect with another automobile collections def |(other) new_keys = other.automobiles_hash.keys - @collection_hash.keys new_collection = @collection + other.automobiles_hash.values_at(*new_keys) self.class.new new_collection end class AutomobileItem # two seperate methods because I think the interface for # webservice automobile and database automobile wont match. def self.from_webservice(automobile) instance = new automobile.manufacturer # ... instance end def self.from_database(automobile) instance = new automobile.manufacturer # ... def instance.favor # nop ... end instance end def initialize(manufacturer, *further_attributes) @attributes_hash = { # ... } end # generate an unique but compareable identifier def identifier "#{ manufacturer } ..." end # save the record, or maybe not when boxed automobile was loaded from db... def favor Automobile.create @attributes_hash # nop def self.favor; end end end end To make a subclass of ActiveRecord::Base to something not subclassing it requires some voodoo magic. If you really interested in this kind of stuff you should gte yourself involved with the rubiunius project. ;) Otherwise box them in something that would provide the same interface for SOAPed objects as for ORMed objects. This code is fully untested, but I hope you get the idea. Regards Florian Am 02.01.2009 um 20:46 schrieb Rick:> > I understand I can just define a class without extending > ActiveReord::Base, but what if I want to use the model object > sometimes without having the data persist. For example... > > Let''s say I have an "AutoManufacturer" object it might have > name=Mercedes,etc. But AutoManufacturer could contain a collection of > "Automobile" objects, (class=CLS, model="CLS350, numberOfDoors=4"). > Maybe your db isn''t the one storing ALL the Automobile objects, you > might only want to store ''favorite automobiles'' but you still want to > collect all the Automobile information (class, model, etc) when you > record a favorite. > > So now what if I go to my DB and get my "AutoManufacturer" objects and > for each AutoManufacturer I query some webservice to return a list of > Automobiles and I want to then display on a page the AutoManufacturers > and a collection of the Automobile objects I returned from my > webservice call. If I have "Automobile" defined as an ActiveRecord > type when I do something like.... > > automobiles = getCarsFromWebservice() > automobiles.each do |a| > car = Automobile.new(); > car.class= a.class > car.type= a.type > autoManufacturer.autos << car > end > > every new car created above and added to the autoManufacturer actually > creates a new car in the db, In this case all I want is fully > populated list of autos in each autoManufacturer object for use to > display on the front end, but I don''t really want the automobile added > to the db at this time. (Maybe after they select some, I''ll then query > a webservice and populate a real Automobile that I do want to persist > in my db.) > > Currently I''m having to do something really lame. I''m creating > basically identical objects - one a model object and one a simple > pojo. It doesn''t seem very dry to do it this way though. What''s a > better approach? > > -- > Rick > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Rick
2009-Jan-03 17:03 UTC
Re: How can I use the same model/pojo as both type ActiveRecord and non-ActiveRecord. Doesn''t seem dry to make two identical type objects.
Thanks for this Florian. I really appreciate the help. I have to admit though being a rails and ruby newbie, I''m a bit confused by it (ok maybe a lot confused.) (I''m a seasoned Java/JEE guy though so I''m not having too much trouble catching on too ruby and rails.) I''ve never seen a non ActionRecord object work as being persisted and retrieved. In the case below AutomobileItem is that object that could act as being retrieved from a db or a webservice (and as a collection like you have shown.) I think some of the info that is left out in the comment block in def self.from_database(automobile) I might need to see. Say I wanted to get a single AutomobileItem out of the db by the automoblileID how is it done? I take it''s something like setting an AutomobileItem with the id and then passing it to the from_database(automobile) method? I''m just clueless on how that would work? (I probably need to find a document or something online explaining it? I have the Agile Web Development with Rails pdf but I don''t think that covers this?) Also what if just wanted all automobiles.. since I don''t have a AutomobileItem.find(:all), what would I call? Sorry for these probably ignorant questions, it''s just a bit difficult for me since almost all the examples I''m finding deal with pure ActiveRecord objects. (Not that it matters but in real life this isn''t working with Automobiles, but rss feeds. I''m currently using Hobo migrations and my models look like: class RssFeed < ActiveRecord::Base fields do title :string body :text authors :string entry_url :string timestamps end belongs_to :rss_feed_source end class RssFeedSource < ActiveRecord::Base fields do name :string url :string timestamps end has_many :rss_feeds #used for non persistent feeds attr_accessor :feeds #tried declaring array in def intitialize but must have done it wrong def add_feed(feed) @feeds = [] if @feeds == nil @feeds << feed end end //see now annoying because I had to create this non persistent object that mimics the RssFeed class! class RssFeedNonpersistent attr_accessor :title, :body, :authors, :entry_url end On Fri, Jan 2, 2009 at 11:39 PM, Florian Aßmann <florian.assmann-htSm2yLGOjU@public.gmane.org> wrote:> > Hi Rick, hope I got it right: > > class AutomobileManufacturer < ActiveRecord::Base > has_many :automobiles > > def favorite_automobiles > AutomobileCollection.from_association_collection automobiles > end > def all_automobiles > favorite_automobiles | remote_automobiles > end > def remote_automobiles > AutomobileCollection.from_webservice > end > > end > > class AutomobileCollection > > def self.from_association_collection(collection) > collection = collection.map { |a| AutomobileItem.from_database a } > new collection > end > def self.from_webservice > # load collection... or take it as argument > collection = collection.map { |a| AutomobileItem.from_webservice > a } > new collection > end > > # generate a hash to simplify intersect > def initialize(collection) > @collection_hash = collection.inject({}) { |hash, item| > hash.merge item.identifier => item > } > @collection = collection > end > > # this could possibly be done with ruby stdlib ''Delegate'' > def each(&block) > @collection.each(&block) > end > > # intersect with another automobile collections > def |(other) > new_keys = other.automobiles_hash.keys - @collection_hash.keys > new_collection = @collection + > other.automobiles_hash.values_at(*new_keys) > > self.class.new new_collection > end > > class AutomobileItem > > # two seperate methods because I think the interface for > # webservice automobile and database automobile wont match. > > def self.from_webservice(automobile) > instance = new automobile.manufacturer # ... > instance > end > def self.from_database(automobile) > instance = new automobile.manufacturer # ... > def instance.favor > # nop ... > end > instance > end > > def initialize(manufacturer, *further_attributes) > @attributes_hash = { > # ... > } > end > # generate an unique but compareable identifier > def identifier > "#{ manufacturer } ..." > end > # save the record, or maybe not when boxed automobile was loaded > from db... > def favor > Automobile.create @attributes_hash > # nop > def self.favor; end > end > end > > end > > To make a subclass of ActiveRecord::Base to something not subclassing > it requires some voodoo magic. If you really interested in this kind > of stuff you should gte yourself involved with the rubiunius project. ;) > Otherwise box them in something that would provide the same interface > for SOAPed objects as for ORMed objects. > > This code is fully untested, but I hope you get the idea. > > Regards > Florian > > Am 02.01.2009 um 20:46 schrieb Rick: > >> >> I understand I can just define a class without extending >> ActiveReord::Base, but what if I want to use the model object >> sometimes without having the data persist. For example... >> >> Let''s say I have an "AutoManufacturer" object it might have >> name=Mercedes,etc. But AutoManufacturer could contain a collection of >> "Automobile" objects, (class=CLS, model="CLS350, numberOfDoors=4"). >> Maybe your db isn''t the one storing ALL the Automobile objects, you >> might only want to store ''favorite automobiles'' but you still want to >> collect all the Automobile information (class, model, etc) when you >> record a favorite. >> >> So now what if I go to my DB and get my "AutoManufacturer" objects and >> for each AutoManufacturer I query some webservice to return a list of >> Automobiles and I want to then display on a page the AutoManufacturers >> and a collection of the Automobile objects I returned from my >> webservice call. If I have "Automobile" defined as an ActiveRecord >> type when I do something like.... >> >> automobiles = getCarsFromWebservice() >> automobiles.each do |a| >> car = Automobile.new(); >> car.class= a.class >> car.type= a.type >> autoManufacturer.autos << car >> end >> >> every new car created above and added to the autoManufacturer actually >> creates a new car in the db, In this case all I want is fully >> populated list of autos in each autoManufacturer object for use to >> display on the front end, but I don''t really want the automobile added >> to the db at this time. (Maybe after they select some, I''ll then query >> a webservice and populate a real Automobile that I do want to persist >> in my db.) >> >> Currently I''m having to do something really lame. I''m creating >> basically identical objects - one a model object and one a simple >> pojo. It doesn''t seem very dry to do it this way though. What''s a >> better approach? >> >> -- >> Rick >> >> > > > > > >-- Rick --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---