On Thursday, 11 December 2014 09:34:12 UTC-6, Jason FB wrote:
>
> Jorge, 
>
> Although I have heard of people using a has_many in some cases when the 
> actual domain model might want a has_one (for example, if your business 
> rule is that the association can have only one at a time and you want to 
> keep the old join table records around with an "expired" field), generally 
> I would recommend using has_one where has_one is appropriate.
>
> has_one shouldn't preclude you from being able to create many-to-many 
> relationships on the table B (or rather from B->C), nor should it disable 
> you from being able to join together multiple eager loading associations in 
> your finder. 
>
> It will however change the naming of your relationships, and it may mean 
> you wind up with some law-of-demeter violations down the road. 
>
> In short, I would recommend using a has_one unless you have a compelling 
> reason to do it with has_many. Two examples of compelling reasons: 1) You 
> want to preserve old join records like I said above, or 2) You will want to 
> change this relationship to many-to-many soon (within 3 months) and you 
> want to plan for that change. 
>
> Take a step back and consider that all Rails associations are doing are 
> adding "utility" methods to your object. How you use them, and how elegant 
> you find the code that is produced, is subjective and at the end of the day 
> still in your court. So use them as best you can to make the most elegant 
> code you can. (Performance considerations aside)
>
> On a side note, I would strongly encourage you to look into Active Model 
> serializer to encapsulate the serialization logic. 
>
> Finally, I would note that one little trick you can do to enforce a 
> has_one-like behavior while actually using has_many is in your join model 
> you could use validates_uniqueness_of to enforce that the join table has 1 
> and only 1 record for a User, like so:
>
> class Memberships
>   belongs_to :user
>   belongs_to :club
>   validates_uniqueness_of :user
> end
>

This won't work, unfortunately - `validates_uniqueness_of` is expecting a 
column name. Swapping in :user_id would, though.

 

>
>
> On Dec 11, 2014, at 1:20 AM, Jorge M. <li...@ruby-forum.com <javascript:>> 
> wrote:
>
> Hello everyone,
>
> I came across with the following case and I was wondering if using a
> has_many through association is a valid solution.
>
> Let's say we have three models: A, B and C. The association between
> model A and model B is a 1 to 1 association with B having a Foreign Key
> to A. Now, the association between B and C is a 1 to many association
> with C having a Foreign Key to B. There's an action where I need to
> create an xml representation of some of the properties of each instance
> in a collection of A objects. Additionally, for each instance of A, I
> need to append to its serialized representation two properties from
> each instance of C. This C instance is associated somehow to the A
> instance through an instance of B.
>
> To create the xml for each instance of A, I will need to iterate over
> each  A instance, for each A instance I will need to read two
> attributes of its corresponding C instances. I want to avoid
> unnecessary trips to the database, therefore, I would like to load the
> A instances together with its somehow corresponding C instances outside
> the loop for the xml creation. I thought to add a has_many through
> association in A like this:
>
> class A < ActiverRecord::Base
>  has_many :cs, through: :b
> end
>
> This is missing a part. The `through` option takes the name of another 
association on the same class. If I'm reading you correctly, your models 
look something like this:

class A < ActiveRecord::Base
  has_one :b
  has_many :cs, through: :b
end

class B < ActiveRecord::Base
  belongs_to :a
  has_many :cs
end

class C < ActiveRecord::Base
  belongs_to :b
end

In this case, you can certainly load As together with the corresponding Cs 
using `include`:

a_ids = [1,2,3,4] # presumably you start with ids, or some other data 
sufficient to find records

all_the_as = A.include(:cs).find(a_ids) # this loads the specified A 
records, together with all their corresponding C records

The above code will load ALL the A records at once. If this isn't a good 
idea (maybe a_ids has 30k ids in it...) then read up on find_each / 
find_in_batches to do things more efficiently.

--Matt Jones

> so later I could do the following:
>
> as = A.all.includes(:cs)
> as.each do |a|
>  xml.prop_1 a.prop_1
>  xml.prop_2 a.prop_2
>  a.cs.each do |c|
>    xml.prop_3 = c.prop_3
>    xml.prop_4 = c.prop_4
>  end
> end
>
> that way, I avoid some unnecessary trips to the database. However, I am
> not sure if this approach is correct. According to the Rails
> documentation, the examples about the has_many :through association
> illustrates its usage when B has a 1 to many association to both A and
> C, in other words, a Foreign Key to A and C respectively. The
> association in my case between A, B and C is different. So I am not
> sure if adding a has_many through in my case would be a valid solution.
> I checked the final result and apparently it's working as expected, but
> I would like to know if I am missing something with this approach.
>
> I am going to look at the rails source code to try to find out if this
> approach is valid or not, but in the meantime any help to confirm if it
> is acceptable to use a has_many through, why and why not, would be
> really appreciated.
>
> -- 
> Posted via http://www.ruby-forum.com/.
>
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Ruby on Rails: Talk" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to rubyonrails-ta...@googlegroups.com <javascript:>.
> To post to this group, send email to rubyonra...@googlegroups.com 
> <javascript:>.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/rubyonrails-talk/894be5e163e3de789c9c732b5a912826%40ruby-forum.com
> .
> For more options, visit https://groups.google.com/d/optout.
>
>
> ----
>
> Jason Fleetwood-Boldt
> te...@datatravels.com <javascript:>
> http://www.jasonfleetwoodboldt.com/writing
>
> All material © Jason Fleetwood-Boldt 2014. Public conversations may be 
> turned into blog posts (original poster information will be made 
> anonymous). Email ja...@datatravels.com <javascript:> with 
> questions/concerns about this.
>
>

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to rubyonrails-talk+unsubscr...@googlegroups.com.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/rubyonrails-talk/655d36a5-e480-4a6c-aa62-3bc8a6604902%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to