ChuckE
2013-Feb-19 15:56 UTC
has_one from has_many: when an association can be fetched in more than one place.
Hi, I came across a certain use case that could need some fine tuning. Let''s say I have a song Model. This song is available in many formats. So, the song has_many formats (mp3, flac, ...). The song also has the original where the other might have been generated from. So, the song has_one original. This is my current state of affairs: class Song < ActiveRecord::Base has_many :formats has_one :original, class_name: "Format", conditions: { tag: "original" } end So far, so good. Problem is, now I have my original made available in two different places, and if I update one, it is not reproduced on the other, until I synchronize everything from the database (not to the database). s = Song.first s.formats.select{|f| f.tag == "original" } # original original s.original #original original s.original = Format.create(.... tag: "original") # changed original s.formats.select{|f| f.tag == "original" } # original original (!!) s.reload s.formats.select{|f| f.tag == "original" } # changed original And this sucks, specially when I start playing around with validations, I end up tucking more than I would like to. So the question is: how well could one devise such an association which is contained somewhere else? Something like: class Song < ActiveRecord::Base has_many :formats has_one :original, class_name: "Format", conditions: { tag: "original" },*on: :formats * end And from then on this "has one" would be a proxy to an instance contained in an has_many collection. So, what would speak against such a feature? I''m all hears -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-core+unsubscribe@googlegroups.com. To post to this group, send email to rubyonrails-core@googlegroups.com. Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. For more options, visit https://groups.google.com/groups/opt_out.
Rafael Mendonça França
2013-Feb-19 16:04 UTC
Re: has_one from has_many: when an association can be fetched in more than one place.
If you want to reload the association cache you can pass true as argument. s.formats(true).select { |f| f.tag == "original" } Will always get what you want. Rafael Mendonça França http://twitter.com/rafaelfranca https://github.com/rafaelfranca On Tue, Feb 19, 2013 at 12:56 PM, ChuckE <honeyryderchuck@gmail.com> wrote:> Hi, > > I came across a certain use case that could need some fine tuning. Let''s > say I have a song Model. This song is available in many formats. So, the > song has_many formats (mp3, flac, ...). The song also has the original > where the other might have been generated from. So, the song has_one > original. This is my current state of affairs: > > class Song < ActiveRecord::Base > has_many :formats > has_one :original, class_name: "Format", conditions: { tag: "original" } > end > > So far, so good. Problem is, now I have my original made available in two > different places, and if I update one, it is not reproduced on the other, > until I synchronize everything from the database (not to the database). > > s = Song.first > s.formats.select{|f| f.tag == "original" } # original original > s.original #original original > s.original = Format.create(.... tag: "original") # changed original > s.formats.select{|f| f.tag == "original" } # original original (!!) > s.reload > s.formats.select{|f| f.tag == "original" } # changed original > > And this sucks, specially when I start playing around with validations, I > end up tucking more than I would like to. > > So the question is: how well could one devise such an association which is > contained somewhere else? Something like: > > class Song < ActiveRecord::Base > > has_many :formats > has_one :original, class_name: "Format", conditions: { tag: "original" }, > * on: :formats* > > end > > And from then on this "has one" would be a proxy to an instance contained > in an has_many collection. > > So, what would speak against such a feature? I''m all hears > > -- > You received this message because you are subscribed to the Google Groups > "Ruby on Rails: Core" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to rubyonrails-core+unsubscribe@googlegroups.com. > To post to this group, send email to rubyonrails-core@googlegroups.com. > Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. > For more options, visit https://groups.google.com/groups/opt_out. > > >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-core+unsubscribe@googlegroups.com. To post to this group, send email to rubyonrails-core@googlegroups.com. Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. For more options, visit https://groups.google.com/groups/opt_out.
ChuckE
2013-Feb-19 16:13 UTC
Re: has_one from has_many: when an association can be fetched in more than one place.
Thanks for the suggestion, that''s what I meant by tucking stuff. My point is, stuff is already somewhere right in memory, why couldn''t it be set right there? I''m exactly trying to avoid the DB roundtrips and the possible spaghetti code stemming from such a situation. Terça-feira, 19 de Fevereiro de 2013 17:04:50 UTC+1, Rafael Mendonça França escreveu:> > If you want to reload the association cache you can pass true as argument. > > s.formats(true).select { |f| f.tag == "original" } > > Will always get what you want. > > Rafael Mendonça França > http://twitter.com/rafaelfranca > https://github.com/rafaelfranca > > > On Tue, Feb 19, 2013 at 12:56 PM, ChuckE <honeyry...@gmail.com<javascript:> > > wrote: > >> Hi, >> >> I came across a certain use case that could need some fine tuning. Let''s >> say I have a song Model. This song is available in many formats. So, the >> song has_many formats (mp3, flac, ...). The song also has the original >> where the other might have been generated from. So, the song has_one >> original. This is my current state of affairs: >> >> class Song < ActiveRecord::Base >> has_many :formats >> has_one :original, class_name: "Format", conditions: { tag: "original" } >> end >> >> So far, so good. Problem is, now I have my original made available in two >> different places, and if I update one, it is not reproduced on the other, >> until I synchronize everything from the database (not to the database). >> >> s = Song.first >> s.formats.select{|f| f.tag == "original" } # original original >> s.original #original original >> s.original = Format.create(.... tag: "original") # changed original >> s.formats.select{|f| f.tag == "original" } # original original (!!) >> s.reload >> s.formats.select{|f| f.tag == "original" } # changed original >> >> And this sucks, specially when I start playing around with validations, I >> end up tucking more than I would like to. >> >> So the question is: how well could one devise such an association which >> is contained somewhere else? Something like: >> >> class Song < ActiveRecord::Base >> >> has_many :formats >> has_one :original, class_name: "Format", conditions: { tag: "original" >> },* on: :formats* >> >> end >> >> And from then on this "has one" would be a proxy to an instance contained >> in an has_many collection. >> >> So, what would speak against such a feature? I''m all hears >> >> -- >> You received this message because you are subscribed to the Google Groups >> "Ruby on Rails: Core" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to rubyonrails-co...@googlegroups.com <javascript:>. >> To post to this group, send email to rubyonra...@googlegroups.com<javascript:> >> . >> Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en >> . >> For more options, visit https://groups.google.com/groups/opt_out. >> >> >> > >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-core+unsubscribe@googlegroups.com. To post to this group, send email to rubyonrails-core@googlegroups.com. Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. For more options, visit https://groups.google.com/groups/opt_out.
Rafael Mendonça França
2013-Feb-19 16:18 UTC
Re: has_one from has_many: when an association can be fetched in more than one place.
Because what is on memory is a cached version of you association. It is cached to avoid unnecessary queries on the database. If you want to invalidate the cache you have to tell Rails to do it. Rafael Mendonça França http://twitter.com/rafaelfranca https://github.com/rafaelfranca On Tue, Feb 19, 2013 at 1:13 PM, ChuckE <honeyryderchuck@gmail.com> wrote:> Thanks for the suggestion, that''s what I meant by tucking stuff. My point > is, stuff is already somewhere right in memory, why couldn''t it be set > right there? I''m exactly trying to avoid the DB roundtrips and the possible > spaghetti code stemming from such a situation. > > Terça-feira, 19 de Fevereiro de 2013 17:04:50 UTC+1, Rafael Mendonça > França escreveu: >> >> If you want to reload the association cache you can pass true as >> argument. >> >> s.formats(true).select { |f| f.tag == "original" } >> >> Will always get what you want. >> >> Rafael Mendonça França >> http://twitter.com/**rafaelfranca <http://twitter.com/rafaelfranca> >> https://github.com/**rafaelfranca <https://github.com/rafaelfranca> >> >> >> On Tue, Feb 19, 2013 at 12:56 PM, ChuckE <honeyry...@gmail.com> wrote: >> >>> Hi, >>> >>> I came across a certain use case that could need some fine tuning. Let''s >>> say I have a song Model. This song is available in many formats. So, the >>> song has_many formats (mp3, flac, ...). The song also has the original >>> where the other might have been generated from. So, the song has_one >>> original. This is my current state of affairs: >>> >>> class Song < ActiveRecord::Base >>> has_many :formats >>> has_one :original, class_name: "Format", conditions: { tag: "original" >>> } >>> end >>> >>> So far, so good. Problem is, now I have my original made available in >>> two different places, and if I update one, it is not reproduced on the >>> other, until I synchronize everything from the database (not to the >>> database). >>> >>> s = Song.first >>> s.formats.select{|f| f.tag == "original" } # original original >>> s.original #original original >>> s.original = Format.create(.... tag: "original") # changed original >>> s.formats.select{|f| f.tag == "original" } # original original (!!) >>> s.reload >>> s.formats.select{|f| f.tag == "original" } # changed original >>> >>> And this sucks, specially when I start playing around with validations, >>> I end up tucking more than I would like to. >>> >>> So the question is: how well could one devise such an association which >>> is contained somewhere else? Something like: >>> >>> class Song < ActiveRecord::Base >>> >>> has_many :formats >>> has_one :original, class_name: "Format", conditions: { tag: "original" >>> },* on: :formats* >>> >>> end >>> >>> And from then on this "has one" would be a proxy to an instance >>> contained in an has_many collection. >>> >>> So, what would speak against such a feature? I''m all hears >>> >>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Ruby on Rails: Core" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to rubyonrails-co...@**googlegroups.com. >>> To post to this group, send email to rubyonra...@googlegroups.**com. >>> >>> Visit this group at http://groups.google.com/** >>> group/rubyonrails-core?hl=en<http://groups.google.com/group/rubyonrails-core?hl=en> >>> . >>> For more options, visit https://groups.google.com/**groups/opt_out<https://groups.google.com/groups/opt_out> >>> . >>> >>> >>> >> >> -- > You received this message because you are subscribed to the Google Groups > "Ruby on Rails: Core" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to rubyonrails-core+unsubscribe@googlegroups.com. > To post to this group, send email to rubyonrails-core@googlegroups.com. > Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. > For more options, visit https://groups.google.com/groups/opt_out. > > >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-core+unsubscribe@googlegroups.com. To post to this group, send email to rubyonrails-core@googlegroups.com. Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. For more options, visit https://groups.google.com/groups/opt_out.
ChuckE
2013-Feb-19 16:53 UTC
Re: has_one from has_many: when an association can be fetched in more than one place.
Yes, explicitly instead of implicitly. I agree with you, and the purpose here was not to discuss the role of the model layer in Rails. I wanted to discuss the possible implementation, and using your abstraction, of an association as a cached version of a cached version of a DB row state, in which the cached versions would communicate with one another through observation, instead of two cached versions of the same DB state which can theoretically update the DB state concurrently in an optimistic locking model in which the last update wins and we all lose. Terça-feira, 19 de Fevereiro de 2013 17:18:09 UTC+1, Rafael Mendonça França escreveu:> > Because what is on memory is a cached version of you association. It is > cached to avoid unnecessary queries on the database. > > If you want to invalidate the cache you have to tell Rails to do it. > > Rafael Mendonça França > http://twitter.com/rafaelfranca > https://github.com/rafaelfranca > > > On Tue, Feb 19, 2013 at 1:13 PM, ChuckE <honeyry...@gmail.com<javascript:> > > wrote: > >> Thanks for the suggestion, that''s what I meant by tucking stuff. My point >> is, stuff is already somewhere right in memory, why couldn''t it be set >> right there? I''m exactly trying to avoid the DB roundtrips and the possible >> spaghetti code stemming from such a situation. >> >> Terça-feira, 19 de Fevereiro de 2013 17:04:50 UTC+1, Rafael Mendonça >> França escreveu: >>> >>> If you want to reload the association cache you can pass true as >>> argument. >>> >>> s.formats(true).select { |f| f.tag == "original" } >>> >>> Will always get what you want. >>> >>> Rafael Mendonça França >>> http://twitter.com/**rafaelfranca <http://twitter.com/rafaelfranca> >>> https://github.com/**rafaelfranca <https://github.com/rafaelfranca> >>> >>> >>> On Tue, Feb 19, 2013 at 12:56 PM, ChuckE <honeyry...@gmail.com> wrote: >>> >>>> Hi, >>>> >>>> I came across a certain use case that could need some fine tuning. >>>> Let''s say I have a song Model. This song is available in many formats. So, >>>> the song has_many formats (mp3, flac, ...). The song also has the original >>>> where the other might have been generated from. So, the song has_one >>>> original. This is my current state of affairs: >>>> >>>> class Song < ActiveRecord::Base >>>> has_many :formats >>>> has_one :original, class_name: "Format", conditions: { tag: >>>> "original" } >>>> end >>>> >>>> So far, so good. Problem is, now I have my original made available in >>>> two different places, and if I update one, it is not reproduced on the >>>> other, until I synchronize everything from the database (not to the >>>> database). >>>> >>>> s = Song.first >>>> s.formats.select{|f| f.tag == "original" } # original original >>>> s.original #original original >>>> s.original = Format.create(.... tag: "original") # changed original >>>> s.formats.select{|f| f.tag == "original" } # original original (!!) >>>> s.reload >>>> s.formats.select{|f| f.tag == "original" } # changed original >>>> >>>> And this sucks, specially when I start playing around with validations, >>>> I end up tucking more than I would like to. >>>> >>>> So the question is: how well could one devise such an association which >>>> is contained somewhere else? Something like: >>>> >>>> class Song < ActiveRecord::Base >>>> >>>> has_many :formats >>>> has_one :original, class_name: "Format", conditions: { tag: >>>> "original" },* on: :formats* >>>> >>>> end >>>> >>>> And from then on this "has one" would be a proxy to an instance >>>> contained in an has_many collection. >>>> >>>> So, what would speak against such a feature? I''m all hears >>>> >>>> >>>> -- >>>> You received this message because you are subscribed to the Google >>>> Groups "Ruby on Rails: Core" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to rubyonrails-co...@**googlegroups.com. >>>> To post to this group, send email to rubyonra...@googlegroups.**com. >>>> >>>> Visit this group at http://groups.google.com/** >>>> group/rubyonrails-core?hl=en<http://groups.google.com/group/rubyonrails-core?hl=en> >>>> . >>>> For more options, visit https://groups.google.com/**groups/opt_out<https://groups.google.com/groups/opt_out> >>>> . >>>> >>>> >>>> >>> >>> -- >> You received this message because you are subscribed to the Google Groups >> "Ruby on Rails: Core" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to rubyonrails-co...@googlegroups.com <javascript:>. >> To post to this group, send email to rubyonra...@googlegroups.com<javascript:> >> . >> Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en >> . >> For more options, visit https://groups.google.com/groups/opt_out. >> >> >> > >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-core+unsubscribe@googlegroups.com. To post to this group, send email to rubyonrails-core@googlegroups.com. Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. For more options, visit https://groups.google.com/groups/opt_out.
Rafael Mendonça França
2013-Feb-19 16:59 UTC
Re: has_one from has_many: when an association can be fetched in more than one place.
I *think* if you use the :through option in the has_one association will do what you want. Rafael Mendonça França http://twitter.com/rafaelfranca https://github.com/rafaelfranca On Tue, Feb 19, 2013 at 1:53 PM, ChuckE <honeyryderchuck@gmail.com> wrote:> Yes, explicitly instead of implicitly. I agree with you, and the purpose > here was not to discuss the role of the model layer in Rails. I wanted to > discuss the possible implementation, and using your abstraction, of an > association as a cached version of a cached version of a DB row state, in > which the cached versions would communicate with one another through > observation, instead of two cached versions of the same DB state which can > theoretically update the DB state concurrently in an optimistic locking > model in which the last update wins and we all lose. > > Terça-feira, 19 de Fevereiro de 2013 17:18:09 UTC+1, Rafael Mendonça > França escreveu: >> >> Because what is on memory is a cached version of you association. It is >> cached to avoid unnecessary queries on the database. >> >> If you want to invalidate the cache you have to tell Rails to do it. >> >> Rafael Mendonça França >> http://twitter.com/**rafaelfranca <http://twitter.com/rafaelfranca> >> https://github.com/**rafaelfranca <https://github.com/rafaelfranca> >> >> >> On Tue, Feb 19, 2013 at 1:13 PM, ChuckE <honeyry...@gmail.com> wrote: >> >>> Thanks for the suggestion, that''s what I meant by tucking stuff. My >>> point is, stuff is already somewhere right in memory, why couldn''t it be >>> set right there? I''m exactly trying to avoid the DB roundtrips and the >>> possible spaghetti code stemming from such a situation. >>> >>> Terça-feira, 19 de Fevereiro de 2013 17:04:50 UTC+1, Rafael Mendonça >>> França escreveu: >>>> >>>> If you want to reload the association cache you can pass true as >>>> argument. >>>> >>>> s.formats(true).select { |f| f.tag == "original" } >>>> >>>> Will always get what you want. >>>> >>>> Rafael Mendonça França >>>> http://twitter.com/**rafaelfranc**a <http://twitter.com/rafaelfranca> >>>> https://github.com/**rafaelfranc**a <https://github.com/rafaelfranca> >>>> >>>> >>>> On Tue, Feb 19, 2013 at 12:56 PM, ChuckE <honeyry...@gmail.com> wrote: >>>> >>>>> Hi, >>>>> >>>>> I came across a certain use case that could need some fine tuning. >>>>> Let''s say I have a song Model. This song is available in many formats. So, >>>>> the song has_many formats (mp3, flac, ...). The song also has the original >>>>> where the other might have been generated from. So, the song has_one >>>>> original. This is my current state of affairs: >>>>> >>>>> class Song < ActiveRecord::Base >>>>> has_many :formats >>>>> has_one :original, class_name: "Format", conditions: { tag: >>>>> "original" } >>>>> end >>>>> >>>>> So far, so good. Problem is, now I have my original made available in >>>>> two different places, and if I update one, it is not reproduced on the >>>>> other, until I synchronize everything from the database (not to the >>>>> database). >>>>> >>>>> s = Song.first >>>>> s.formats.select{|f| f.tag == "original" } # original original >>>>> s.original #original original >>>>> s.original = Format.create(.... tag: "original") # changed original >>>>> s.formats.select{|f| f.tag == "original" } # original original (!!) >>>>> s.reload >>>>> s.formats.select{|f| f.tag == "original" } # changed original >>>>> >>>>> And this sucks, specially when I start playing around with >>>>> validations, I end up tucking more than I would like to. >>>>> >>>>> So the question is: how well could one devise such an association >>>>> which is contained somewhere else? Something like: >>>>> >>>>> class Song < ActiveRecord::Base >>>>> >>>>> has_many :formats >>>>> has_one :original, class_name: "Format", conditions: { tag: >>>>> "original" },* on: :formats* >>>>> >>>>> end >>>>> >>>>> And from then on this "has one" would be a proxy to an instance >>>>> contained in an has_many collection. >>>>> >>>>> So, what would speak against such a feature? I''m all hears >>>>> >>>>> >>>>> -- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "Ruby on Rails: Core" group. >>>>> To unsubscribe from this group and stop receiving emails from it, send >>>>> an email to rubyonrails-co...@**googlegroups**.com. >>>>> To post to this group, send email to rubyonra...@googlegroups.**com. >>>>> >>>>> Visit this group at http://groups.google.com/**group** >>>>> /rubyonrails-core?hl=en<http://groups.google.com/group/rubyonrails-core?hl=en> >>>>> . >>>>> For more options, visit https://groups.google.com/**grou**ps/opt_out<https://groups.google.com/groups/opt_out> >>>>> . >>>>> >>>>> >>>>> >>>> >>>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Ruby on Rails: Core" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to rubyonrails-co...@**googlegroups.com. >>> To post to this group, send email to rubyonra...@googlegroups.**com. >>> Visit this group at http://groups.google.com/** >>> group/rubyonrails-core?hl=en<http://groups.google.com/group/rubyonrails-core?hl=en> >>> . >>> For more options, visit https://groups.google.com/**groups/opt_out<https://groups.google.com/groups/opt_out> >>> . >>> >>> >>> >> >> -- > You received this message because you are subscribed to the Google Groups > "Ruby on Rails: Core" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to rubyonrails-core+unsubscribe@googlegroups.com. > To post to this group, send email to rubyonrails-core@googlegroups.com. > Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. > For more options, visit https://groups.google.com/groups/opt_out. > > >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-core+unsubscribe@googlegroups.com. To post to this group, send email to rubyonrails-core@googlegroups.com. Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. For more options, visit https://groups.google.com/groups/opt_out.
Josh Susser
2013-Feb-19 17:07 UTC
Re: has_one from has_many: when an association can be fetched in more than one place.
You are looking at one particular case where the IdentityMap[1] pattern would be a solution. There are plenty of other cases, including reciprocal associations (which is currently partly addressed by the :inverse_of option on association). There was a Ruby Summer of Code project for doing an IdentityMap in Rails 2 or 3 years ago, but it turned out to be unworkable. I don''t know if that was just the particular implementation, or if there are more fundamental issues that made that approach incompatible. [1] http://martinfowler.com/eaaCatalog/identityMap.html On Tue, Feb 19, 2013 at 8:53 AM, ChuckE <honeyryderchuck@gmail.com> wrote:> Yes, explicitly instead of implicitly. I agree with you, and the purpose > here was not to discuss the role of the model layer in Rails. I wanted to > discuss the possible implementation, and using your abstraction, of an > association as a cached version of a cached version of a DB row state, in > which the cached versions would communicate with one another through > observation, instead of two cached versions of the same DB state which can > theoretically update the DB state concurrently in an optimistic locking > model in which the last update wins and we all lose. > > Terça-feira, 19 de Fevereiro de 2013 17:18:09 UTC+1, Rafael Mendonça > França escreveu: >> >> Because what is on memory is a cached version of you association. It is >> cached to avoid unnecessary queries on the database. >> >> If you want to invalidate the cache you have to tell Rails to do it. >> >> Rafael Mendonça França >> http://twitter.com/**rafaelfranca <http://twitter.com/rafaelfranca> >> https://github.com/**rafaelfranca <https://github.com/rafaelfranca> >> >> >> On Tue, Feb 19, 2013 at 1:13 PM, ChuckE <honeyry...@gmail.com> wrote: >> >>> Thanks for the suggestion, that''s what I meant by tucking stuff. My >>> point is, stuff is already somewhere right in memory, why couldn''t it be >>> set right there? I''m exactly trying to avoid the DB roundtrips and the >>> possible spaghetti code stemming from such a situation. >>> >>> Terça-feira, 19 de Fevereiro de 2013 17:04:50 UTC+1, Rafael Mendonça >>> França escreveu: >>>> >>>> If you want to reload the association cache you can pass true as >>>> argument. >>>> >>>> s.formats(true).select { |f| f.tag == "original" } >>>> >>>> Will always get what you want. >>>> >>>> Rafael Mendonça França >>>> http://twitter.com/**rafaelfranc**a <http://twitter.com/rafaelfranca> >>>> https://github.com/**rafaelfranc**a <https://github.com/rafaelfranca> >>>> >>>> >>>> On Tue, Feb 19, 2013 at 12:56 PM, ChuckE <honeyry...@gmail.com> wrote: >>>> >>>>> Hi, >>>>> >>>>> I came across a certain use case that could need some fine tuning. >>>>> Let''s say I have a song Model. This song is available in many formats. So, >>>>> the song has_many formats (mp3, flac, ...). The song also has the original >>>>> where the other might have been generated from. So, the song has_one >>>>> original. This is my current state of affairs: >>>>> >>>>> class Song < ActiveRecord::Base >>>>> has_many :formats >>>>> has_one :original, class_name: "Format", conditions: { tag: >>>>> "original" } >>>>> end >>>>> >>>>> So far, so good. Problem is, now I have my original made available in >>>>> two different places, and if I update one, it is not reproduced on the >>>>> other, until I synchronize everything from the database (not to the >>>>> database). >>>>> >>>>> s = Song.first >>>>> s.formats.select{|f| f.tag == "original" } # original original >>>>> s.original #original original >>>>> s.original = Format.create(.... tag: "original") # changed original >>>>> s.formats.select{|f| f.tag == "original" } # original original (!!) >>>>> s.reload >>>>> s.formats.select{|f| f.tag == "original" } # changed original >>>>> >>>>> And this sucks, specially when I start playing around with >>>>> validations, I end up tucking more than I would like to. >>>>> >>>>> So the question is: how well could one devise such an association >>>>> which is contained somewhere else? Something like: >>>>> >>>>> class Song < ActiveRecord::Base >>>>> >>>>> has_many :formats >>>>> has_one :original, class_name: "Format", conditions: { tag: >>>>> "original" },* on: :formats* >>>>> >>>>> end >>>>> >>>>> And from then on this "has one" would be a proxy to an instance >>>>> contained in an has_many collection. >>>>> >>>>> So, what would speak against such a feature? I''m all hears >>>>> >>>>> >>>>> -- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "Ruby on Rails: Core" group. >>>>> To unsubscribe from this group and stop receiving emails from it, send >>>>> an email to rubyonrails-co...@**googlegroups**.com. >>>>> To post to this group, send email to rubyonra...@googlegroups.**com. >>>>> >>>>> Visit this group at http://groups.google.com/**group** >>>>> /rubyonrails-core?hl=en<http://groups.google.com/group/rubyonrails-core?hl=en> >>>>> . >>>>> For more options, visit https://groups.google.com/**grou**ps/opt_out<https://groups.google.com/groups/opt_out> >>>>> . >>>>> >>>>> >>>>> >>>> >>>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Ruby on Rails: Core" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to rubyonrails-co...@**googlegroups.com. >>> To post to this group, send email to rubyonra...@googlegroups.**com. >>> Visit this group at http://groups.google.com/** >>> group/rubyonrails-core?hl=en<http://groups.google.com/group/rubyonrails-core?hl=en> >>> . >>> For more options, visit https://groups.google.com/**groups/opt_out<https://groups.google.com/groups/opt_out> >>> . >>> >>> >>> >> >> -- > You received this message because you are subscribed to the Google Groups > "Ruby on Rails: Core" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to rubyonrails-core+unsubscribe@googlegroups.com. > To post to this group, send email to rubyonrails-core@googlegroups.com. > Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. > For more options, visit https://groups.google.com/groups/opt_out. > > >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-core+unsubscribe@googlegroups.com. To post to this group, send email to rubyonrails-core@googlegroups.com. Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. For more options, visit https://groups.google.com/groups/opt_out.
ChuckE
2013-Feb-20 14:42 UTC
Re: has_one from has_many: when an association can be fetched in more than one place.
@Rafael, nop, that does not work, and has nothing to do with what I''m trying to achieve. :through option checks for an association with that name in the refered :through association. Explaining with my example: :through tells me each format has an original. I''m saying that one of the formats is the original. @John Susser, that''s actually quite interesting. I don''t know the stand of things concerning the IdentityMap implementation on ActiveRecord. Can you lead me to relevant documentation about the issue? (Assume that I''ll be googling about it as well :) ). Terça-feira, 19 de Fevereiro de 2013 17:59:23 UTC+1, Rafael Mendonça França escreveu:> > I *think* if you use the :through option in the has_one association will > do what you want. > > Rafael Mendonça França > http://twitter.com/rafaelfranca > https://github.com/rafaelfranca > > > On Tue, Feb 19, 2013 at 1:53 PM, ChuckE <honeyry...@gmail.com<javascript:> > > wrote: > >> Yes, explicitly instead of implicitly. I agree with you, and the purpose >> here was not to discuss the role of the model layer in Rails. I wanted to >> discuss the possible implementation, and using your abstraction, of an >> association as a cached version of a cached version of a DB row state, in >> which the cached versions would communicate with one another through >> observation, instead of two cached versions of the same DB state which can >> theoretically update the DB state concurrently in an optimistic locking >> model in which the last update wins and we all lose. >> >> Terça-feira, 19 de Fevereiro de 2013 17:18:09 UTC+1, Rafael Mendonça >> França escreveu: >>> >>> Because what is on memory is a cached version of you association. It is >>> cached to avoid unnecessary queries on the database. >>> >>> If you want to invalidate the cache you have to tell Rails to do it. >>> >>> Rafael Mendonça França >>> http://twitter.com/**rafaelfranca <http://twitter.com/rafaelfranca> >>> https://github.com/**rafaelfranca <https://github.com/rafaelfranca> >>> >>> >>> On Tue, Feb 19, 2013 at 1:13 PM, ChuckE <honeyry...@gmail.com> wrote: >>> >>>> Thanks for the suggestion, that''s what I meant by tucking stuff. My >>>> point is, stuff is already somewhere right in memory, why couldn''t it be >>>> set right there? I''m exactly trying to avoid the DB roundtrips and the >>>> possible spaghetti code stemming from such a situation. >>>> >>>> Terça-feira, 19 de Fevereiro de 2013 17:04:50 UTC+1, Rafael Mendonça >>>> França escreveu: >>>>> >>>>> If you want to reload the association cache you can pass true as >>>>> argument. >>>>> >>>>> s.formats(true).select { |f| f.tag == "original" } >>>>> >>>>> Will always get what you want. >>>>> >>>>> Rafael Mendonça França >>>>> http://twitter.com/**rafaelfranc**a <http://twitter.com/rafaelfranca> >>>>> https://github.com/**rafaelfranc**a <https://github.com/rafaelfranca> >>>>> >>>>> >>>>> On Tue, Feb 19, 2013 at 12:56 PM, ChuckE <honeyry...@gmail.com> wrote: >>>>> >>>>>> Hi, >>>>>> >>>>>> I came across a certain use case that could need some fine tuning. >>>>>> Let''s say I have a song Model. This song is available in many formats. So, >>>>>> the song has_many formats (mp3, flac, ...). The song also has the original >>>>>> where the other might have been generated from. So, the song has_one >>>>>> original. This is my current state of affairs: >>>>>> >>>>>> class Song < ActiveRecord::Base >>>>>> has_many :formats >>>>>> has_one :original, class_name: "Format", conditions: { tag: >>>>>> "original" } >>>>>> end >>>>>> >>>>>> So far, so good. Problem is, now I have my original made available in >>>>>> two different places, and if I update one, it is not reproduced on the >>>>>> other, until I synchronize everything from the database (not to the >>>>>> database). >>>>>> >>>>>> s = Song.first >>>>>> s.formats.select{|f| f.tag == "original" } # original original >>>>>> s.original #original original >>>>>> s.original = Format.create(.... tag: "original") # changed original >>>>>> s.formats.select{|f| f.tag == "original" } # original original (!!) >>>>>> s.reload >>>>>> s.formats.select{|f| f.tag == "original" } # changed original >>>>>> >>>>>> And this sucks, specially when I start playing around with >>>>>> validations, I end up tucking more than I would like to. >>>>>> >>>>>> So the question is: how well could one devise such an association >>>>>> which is contained somewhere else? Something like: >>>>>> >>>>>> class Song < ActiveRecord::Base >>>>>> >>>>>> has_many :formats >>>>>> has_one :original, class_name: "Format", conditions: { tag: >>>>>> "original" },* on: :formats* >>>>>> >>>>>> end >>>>>> >>>>>> And from then on this "has one" would be a proxy to an instance >>>>>> contained in an has_many collection. >>>>>> >>>>>> So, what would speak against such a feature? I''m all hears >>>>>> >>>>>> >>>>>> -- >>>>>> You received this message because you are subscribed to the Google >>>>>> Groups "Ruby on Rails: Core" group. >>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>> send an email to rubyonrails-co...@**googlegroups**.com. >>>>>> To post to this group, send email to rubyonra...@googlegroups.**com. >>>>>> >>>>>> Visit this group at http://groups.google.com/**group** >>>>>> /rubyonrails-core?hl=en<http://groups.google.com/group/rubyonrails-core?hl=en> >>>>>> . >>>>>> For more options, visit https://groups.google.com/**grou**ps/opt_out<https://groups.google.com/groups/opt_out> >>>>>> . >>>>>> >>>>>> >>>>>> >>>>> >>>>> -- >>>> You received this message because you are subscribed to the Google >>>> Groups "Ruby on Rails: Core" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to rubyonrails-co...@**googlegroups.com. >>>> To post to this group, send email to rubyonra...@googlegroups.**com. >>>> Visit this group at http://groups.google.com/** >>>> group/rubyonrails-core?hl=en<http://groups.google.com/group/rubyonrails-core?hl=en> >>>> . >>>> For more options, visit https://groups.google.com/**groups/opt_out<https://groups.google.com/groups/opt_out> >>>> . >>>> >>>> >>>> >>> >>> -- >> You received this message because you are subscribed to the Google Groups >> "Ruby on Rails: Core" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to rubyonrails-co...@googlegroups.com <javascript:>. >> To post to this group, send email to rubyonra...@googlegroups.com<javascript:> >> . >> Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en >> . >> For more options, visit https://groups.google.com/groups/opt_out. >> >> >> > >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-core+unsubscribe@googlegroups.com. To post to this group, send email to rubyonrails-core@googlegroups.com. Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. For more options, visit https://groups.google.com/groups/opt_out.