Reputation: 16316
I've tried wrapping my mind around how to navigate the associations I want, but I can't seem to figure it out. I'm trying to get all the Posts
given a Tag
. Each Post currently has a title and body text, both of which are represented as TaggedText
. Each TaggedText can have many unique tags — like tagging multiple people/pages in a Facebook post (uniqueness is enforced in the model when saving an instance).
class Tag < ActiveRecord::Base
has_many :tagged_texts, through: :tag_ranges
end
class Post < ActiveRecord::Base
has_many :tagged_texts
end
class TaggedText < ActiveRecord::Base
# Each TaggedText cannot have more than one of each tag
has_many :tags, through: :tag_ranges
belongs_to :post
end
class TagRange < ActiveRecord::Base
# TaggedText cannot have more than one of each tag
belongs_to :tagged_text
belongs_to :tag
end
I tried joining the tables, but I get the error Association named 'tag_ranges' was not found on Post
:
def get_posts_by_tag(tag, page, posts_per_page)
Post
.joins(:tagged_texts)
.joins(:tag_ranges)
.joins(:tags)
.where('tag.id = ?', tag.id)
.uniq
.limit(posts_per_page)
.offset(page - 1)
.to_a
end
What am I missing to get the query to work — or should I restructure my models and associations somehow?
Upvotes: 0
Views: 334
Reputation: 9443
As you error states, you need to add a tag_ranges
association to your Post
model. I've also added a few associations that you may or may not find useful, and one that will simplify your query greatly. Not that your TagRange
class's associations are fine as is.
class Tag < ActiveRecord::Base
has_many :tag_ranges # need this association in order to get tagged_texts
has_many :tagged_texts, through: :tag_ranges
has_many :posts, -> { uniq }, through: :tagged_texts # posts with the given tag
end
class Post < ActiveRecord::Base
has_many :tagged_texts
has_many :tag_ranges, through: :tagged_texts # Post now has association named 'tagged_ranges'
has_many :tags, -> { uniq }, through: :tag_ranges # tags that given post has
end
class TaggedText < ActiveRecord::Base
has_many :tag_ranges # all tag ranges for a tag text
has_many :tags, through: :tag_range
belongs_to :post
end
And now, your query to get all the posts for a tag:
def get_posts_by_tag(tag, page, posts_per_page)
tag.posts.limit(posts_per_page).offset(page - 1).to_a
end
Hopefully this helps!
Upvotes: 1