user504909
user504909

Reputation: 9549

How to use join to select many to many relationship model in ruby on rails4?

My data model is fellows, the note and hashtag's relationship is many to many

class Note < ActiveRecord::Base

  attr_accessible :title
  attr_accessible :content
  attr_accessible :created_at
  default_scope -> { order(created_at: :desc) }

  has_and_belongs_to_many :hashtags
end

class Hashtag < ActiveRecord::Base
  attr_accessible :name
  has_and_belongs_to_many :notes
end

class NoteHashtag < ActiveRecord::Base
  t.belongs_to :note, index: true
  t.belongs_to :hashtag, index: true
end

I want to inquire the sql like:

 select Note.* from Note inner join NoteHashtag on Note.id=NoteHashtag.note inner join Hashtag on NoteHastag.hashtag=Hashtag.id where Hashtag.name="test"

How to convert the sql into the datamodel operation in ruby on rails4?

I try to use the:

@note=Note.joins(:hashtag).where(name: "test")

and the error is:

ActionView::Template::Error (Association named 'hashtag' was not found on Note;perhaps you misspelled it?):

Upvotes: 1

Views: 93

Answers (3)

bo-oz
bo-oz

Reputation: 2872

Why don't you address this relationship originating from the proper model? Define your models like this:

class Note < ActiveRecord::Base
  ...
  has_many :note_hashtags
  has_many :hashtags, through: :note_hashtags
end

class Hashtag < ActiveRecord::Base
  attr_accessible :name
  has_many :note_hashtags
  has_many :notes through: :notes_hashtags
end

class NoteHashtag < ActiveRecord::Base
  belongs_to :note
  belongs_to :hashtag
end

And then query like this:

Hashtag.where(name: 'Test').notes

Upvotes: 0

user3506853
user3506853

Reputation: 814

You can get records from many to many relationship by doing this:-

@note = Note.joins(:hashtags).where('hashtags.name' => 'test')

Upvotes: 0

Ray Baxter
Ray Baxter

Reputation: 3200

You need has_many :through associations if you are going to explicitly define the join model NoteHashtag. If you delete that model, you can do @notes=Note.joins(:hashtag).where(name: "test") and ActiveRecord will generate the query you are expecting.

Otherwise you could do

class Note < ActiveRecord::Base
  ...
  has_many :note_hashtags
  has_many :hashtags, through: :note_hash_tags
end

class Hashtag < ActiveRecord::Base
  attr_accessible :name
end

class NoteHashtag < ActiveRecord::Base
  belongs_to :note
end

Then @notes = Note.joins(:note_hashtags).joins(:hash_tags).where(name: "test) would work.

Note that both of these will return more than one note.

Upvotes: 1

Related Questions