0

New to Rails development. I'm creating an application that has users, artists and tags associated with artists applied by users. Here are the two models for artists and tags:

class Artist < ApplicationRecord
  has_and_belongs_to_many :tags
end
class Tag < ApplicationRecord
  has_and_belongs_to_many :artists
end

A user has the option to either create a new tag, in which case we create tag record in the tags table, and an association record between the newly created tag and the artist it was created for. The second option is clicking an existing tag for that artist, in this case I would like to increase the count in the association table for that tag for that artist, but Active Record doesn't index join tables so while I can create add a count column to the join table, I can't access and modify that column. But I can do this in SQL:

UPDATE Artists_Tags
    SET count = count + 1
    WHERE artist_id=artistid AND tag_id=tagid;

Table in schema.rb:

create_table "artists_tags", id: false, force: :cascade do |t|
  t.bigint "artist_id", null: false
  t.bigint "tag_id", null: false
  t.integer "count", default: 1, null: false
  t.index ["artist_id", "tag_id"], name: 
"index_artists_tags_on_artist_id_and_tag_id"
end

But I can't put this SQL query into my controller method to update count. Am I approaching this problem wrong? I'd appreciate any tips. Note: Increasing count is used to display the most applied tag to that artist.

1 Answers1

2

I guess the problem is that you're using HABTM association, and in that case you can't have any additional information about the relationship (see more about that in http://blog.flatironschool.com/why-you-dont-need-has-and-belongs-to-many/). I would change the way to do that many-to-many relationship using has_many :through with a new model, ArtistTag. Would be something like:

rails g model ArtistTag artist:references tag:references tag_count:integer

And would change the models to:

class Artist < ApplicationRecord
  has_many :artist_tags
  has_many :tags, through: :artist_tags
end

class Tag < ApplicationRecord
  has_many :artist_tags
  has_many :artists, through: :artist_tags
end

Like that, you could do something like (using active record):

artist_tag = artist.artist_tags.find_by_tag_id(your_tag_id)
artist_tag.update(tag_count: artist_tag.tag_count + 1)

I personally think this is a better approach and could solve your problem. Hope this helps and good luck!

Ronan Lopes
  • 3,320
  • 4
  • 25
  • 51
  • That makes a lot of sense. I've been confused about using HATBM vs HMT, but since I'm doing more than storing ids of the associated records, association through model that has count is more appropriate, and I should be able to use the same model to keep track of which user submitted which tag, if I understood correctly. Thanks for the answer! – Seely Sassage May 09 '18 at 18:23
  • Yeah, you can put any additional information about the relationship in your join model (also validations and callbacks). HABTM has a shorter syntax but it can be a problem as your application grows. Glad to help! – Ronan Lopes May 09 '18 at 18:25