简体   繁体   中英

Rails: Fetch model across many associations

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?

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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM