Andre Zimpel
Andre Zimpel

Reputation: 2343

Related content by Association in Ruby (on rails)

Let's say I got questions that have multiple tags on them. I want to be able to find related questions by tags (similar to e.g. iTunes Genius) or find related tags for a tag based on the questions that share them.

Unfortunately, I have no clue how to do that. Especially when it comes to related tags.

I hope somebody can give me a hint! Thanks a lot!

Upvotes: 2

Views: 215

Answers (2)

PinnyM
PinnyM

Reputation: 35533

Accomplishing this efficiently requires a strong understanding of SQL. You can use ActiveRecord to help you build the queries, but the strategy actually lies in the SQL query that will be generated.

Assuming you have Tag and Question models with a QuestionTag join model for a has-many-through relationship:

class Question < ActiveRecord::Base
  has_many :question_tags
  has_many :tags, :through => :question_tags
end

class Tag < ActiveRecord::Base
  has_many :question_tags
  has_many :questions, :through => :question_tags
end

class QuestionTag < ActiveRecord::Base
  belongs_to :question
  belongs_to :tag
end

You can do this to find questions matching a particular tag:

tag = Tag.find_by(name: 'foo')
related_questions = tag.questions

And you can also find questions that match all of a set of tags:

tag_names = ['foo', 'bar', 'baz']
subquery = QuestionTag.joins(:tag).
             select('question_tags.question_id').
             where(tags: {name: tag_names}).
             group('question_tags.question_id').
             having("COUNT(*) = #{tag_names.size}").to_sql
related_questions = Question.where("id IN (#{subquery})")

You can find tags related to a specific tag like this:

tag = Tag.find_by(name: 'foo')
subquery = tag.question_tags.select('question_tags.question_id').to_sql
related_tags = Tag.joins(:question_tags).
                 where("question_tags.question_id IN #{subquery}").
                 where.not(id: tag.id)

Upvotes: 3

Tanner Swenson
Tanner Swenson

Reputation: 76

What you're describing is a many-to-many relationship meaning that questions can have many tags and tags many questions. To do this you must create a third table the consists of tag_ids and question_ids to do this you will need to read up on active record associations. Specifically the has-many-through association. http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association I am currently taking a web development class and we went over this yesterday with students and classes here are our notes. Which walks through creating the models and using them I suspect it would be really helpful for you. https://github.com/wdi-sf-jan-2014/notes/blob/master/active_record_associations/migrations_and_associations.md

Upvotes: 1

Related Questions