Hi I am new to rails and I would like to know what is the best way who save dependent objects in an HBTM relation.
Specifically, I have two classes Post and Tag
class Post < ActiveRecord::Base
has_and_belongs_to_many :tags
end
class Tag < ActiveRecord::Base
has_and_belongs_to_many :posts
end
I have a migration to create the joining table
class AddPostsTagsJoinTable < ActiveRecord::Migration
def self.up
create_table :posts_tags, :id => false do |t|
t.integer :post_id
t.integer :tag_id
end
end
def self.down
drop_table :postss_tags
end
end
All is good up to here
So I have a PostsController from which I handle the creation, updates and deletes for the posts, and I want to encapsulate the Tags so that the creation is via the PostsController... like so:
class PostsController < ApplicationController
#... code removed for brevity
def create
@post = current_user.posts.build(params[:post])
if @post.save
tag_names = params[:post][:tags].strip.split(' ')
tag_names.each do |t|
#see if the tag already exists
tag = Tag.find_by_name(t);
if tag.nil?
@post.tags.create!(:name => t)
else
@post.tags << tag #just create the association
end
end
flash[:success] = "Post created."
redirect_to(user_posts_path(current_user.username))
else
@user = current_user
render 'new'
end
end
end
I am not sure how I should handle the creation of my Tag(s) because if I just call
@post.tags.create!(:name => t)
this will create duplicate records in the Tags table (even when :uniq => true is specified in the model).
So to avoid the duplication I see if a tag is already present and then add it like this
tag = Tag.find_by_name(t);
if tag.nil?
@post.tags.create!(:name => t)
else
@post.tags << tag #just create the association
end
Is this the way it's supposed to be done?
This seems expensive (especially 'cause it's in a loop) so I am wondering if there is another "cleaner" way to do this? (pls forget the DRY'ing up of the action and so on)
Is there a clean way to create my Tags without having to manually check for duplicates?
thank you in advance for your help!