dmuk
dmuk

Reputation: 485

Adding tags/categories to posts in Rails?

I am looking to add tags to my Blog app.

I wish for Posts to have none, one or many tags. For now, I want to restrict the choice of tags to 10 pre-defined tags.

Should I create a model:

   post_id, tag_name
   1, sport
   1, news
   1, fun
   2, sport
   3, news

Or a wider table:

   post_id, tag_sport, tag_special
   1,Yes,No,...

Or include the chosen tags within the post table:

   post_id, post_body, post_tags
   1, lorem ipsum, sport|news|fun

How would the form look?

   Free textbox separated by commas? Checkbox?

I know there are plugins and existing options available, but would like to be able to control the tags via a table. I have followed some tutorials but they do not provide a complete solution.

Upvotes: 1

Views: 2887

Answers (4)

Aayush Khandelwal
Aayush Khandelwal

Reputation: 1071

My suggestion will be use habtm relation between books and tags.

   class < books
     has_and_belongs_to_many :tags
     validates :no_of_tags


     def no_of_tags
        if self.tags.length < 4 #your choiche
          false
        end
     end
   end


   class < tags
     has_and_belongs_to_many :books
   end

Plus create a table books_posts

this will solve your problem

Upvotes: 0

Alistair A. Israel
Alistair A. Israel

Reputation: 6567

Personally, and keeping with "the simplest thing that could possibly work", if you only have to deal with, say, 10 pre-defined tags then I might be inclined to go with a simple serialized field.

However, this entails additional effort and places unnecessary load on your database when you want to search for posts by tag (simplest is a LIKE query, which in most cases involves a table scan).

So, personally, even with a simple tagging system I will almost always end up with a tags table of just id and name, then a has_and_belongs_to_many relationship between the tags and the taggable entities:

class Post < ActiveRecord::Base

  has_and_belongs_to_many :tags

And in Tag:

class Tag < ActiveRecord::Base

  attr_accessible :name

  has_and_belongs_to_many :posts

  validates :name, presence: true, uniqueness: {case_sensitive: false}  

Of course, this means having to write a migration to create the appropriate join table, something like:

class CreatePostsTags < ActiveRecord::Migration
  def change
    create_table :posts_tags do |t|
      t.references :post, null: false
      t.references :tag, null: false
    end
  end
end

This way the database schema is also kept in normal form.

To search by tag, it reduces to something like:

Tag.find_by_name('news').posts

(In practice, you'll want a Tag.named(name) method that'll strip.downcase name for you.)

As for the form, again, the simplest thing I might end up with is just a plain text field, where tags are separated by commas (and therefore the comma character isn't a valid character in a tag name). Or, if you don't allow spaces in tag names, you can use the space as a delimiter.

Upvotes: 0

Kai Mattern
Kai Mattern

Reputation: 3085

You won't get a comnplete solution here. SO is not a code dispenser.

What you have here is a typical n to m relationship. A post may have many tags (the restriction of a max of 10 tags is irrelevant for this) - and a tag can be part of many posts.

n to m relations are modelled through the use of a 2 additional tables: 1 for the relating model (the tag) and one for saving the relationships.

This give you (assuming your post table is named posts)

Table posts_tags which looks like this:

id
post_id
tag_id

And a table tags:

id
tagname

The relation is then described in the models via has_and_belongs_to_many

If a post only can have one tag - you can simplify this with using just a 1 to many relation.

For the design and given the small number of tags, I would just use a bunch of checkboxes. But that is up to you. You will find examples for the visualisation of n:m with rails on the web.

Upvotes: 0

Amar
Amar

Reputation: 6942

You can try this acts-as-taggable-on gem,watch railscast may give you better idea

Upvotes: 1

Related Questions