0

I need someone to guide me in generating Categories for my Post model. I want to have a main navigation bar at the top and all the categories with multiple submenus in the sidebar section.

I read multiple posts and found out I could either generate multiple models for my categories or use tags. I've already created tag model but not sure how I can create a tree structure using this.

-----edit----------

I've already tried using Acts-As-Taggable-On Gem and created tags for my Post model. But not sure how I can use this to create a categories for navigation and sidebar.

/////-----Edit 2 ---------///

views/application.html.erb

<ul>
  <% Tag.roots.each do |tag| %> 
    <li><%= link_to tag.name, tag_path(tag) %></li>
  <% end %>
</ul>

This forms a list of Tag root nodes. When I click one of the tag, I get following error:

Started GET "/tags/1" for 127.0.0.1 at 2014-01-25 01:23:48 -0500
Processing by PostsController#index as HTML
  Parameters: {"tag"=>"1"}
  Tag Load (0.3ms)  SELECT "tags".* FROM "tags" WHERE "tags"."name" = '1' LIMIT 1
Completed 404 Not Found in 3ms

ActiveRecord::RecordNotFound (ActiveRecord::RecordNotFound):
  app/models/post.rb:6:in `tagged_with'
  app/controllers/posts_controller.rb:23:in `index'

This is what I've put for routes: routes.rb

  get 'tags/:tag', to: 'posts#index', as: :tag

I'm also including posts_controller.rb:

class PostsController < ApplicationController


  def new
    @post = Post.new
  end

  def create
    @post = Post.new(post_params)
    if @post.save(params[:post].permit(:title, :body, :tag_list))
      redirect_to @post
    else 
      render 'new'
    end
  end

  def show
    @post = Post.find(params[:id])
  end

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

  def update 
    @post = Post.find(params[:id])

    if @post.update(params[:post].permit(:title, :body, :tag_list))
      redirect_to @post
    else
      render 'edit'
    end
  end

  def edit
    @post = Post.find(params[:id])
  end

  def destroy
    @post = Post.find(params[:id])
    @post.destroy 

    redirect_to posts_path
  end

  private
    def post_params
      params.require(:post).permit(:title, :body, :tag_list)
    end
end
Simone Carletti
  • 173,507
  • 49
  • 363
  • 364
wag0325
  • 1,008
  • 5
  • 18
  • 34
  • 2
    https://github.com/mbleigh/acts-as-taggable-on is your best friend on this one. – IT Ninja Jan 25 '14 at 02:24
  • @ITNinja I've already installed acts-as-taggable-on and implemented it to my Post model so that a user can enter and create tags. But I'm not sure how I can create categories using these tags. Also, the README page of acts-as-taggable-on explains the way to create tag_list but not sure where I can state this to generate tag_list for me to use. – wag0325 Jan 25 '14 at 02:47
  • 1
    well, you can do something like this. You attach a tag to a post with the given category. Then in order to get all items from that category, you search for all posts with that given tag. In order to create the sidebar, you make logic to check for a query parameter (that you add to your link_to's) with the given category. In the logic, you would return the posts with that specific tag. – IT Ninja Jan 25 '14 at 03:51
  • So far, I've implemented acts-as-taggable-on gem and the closure tree gem and generated hierarchies in my tags. For the main navbar, I've called the root nodes but still not too sure what to put inside the link_to. Please refer back the my original post for my codes. – wag0325 Jan 25 '14 at 06:21

1 Answers1

0

IMO you're getting confused with 2 different issues:

  1. Associate Post With Many Categories
  2. Category Hierarchy

Posts

If you want your post to have many categories, you could just use a HABTM association:

#app/models/post.rb
Class Post < ActiveRecord::Base
     has_and_belongs_to_many :categories
end 

#app/models/category.rb
Class Category < ActiveRecord::Base
     has_and_belongs_to_many :posts
end

You'll need to create a categories_posts table like this (Rails 3 has_and_belongs_to_many migration):

#db/migrate/your_migration.rb
create_table :categories_posts, :id => false do |t|
    t.references :categories
    t.references :posts
 end

This will allow you to associate any post with as many categories as you want. There are numerous ways to do this, but the simplest is to simply use the << ActiveRecord function:

#app/controllers/posts_controller.rb
def add_category
    @post = Post.find(params[:id])
    @post.categories << Category.find(params[:category_id])
end

Hierarchy

Because you'll have your categories separate to your posts, you'll be able to use a gem such as ancestry to give them hierarchy

Unlike tags, I see categories as mainly being fixed, meaning you can do what you want with them in the backend, presenting the user with a structured selection

Community
  • 1
  • 1
Richard Peck
  • 76,116
  • 9
  • 93
  • 147