1

I have two models

Article

class Article < ActiveRecord::Base
  mount_uploader :photo, ImageUploader
  has_many :comments
  has_many :article_tags
  has_many :tags, :through => :article_tags
  belongs_to :category

  validates :title, presence: true
  validates :text, presence: true
end

ArticleTag

class ArticleTag < ActiveRecord::Base
  belongs_to :article
  belongs_to :tag
end

Tag

class Tag < ActiveRecord::Base
 has_many :article_tags
 has_many :articles, :through => :article_tags
end

This is how i am getting the tags in the .

@article = params[:article]
@tags = params[:tag_ids]

Now the real problem comes with posting the article into the articles table as well as the posting the tags associated with the various articles into the article_tags table.

Update

I am using simple_form_for gem which allows me to create a multi-select in bootstrap using the association method so the problem is not getting the tags into the form but rather posting them into the database(creating new rows for the article_tags). I want to be able to retrieve them via @article.article_tags. This is what is was trying but i don't know if it is right.

@article_params = params[:article]
  article_params[:tag_ids].each do |tag|
  @article_tag =    @article.article_tags.build('article_id'=>@article.id,'tag_id'=>tag)
      @article_tag.save
end

def article_params
params.require(:article).permit(:title,:category_id,:text,     :photo,:tag_ids => [])
end

This has to be done as the article is being created it's like posting to two tables at the same time in the same method ie the articles and article_tags tables.

2 Answers 2

1

You can use the concept of nested attributes in rails to solve this.

You can find an example/Explanation on this rails cast

When you use nested attributes, you won't need to separately get the articles and tags in your controller, and then worry about saving these, rails will automatically handle that.

Sign up to request clarification or add additional context in comments.

Comments

0

You have two options:

  1. If you want to associate existing tags to the new article, you'll just need to populate tag_ids
  2. If you want to create new tags, you'll have to use accepts_nested_attributes_for

Existing Tags

Adding existing tags to an article is simple:

#app/models/article.rb
class Article < ActiveRecord::Base
  has_many :article_tags
  has_many :tags, through: :article_tags

  validates :title, :text, presence: true #-> declare multiple validations on same line
end

#app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
   def create
      @article = Article.new article_params
      @article.save
   end

   private

   def article_params
      params.require(:article).permit(tag_ids: [])
   end
end

Use the collection_singular_ids attribute to assign "join" records in your parent:

#app/views/articles/new.html.erb
<%= form_for @article do |f| %>
   <%= f.collection_select :tag_ids, Tag.all, :id, :name %>
   <%= f.submit %>
<% end %> 

This will allocate any tag to your new article, however, it will not allow you to create new tags.


New Tags

If you wished to create new tags with your article, you'll have to use accepts_nested_attributes_for with fields_for:

#app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
   def new
     @article = Article.new
     @article.tags.build
   end

   def create
     @article = Article.new article_params
     @article.save
   end

   private

   def article_params
     params.require(:article).permit(tags_attributes: [:name])
   end
end

#app/views/articles/new.html.erb
<%= form_for @article do |f| %>
   <%= f.fields_for :tags do |t| %>
      <%= t.text_field :name %>
   <% end %>
   <%= f.submit %>
<% end %>

This will create new tags an automatically associate them with your new article.

1 Comment

Updated the question

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.