Created
February 19, 2015 00:13
-
-
Save FluffyCode/90c57e07c3a200ea5b56 to your computer and use it in GitHub Desktop.
acts-as-taggable-on in Rails 4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This information originally found at: | |
http://www.reddit.com/r/rails/comments/2chtgw/tagging_in_rails_4/ | |
Saving it here, in case it helps/is lost in the future. | |
Installation | |
Gemfile | |
gem 'acts-as-taggable-on' | |
terminal | |
bundle install | |
terminal | |
rake acts_as_taggable_on_engine:install:migrations | |
rake db:migrate | |
This creates some tables and doesn't need to know anything specific about your models. | |
The models and concerns for working with these tables (Tag, Tagging, etc) live inside the gem. | |
Model integration | |
app/models/post.rb | |
class Post | |
acts_as_taggable | |
end | |
Now you can do, eg: | |
post = Post.create | |
post.tag_list = "programming, ruby, rails" | |
post.tag_list | |
# => ['programming', 'ruby', 'rails'] | |
#tag_list= takes a string and splits it up, using the resulting substrings to find_or_create Tags, and associate them with the taggable thing (eg, Post), through Taggings. You don't need to know this. | |
The important thing is that, with #tag_list= we can manage tags via a comma-separated-list in a text field in a form. | |
Controller integration | |
app/controllers/posts_controller.rb | |
class PostsController < ApplicationController | |
def create | |
@post = Post.create(post_params) | |
redirect_to @post | |
end | |
def post_params | |
params.require(:post).permit(:title, :body, :tag_list) | |
end | |
end | |
This is assuming you're trying to tag an existing Post model with title and body fields, web-accessible through an existing PostsController, with index, show, new, etc. methods. | |
Substitute your own, the important machinery here is whitelisting tag_list from the params. | |
Form integration | |
app/views/posts/_form.html.erb | |
<%= form_for post do |f| %> | |
<%= f.text_field :title %> | |
<%= f.text_area :body %> | |
<%= f.text_field :tag_list %> | |
<%= f.submit %> | |
<% end %> | |
Let me know if you don't know how to use this partial to do new/edit, and I'll elaborate. | |
Now you can create tags for stuff. How about displaying them? Couple options, I'll go through the most explicit (a TagsController with index and show actions), but they can be rolled up into other controllers/actions. | |
Controller | |
config/routes.rb | |
Rails.application.routes.draw do | |
resources :posts | |
resources :tags, only: [:index, :show] | |
end | |
app/controllers/tags_controller.rb | |
class TagsController < ApplicationController | |
def index | |
@tags = ActsAsTaggableOn::Tag.all | |
end | |
def show | |
@tag = ActsAsTaggableOn::Tag.find(params[:id]) | |
@posts = Post.tagged_with(@tag.name) | |
end | |
end | |
It's unfortunate we have to do this slightly awkward workaround with Post.tagged_with(@tag.name) in tags#show. The ActsAsTaggableOn::Tag model does not have a built-in relationship with its taggable types (this is a necessary consequence of some polymorphism which we're not using here). We could add one for Post, but this way is easier to demonstrate. | |
Tags Views | |
app/views/acts_as_taggable_on/tags/_tag.html.erb | |
<%= link_to tag.name, tag_path(tag) %> | |
app/views/tags/index.html.erb | |
<h1>Tags</h1> | |
<%= render @tags %> | |
app/views/tags/show.html.erb | |
<h1><%= @tag.name %></h1> | |
<div><%= render @posts %></div> | |
Note the partial path is acts_as_taggable_on/tags/tag. This is so we can just say render @tags and let rails do its implicit magic. There are other ways to organize everything, but this is the simplest. | |
View integration | |
app/views/posts/_post.html.erb | |
<h2><%= link_to post.title, post_path(post) %></h2> | |
<div><%= render post.tags %></div> | |
app/views/posts/index.html.erb | |
<h1>Posts</h1> | |
<%= render @posts %> | |
app/views/posts/show.html.erb | |
<h1><%= @post.title %></h1> | |
<div><%= @post.body %></div> | |
<div><%= render @post.tags %></div> | |
And that should be it. It'll look shitty, but I hope you can figure out how to elaborate on this once you have it working. If anything here is assuming familiarity with something you don't have, ask and I will gladly elaborate. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment