I''m dying for this functionality between my models. class Person < ActiveRecord::Base has_many :notes end class Note < ActiveResource::Base belongs_to :person end Ideally associations should be generic enough to work with any "ActiveModel" type. Associations shouldn''t be dealing directly with SQL, this is the job of the target model. There are a few quirks I want to get started with. Associations try to load construct the necessary finder sql when called. I''ve been using this little hack for ActiveResource. class ActiveResource::Base class << self def table_name collection_name end def sanitize_sql(sql) ActiveRecord::Base.send(:sanitize_sql, sql) end end end Right now, I am using ugly ActiveResource monkey patches to interpret the SQL arguments ActiveRecord sends it. class ActiveResource::Base class << self def find_with_associations(*args) if args.last.is_a?(Hash) && args.last[:conditions] if args.first == :all || args.first == :first if conditions = args.last[:conditions] and conditions.is_a? (String) scope, id = conditions.gsub(/\.| = /, "-").split("-").last(2) else scope, id = conditions.to_a.flatten.map(&:to_s) end find_without_associations(args.first, :from => "/ #{scope.humanize.tableize}/#{id}/#{collection_name}.xml") else find_without_associations(*args) end else find_without_associations(*args) end end alias_method_chain :find, :associations end end This turns this "Note.find(:all, :conditions = ''notes.person_id = 1'')" into "Note.find(:all, :from => "/people/1/notes")". I''ll be submitting patches over the next few weeks that hopefully cleanup this muck. Just wondering if anyone else has been trying to hack something similar together? --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
I was actually just looking into this for my first project to utilize ActiveResource. I need to be able to create a has_many :through association between one of my ActiveRecord models and an ActiveResource model through an intermediary ActiveRecord model. :-) It would be nice to be able to create any association between ActiveRecord resources (local resources) and ActiveResource resources (remote resources) where the foreign key is stored somewhere in the local database. So in other words... On ActiveRecord models ===============has_and_belongs_to_many :remote_objects # habtm table being local has_many :remote_objects, :through => :local_join_model belongs_to :remote_object On ActiveResource models ================has_many :local_objects has_one :local_object There are a couple issues with this though: 1) How do you handle local records that are orphaned by a record that''s deleted by the remote application? The local application will have no way of knowing that the associated remote record was removed unless it is the one that did the deleting. It won''t know it was deleted until it executes a get request on that remote record. 2) How do you load the remote objects on habtm & has_many :through associations? With RESTful urls, you either GET the entire collection or GET one element. Do you just do a get request on the entire remote collection and then remove the unassociated objects? That could be a very costly operation with large collections. And I don''t think you want to do a GET request on each individual object either. Has the Rails Core discussed ActiveResource associations at all? If so, what''s the current thinking about them? Josh, I''m confused about the example you gave though. You did a belongs_to association on a remote resource to a local resource. How does the remote application know about the local resource? Note.find(:all, :from => "/people/1/notes") indicates that the remote application knows about Person, but you said Person was an ActiveRecord model. On Aug 24, 12:58 pm, Josh Peek <joshp...@gmail.com> wrote:> I''m dying for this functionality between my models. > > class Person < ActiveRecord::Base > has_many :notes > end > > class Note < ActiveResource::Base > belongs_to :person > end > > Ideally associations should be generic enough to work with any > "ActiveModel" type. Associations shouldn''t be dealing directly with > SQL, this is the job of the target model. > > There are a few quirks I want to get started with. Associations try to > load construct the necessary finder sql when called. I''ve been using > this little hack for ActiveResource. > > class ActiveResource::Base > class << self > def table_name > collection_name > end > > def sanitize_sql(sql) > ActiveRecord::Base.send(:sanitize_sql, sql) > end > end > end > > Right now, I am using ugly ActiveResource monkey patches to interpret > the SQL arguments ActiveRecord sends it. > > class ActiveResource::Base > class << self > def find_with_associations(*args) > if args.last.is_a?(Hash) && args.last[:conditions] > if args.first == :all || args.first == :first > if conditions = args.last[:conditions] and conditions.is_a? > (String) > scope, id = conditions.gsub(/\.| = /, > "-").split("-").last(2) > else > scope, id = conditions.to_a.flatten.map(&:to_s) > end > find_without_associations(args.first, :from => "/ > #{scope.humanize.tableize}/#{id}/#{collection_name}.xml") > else > find_without_associations(*args) > end > else > find_without_associations(*args) > end > end > alias_method_chain :find, :associations > end > end > > This turns this "Note.find(:all, :conditions = ''notes.person_id = 1'')" > into "Note.find(:all, :from => "/people/1/notes")". > > I''ll be submitting patches over the next few weeks that hopefully > cleanup this muck. > > Just wondering if anyone else has been trying to hack something > similar together?--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
On Aug 26, 2:47 am, Marc Love <marcsl...@gmail.com> wrote:> 1) How do you handle local records that are orphaned by a record > that''s deleted by the remote application? The local application will > have no way of knowing that the associated remote record was removed > unless it is the one that did the deleting. It won''t know it was > deleted until it executes a get request on that remote record.By default ActiveRecord leaves orphaned records as well. The same "destroy" callback applies for both ActiveRecord and ActiveResource models. (However delete_all doesn''t exactly work remotely)> 2) How do you load the remote objects on habtm & has_many :through > associations? With RESTful urls, you either GET the entire collection > or GET one element. Do you just do a get request on the entire remote > collection and then remove the unassociated objects? That could be a > very costly operation with large collections. And I don''t think you > want to do a GET request on each individual object either.Some conventions need to come up for plain old has_many relationships. I''m using the nested collection resource (/people/1/notes). But your right, there is no way to efficiently do has_many :through. I think we need to solve the simple ones first (belongs_to, has_one, has_many).> Josh, I''m confused about the example you gave though. You did a > belongs_to association on a remote resource to a local resource. How > does the remote application know about the local resource? > Note.find(:all, :from => "/people/1/notes") indicates that the remote > application knows about Person, but you said Person was an > ActiveRecord model.Person was local and Note was remote. The Note uses a simple belongs_to association and just looks up the person with the foreign key it has. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
> By default ActiveRecord leaves orphaned records as well. The same > "destroy" callback applies for both ActiveRecord and ActiveResource > models. (However delete_all doesn''t exactly work remotely)Right, but I''d bet that most people are using the dependent option fairly frequently. The destroy callbacks wouldn''t work on an ActiveResource model because the local application (and therefore the ActiveResource model) is not notified by the remote application when it destroys a record on its own. For instance, lets say my remote application is something like an Amazon-type store. And my local application is a review website that depends on the product records provided by the RESTful store. In this situation I have: class Review < ActiveRecord::Base belongs_to :product end class Product < ActiveResource::Base has_many :reviews end Now what happens when the RESTful store itself removes a product? The RESTful store never notifies my local application of the deletion because it doesn''t know anything about my local application. So a destroy callback won''t be called by ActiveResource model. Sure I could just let the orphaned reviews stay in my database, but maybe that''s not ideal for my particular application.> Person was local and Note was remote. The Note uses a simple > belongs_to association and just looks up the person with the foreign > key it has.Okay, but the foreign key is stored in the table for the class saying belongs_to. If Note is remote, where are you storing the foreign key? And how do you call Note.find(:all, :from => "/people/1/notes") on the remote application when "people" are stored locally? On Aug 26, 5:54 am, Josh Peek <joshp...@gmail.com> wrote:> On Aug 26, 2:47 am, Marc Love <marcsl...@gmail.com> wrote: > > > 1) How do you handle local records that are orphaned by a record > > that''s deleted by the remote application? The local application will > > have no way of knowing that the associated remote record was removed > > unless it is the one that did the deleting. It won''t know it was > > deleted until it executes a get request on that remote record. > > By default ActiveRecord leaves orphaned records as well. The same > "destroy" callback applies for both ActiveRecord and ActiveResource > models. (However delete_all doesn''t exactly work remotely) > > > 2) How do you load the remote objects on habtm & has_many :through > > associations? With RESTful urls, you either GET the entire collection > > or GET one element. Do you just do a get request on the entire remote > > collection and then remove the unassociated objects? That could be a > > very costly operation with large collections. And I don''t think you > > want to do a GET request on each individual object either. > > Some conventions need to come up for plain old has_many relationships. > I''m using the nested collection resource (/people/1/notes). But your > right, there is no way to efficiently do has_many :through. I think we > need to solve the simple ones first (belongs_to, has_one, has_many). > > > Josh, I''m confused about the example you gave though. You did a > > belongs_to association on a remote resource to a local resource. How > > does the remote application know about the local resource? > > Note.find(:all, :from => "/people/1/notes") indicates that the remote > > application knows about Person, but you said Person was an > > ActiveRecord model. > > Person was local and Note was remote. The Note uses a simple > belongs_to association and just looks up the person with the foreign > key it has.--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
On Aug 26, 5:45 pm, Marc Love <marcsl...@gmail.com> wrote:> Right, but I''d bet that most people are using the dependent option > fairly frequently. The destroy callbacks wouldn''t work on an > ActiveResource model because the local application (and therefore the > ActiveResource model) is not notified by the remote application when > it destroys a record on its own. For instance, lets say my remote > application is something like an Amazon-type store. And my local > application is a review website that depends on the product records > provided by the RESTful store. In this situation I have: > > class Review < ActiveRecord::Base > belongs_to :product > end > > class Product < ActiveResource::Base > has_many :reviews > end > > Now what happens when the RESTful store itself removes a product? The > RESTful store never notifies my local application of the deletion > because it doesn''t know anything about my local application. So a > destroy callback won''t be called by ActiveResource model. Sure I > could just let the orphaned reviews stay in my database, but maybe > that''s not ideal for my particular application.I sure hope Amazon (or any third party server) doesn''t have access to destroy reviews on my web app. But if I am linking two of my own servers together, I would have the reverse setup on the other server. # Review server class Review < ActiveRecord::Base belongs_to :product end class Product < ActiveResource::Base has_many :reviews end # Product server class Review < ActiveResource::Base belongs_to :product end class Product < ActiveRecord::Base has_many :reviews, :dependent => :destroy end> > Person was local and Note was remote. The Note uses a simple > > belongs_to association and just looks up the person with the foreign > > key it has. > > Okay, but the foreign key is stored in the table for the class saying > belongs_to. If Note is remote, where are you storing the foreign > key? And how do you call Note.find(:all, :from => "/people/1/notes") > on the remote application when "people" are stored locally?The remote server has to know the existence of people on the other server (reverse relationship on the remote server). --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
Ah I see, you''re assuming you have control over both applications. I don''t think that''s something you can assume when working with web services. More often than not, you''re using a web API to interact with someone else''s application. On Aug 26, 9:17 pm, Josh Peek <joshp...@gmail.com> wrote:> On Aug 26, 5:45 pm, Marc Love <marcsl...@gmail.com> wrote: > > > > > Right, but I''d bet that most people are using the dependent option > > fairly frequently. The destroy callbacks wouldn''t work on an > > ActiveResource model because the local application (and therefore the > > ActiveResource model) is not notified by the remote application when > > it destroys a record on its own. For instance, lets say my remote > > application is something like an Amazon-type store. And my local > > application is a review website that depends on the product records > > provided by the RESTful store. In this situation I have: > > > class Review < ActiveRecord::Base > > belongs_to :product > > end > > > class Product < ActiveResource::Base > > has_many :reviews > > end > > > Now what happens when the RESTful store itself removes a product? The > > RESTful store never notifies my local application of the deletion > > because it doesn''t know anything about my local application. So a > > destroy callback won''t be called by ActiveResource model. Sure I > > could just let the orphaned reviews stay in my database, but maybe > > that''s not ideal for my particular application. > > I sure hope Amazon (or any third party server) doesn''t have access to > destroy reviews on my web app. But if I am linking two of my own > servers together, I would have the reverse setup on the other server. > > # Review server > class Review < ActiveRecord::Base > belongs_to :product > end > class Product < ActiveResource::Base > has_many :reviews > end > > # Product server > class Review < ActiveResource::Base > belongs_to :product > end > class Product < ActiveRecord::Base > has_many :reviews, :dependent => :destroy > end > > > > Person was local and Note was remote. The Note uses a simple > > > belongs_to association and just looks up the person with the foreign > > > key it has. > > > Okay, but the foreign key is stored in the table for the class saying > > belongs_to. If Note is remote, where are you storing the foreign > > key? And how do you call Note.find(:all, :from => "/people/1/notes") > > on the remote application when "people" are stored locally? > > The remote server has to know the existence of people on the other > server (reverse relationship on the remote server).--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
Yes. I work with alot of internal web services because our apps are split up. And if you are working with a third party service, you don''t have access to as many features you would if you controlled both. On Aug 27, 12:24 am, Marc Love <marcsl...@gmail.com> wrote:> Ah I see, you''re assuming you have control over both applications. I > don''t think that''s something you can assume when working with web > services. More often than not, you''re using a web API to interact > with someone else''s application.--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---