ruby-on-railsrubyruby-on-rails-4acts-as-taggable

Trouble saving tags in Ruby on Rails 4 with acts_as_taggable


I'm trying to implement act_as_taggable into my Rails 4 app (upon the microposts model), but the program isn't saving the tags, which therefore aren't viewable. The tables for tags and taggings have been raked and exist in the database, but none of the code I'm implemented seems to save a tag or create a tag when the form is submitted. I followed the steps in this tutorial near exactly, but something doesn't seem to work.

I'm not sure if it's a rails 4 centric problem and/or is connected to the lack of 'attr_accessible' code used in rails. Since the code example doesn't specify adding anything to the microposts table, I can only assume the connection is made elsewhere, but where and how I should fix that I don't know (in microposts_helper.rb perhaps?).

Thanks in advance. Any help is greatly appreciated.

Relevant Code Snippets

Gemfile

...

gem 'acts-as-taggable-on', '~> 2.4.1'

...

microposts.rb

   class Micropost < ActiveRecord::Base     
   belongs_to :user  
   acts_as_taggable   
   acts_as_taggable_on :tags
   ... 
   end

microposts_controller.rb

  before_action :signed_in_user, only: [:create, :destroy]
  before_action :correct_user,   only: :destroy

  def index
    if params[:tag]
      @microposts = Micropost.tagged_with(params[:tag])
    else
      @microposts = Micropost.all
    end
  end

  def create
    @micropost = current_user.microposts.build(micropost_params)
    if @micropost.save
      flash[:success] = "Micropost created!"
      redirect_to current_user
    else
      @feed_items = []
      render 'users/show'
    end
  end

  def destroy
    @micropost.destroy
    redirect_to user_url
  end

  def tagged
    if params[:tag].present? 
      @microposts = Micropost.tagged_with(params[:tag])
    else 
      @microposts = Micropost.postall
    end  
  end

  private

    def micropost_params
      params.require(:micropost).permit(:content)
    end

    def correct_user
      @micropost = current_user.microposts.find_by(id: params[:id])
      redirect_to user_url if @micropost.nil?
    end
end

microposts_helper.rb

module MicropostsHelper
    include ActsAsTaggableOn::TagsHelper
end

_microposts_form.html.rb

<%= form_for(@micropost) do |f| %>
  ...
  <div class="field">
    ...
    <%= f.label :tags %>
    <%= f.text_field :tag_list %>
  </div>
  <%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>

_micropost.erb.html

<li>
  <span class="content"><%= micropost.content %></span>
  <span class="tags">
    <%= micropost.tag_list %>
  </span>
...
</li>

schema.rb

...
create_table "microposts", force: true do |t|
    t.string   "content"
    t.integer  "user_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "microposts", ["user_id", "created_at"], name: "index_microposts_on_user_id_and_created_at"
...
  create_table "taggings", force: true do |t|
    t.integer  "tag_id"
    t.integer  "taggable_id"
    t.string   "taggable_type"
    t.integer  "tagger_id"
    t.string   "tagger_type"
    t.string   "context",       limit: 128
    t.datetime "created_at"
  end

  add_index "taggings", ["tag_id"], name: "index_taggings_on_tag_id"
  add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context"

  create_table "tags", force: true do |t|
    t.string "name"
  end
...

routes.rb

Dev::Application.routes.draw do
    ...
    resources :microposts, only: [:create, :destroy]
    ...
    match 'tagged', to: 'microposts#tagged', :as => 'tagged', via: 'get' 
end

Solution

  • If I understand the question correctly, all you should need to do is, essentially, tell the recommended protection model for params(strong_parameters) about the acts-as-taggable gem. Your already Halfway there with this:

    private
    
        def micropost_params
          params.require(:micropost).permit(:content)
        end
    
        [...]
    end
    

    Just add:

    private
    
        def micropost_params
         params.require(:micropost).permit(:content, :tag_list => [])
        end
    
        [...]
    end
    

    Also, you may want to add one thing to your routes.rb file.. Replace the line:

    resources :microposts, only: [:create, :destroy]
    

    with:

    resources :microposts, only: [:create, :destroy, :tag]
    

    Let me know if these suggestions do the trick. Good luck!