Subscribe to RSS

ActiveScaffold, Acts_as_taggable_on_steroids

Update: also read Active Scaffold + Acts_as_taggable + Auto Completion.

This is kind of an advanced topic, but I think it may be useful to a lot of people.

ActiveScaffold is a great plugin to start building a user interface. The great thing about AS is, that is automatically recognizes associated models. When editing a model, you can easily add or select another model that you want to associate with is.

The best example of this is an Article, where you can select the author (the associated User model) with a drop down box.

There is only one point where I ran into trouble with ActiveScaffold: acts_as_taggable_on_steroids.

Acts_as_taggable_on_steroids allows you to easily attach tags to models and do all kinds of crazy stuff with them. But, if you want to integrate in into AcitveScaffold, you’re in for a tough ride.

ActiveScaffold supports has_many :through associations, but not in a way that is compatible with acts_as_taggable_on_steroids. Let me show you.

In your ArticlesController you specify which columns to show. “tag_list” is a stringified version of the tags associated with the Article, which is great for showing to a user.

However, if you want to edit it an article (or create one), I don’t want a text field where I have to enter tags manually, all I want are a bunch of check boxes, so I can check which tags apply to this article.

Showing the check boxes is easy with AS. By default I show ‘tags’, only in the list view do I use ‘tag_list’ instead. Also, make sure to set the ui_type for the tags column to :select. This will show you check boxes, instead of a sub form that allows you to create tags manually.

active_scaffold :article do |config|
    config.columns = [:title, :body, :tags, :author, :created_at]
    config.list.columns = [:title, :author, :tag_list, :created_at]
    config.columns[:tags].ui_type = :select
end

Well, very nice, right. You can now happily select the tags you want, and save your article. Not.

As you may have noticed, the tags are not saved. Why? Acts_as_taggable adds a ‘tags’ attribute to the model, however, when the Article model is saved, the tags attribute is overwritten by the tags specified in the “tags_list” attribute.

The only way to solve this is to convert the tags selected in AS and store them as the tags_list attribute for the Article.

First, let’s add a private method in the ArticleController class:

private
 
def new_tag_list(tag_ids)
    tag_ids.map {|k,h| h['id']}.collect {|i| Tag.find(i)}.map do |tag|
      tag.name.include?(Tag.delimiter) ? "\"#{tag.name}\"" : tag.name
    end.join(Tag.delimiter.ends_with?(" ") ? Tag.delimiter : "#{Tag.delimiter} ")
end

And add two protected methods that extend the functionality of ActiveScaffold:

protected
 
def before_create_save(record)
    record.tag_list = new_tag_list(params[:record][:tags])
end
 
def before_update_save(record)
    record.tag_list = new_tag_list(params[:record][:tags])
end

This will take the actual form values from AS and create a tags_list. This new tags_list is then assigned to the article (named ‘record’ here). The two protected methods process the tags every time an Article is created or updated.

With this in place, you can happily assign tags to your articles! Please let me know if it worked for you, or if you have made any improvements to this solution.

Please share the love of this post by bookmarking it, and sharing it with others. Thanks!

  • Digg
  • del.icio.us
  • description
  • Reddit
  • Technorati
  • BlinkList
  • E-mail this story to a friend!
  • Facebook
  • Live
  • MisterWong
  • Netvouz
  • NewsVine
  • Slashdot
  • SphereIt

15 Comments

  1. Guillaume
    Posted 12 June, 2007 at 13:57 | Permalink

    Hi,

    i found your article very interesting, and i tried to reproduce what you did with AS…
    But unfortunatly, it doesn t work for me…

    I did the exact samething as you, but AS tell me “no option” in the Tags field….
    i ll appreciate your help

    Guillaume.

  2. Posted 12 June, 2007 at 20:18 | Permalink

    Guillaume: Did you create the proper tables for the tags?

    class AddTagSupport < ActiveRecord::Migration
      def self.up
        #Table for your Tags
        create_table :tags do |t|
          t.column :name, :string
        end
     
        create_table :taggings do |t|
          t.column :tag_id, :integer
          #id of tagged object
          t.column :taggable_id, :integer
          #type of object tagged
          t.column :taggable_type, :string
        end
     
        # Index your tags/taggings
        add_index :tags, :name
        add_index :taggings, [:tag_id, :taggable_id, :taggable_type]
      end
     
      def self.down
        drop_table :taggings
        drop_table :tags
      end
    end

    Make sure you have the acts_as_taggable call in your model as well. Maybe restart your development server, that helps too sometimes. Let me know how it goes.

    – You probably have the correct tables, but no tags are in it yet. You cannot currently add a new tag, hence the “no option” message. I’ll post a new article with more info on that later.

  3. Guillaume
    Posted 13 June, 2007 at 11:05 | Permalink

    Ok, so actually i added manually in the DB one tag, and now it works, but something still weird in you article,

    is’nt it possible to add manually tag ?
    i mean having checkbox to choose the tags for your article is very cool, but if the right tag is’nt present, is there a way to show a text field where you can add tags to the artcile and by the way to the tag DB ?

    Guillaume.

  4. Posted 13 June, 2007 at 12:28 | Permalink

    Yes, I know. I’m working on a solution for that. I’ll post it in a new article later this week, probably.

  5. Guillaume
    Posted 13 June, 2007 at 14:37 | Permalink

    Ok, so far i m waiting for a genius solution from you….

    thkx…

  6. Guillaume
    Posted 14 June, 2007 at 22:17 | Permalink

    Any progress ?

    thanks :)

  7. Posted 15 June, 2007 at 08:11 | Permalink

    Nope, not yet. I’m currently having exams and next tuesday I have to deliver a presentation to get my CS degree.

    I’m trying different approaches now, but I think I have found something. Take a look at the _form_association views. That could be very useful.

  8. Guillaume
    Posted 15 June, 2007 at 13:54 | Permalink

    I will… but i guess you ve got more knowledge that me on AS ans RoR…

    Good luck for your exams

  9. Guillaume
    Posted 29 June, 2007 at 15:54 | Permalink

    Hi,

    Did you have any success of resolving the tag problem ?
    (the problem that you can not add tags)

    Thanks
    Guillaume

  10. Posted 1 July, 2007 at 18:37 | Permalink

    I’ve just posted a new article describing a (quite different) solution to this problem.

    Read it here: http://ariejan.net/2007/07/01/activescaffold-acts_as_taggable-auto-complete/

  11. suci
    Posted 8 September, 2007 at 03:29 | Permalink

    i have a question,how to short label in design with activescaffold????

  12. Kristofer
    Posted 25 April, 2008 at 19:31 | Permalink

    so is there any possibility that this routine from above -

    def new_tag_list(tag_ids)
    tag_ids.map {|k,h| h['id']}.collect {|i| Tag.find(i)}.map do |tag|
    tag.name.include?(Tag.delimiter) ? “\”#{tag.name}\”" : tag.name
    end.join(Tag.delimiter.ends_with?(” “) ? Tag.delimiter : “#{Tag.delimiter} “)
    end

    - wouldn’t work in ruby 1.86 and rails 2.0.2? Or with acts_as_taggable_on_steroids (as of 30 March 2008)?

    It throws a

    NoMethodError (You have a nil object when you didn’t expect it!
    You might have expected an instance of Array.
    The error occurred while evaluating nil.map):
    /app/controllers/recipes_controller.rb:46:in `new_new_tag_list’
    /app/controllers/recipes_controller.rb:29:in `before_create_save’
    /vendor/plugins/active_scaffold/lib/actions/create.rb:75:in `do_create’

    when trying to create a new “recipe”. the tag table is not empty, I put a couple in by hand…

    any ideas?

  13. Posted 26 April, 2008 at 08:37 | Permalink

    @Kristofer: I haven’t used this for a while. This probably has to do with acts_as_taggable_on_steroids. I’m not sure you need these helper methods anymore. Did you try using the ‘tag_list’ property directly? I think that should work now.

  14. Kristofer
    Posted 26 April, 2008 at 15:33 | Permalink

    Yep. I took out the before_*_save routines and it works like a champe, even your autocomplete stuff works. Thanks!

  15. Kristofer
    Posted 26 April, 2008 at 15:35 | Permalink

    I do have to say, even after working with Ruby for 9 months, your new_tag_list method made my head hurt trying to figure it out. I wasn’t able to - that’s why I finally wrote to ask you about it all.

One Trackback

  1. [...] digg_url=’http://ariejan.net/2007/07/01/activescaffold-acts_as_taggable-auto-complete/’; digg_skin = ‘button’; digg_bgcolor = ‘#FFFFFF’; digg_title = ‘ActiveScaffold + acts_as_taggable + Auto Complete’; digg_bodytext = ”; digg_topic = ”; I’ve talked before on how to use ActiveScaffold with acts_as_taggable_on_steroids. [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*