What is best way to define AR scope for this?

30 views
Skip to first unread message

Michael Bostler

unread,
Sep 4, 2014, 1:46:43 PM9/4/14
to rubyonra...@googlegroups.com
Hi all,


Say I have an article class that has one main tag, but can also be
associated with multiple secondary tags. Something like schema listed
below. How can I implement the scope method below?


Basically I want one method where I can return ALL articles related to a
tag, regardless of whether it is a primary tag relationship or secondary
tag relationship.


Many Thanks!


class Article < ActiveRecord::Base
belongs_to :primary_tag,
:class_name => "Tag"

has_many :secondary_tag_listings

has_many :secondary_tags,
:through => :secondary_tag_listings,
:class_name => "Tag"

scope :all_with_tag, lambda { |tag_name|
# TODO: how to find all with either primary OR secondary tags
# as tag_name?
}
end




class SecondaryTagListings < ActiveRecord::Base
belongs_to :article
belongs_to :tag
end




class Tag < ActiveRecord::Base
has_many :primary_articles,
:class_name => "Article"

has_many :secondary_tag_listings

has_many :secondary_articles,
:through => :secondary_tag_listings,
:class_name => "Article"
end

--
Posted via http://www.ruby-forum.com/.

Colin Law

unread,
Sep 4, 2014, 2:31:37 PM9/4/14
to rubyonra...@googlegroups.com
On 4 September 2014 18:45, Michael Bostler <li...@ruby-forum.com> wrote:
> Hi all,
>
>
> Say I have an article class that has one main tag, but can also be
> associated with multiple secondary tags. Something like schema listed
> below. How can I implement the scope method below?
>
>
> Basically I want one method where I can return ALL articles related to a
> tag, regardless of whether it is a primary tag relationship or secondary
> tag relationship.

You might consider a different schema to that you have shown below, so
that article has_many tags through tag_listings, and in tag_listings
have a flag to indicate a primary tag (or not). Then you get the
primary tag by selecting the tag with that flag set. Then the problem
you have asked about becomes not a problem (which is the best sort).
Still not ideal I know, as you have to guard against the possibility
of inadvertently ending up with multiple primary tags. Perhaps there
is a better solution.

Colin
> --
> 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.
> To post to this group, send email to rubyonra...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/aced24f771ed6171143cc3dae41231b4%40ruby-forum.com.
> For more options, visit https://groups.google.com/d/optout.

Jason Fleetwood-Boldt

unread,
Sep 4, 2014, 3:23:01 PM9/4/14
to rubyonra...@googlegroups.com

Yes, I'd agree with what Colin wrote.

Generally when you try to have one thing join via a join table ( has many through) and the same set of data also join via a belongs_to you get headaches because you're going a bit against the grain of AR.

You could still implement top-level methods to do what you need, but treat all tags as has_many :through in the AR relationship. You could even put a boolean flag into that join table (tag_listings) to indicate "is_primary"



class TagListings
scope :primary, where(:primary => true)
validates_uniqueness :primary, :scope => :article_id # this makes sure there is only 1 primary tag for any given article
end


then from your Article class
@article.tag_listings.primary would get you the primary tag


Then you kind of eliminate the whole dual-model problem

(in my head the code above works, although I haven not tried)

Just giving you this as perspective as an alternative implementation.
> To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/CAL%3D0gLtbVQ4B%2BYMkhyQQiY4bNwwU_oLfO9PgGcKMcO0f6e2pGA%40mail.gmail.com.

Michael Bostler

unread,
Sep 4, 2014, 5:05:14 PM9/4/14
to rubyonra...@googlegroups.com
I see what you mean. Very very helpful. Thanks both so much for the
timely reply!

I think I will go with what you are suggesting and use the boolean flag
on the join table.

Still open to other answers if there are any for sake of curiosity, and
I will add comment if I come across anything else, but I think I will go
with what you said. Much simpler that way.

Thanks again.
Reply all
Reply to author
Forward
0 new messages