Search code examples
ruby-on-railsrubyruby-on-rails-4acts-as-taggable-on

Ruby on Rails: Acts as taggable on gem, working with context in model


I was wondering if someone can help me understand this part in the documentation:

With the defined context in model, you have multiple new methods at disposal to manage and view the tags in the context. For example, with :skill context these methods are added to the model: skill_list(and skill_list.add, skill_list.remove skill_list=), skills(plural), skill_counts.

I have this:

model:

class Project < ActiveRecord::Base
  acts_as_taggable # Alias for acts_as_taggable_on :tags
  acts_as_taggable_on :item
end

controller:

def project_params
  params.require(:project).permit(
    :user_id, :tag_list)
end

view

<%= f.text_field :tag_list %> <!-- wrapped in a simple_form -->

So my question is... does that mean, if I have :items in my model, I can replace all the :tag_list into :item_list? And just use item_list from now on? I tried this, but its not producing the same results as what I currently have... maybe I messed up somewhere, but is this "theoretically" correct?

Thanks

BONUS:

So eventually, if I have more than one thing that I want to tag:

acts_as_taggable_on :item, :more_taggable_item

I can have this in my strong params

params.require(:project).permit(
    :user_id, :tag_list, :more_taggable_item_list)

and then I can use it in my view:

<%= f.text_field :more_taggable_item_list %>

Solution

  • You are correct. If you use the default acts_as_taggable (or explicitly acts_as_taggable_on :tags) in your model, the following methods will be dynamically defined by the gem: tag_list, tag_list=, tags, tag_counts.

    If you use acts_as_taggable_on :items instead (note the plural, as @smallbutton.com said), the following methods will be dynamically defined: item_list, item_list=, items, item_counts.

    So in your case, you don't need the first acts_as_taggable. Only use acts_as_taggable_on :items, :more_taggable_items. You can then use item_list and more_taggable_item_list in your controllers and views, instead of tag_list.


    PS: for reference, see how acts_as_taggable is defined in the gem:

    # This is an alias for calling <tt>acts_as_taggable_on :tags</tt>.
    def acts_as_taggable
      acts_as_taggable_on :tags
    end
    

    The method generation is a bit more complex, but basically it loops over your acts_as_taggable_on parameters, and define the methods with them:

    # Loop over [:items, :more_taggable_items]
    tag_types.map(&:to_s).each do |tags_type|
      tag_type = tags_type.to_s.singularize # 'item', 'more_taggable_item'
      # ...
    
      taggable_mixin.class_eval <<-RUBY, __FILE__, __LINE__ + 1
        # Define item_list, more_taggable_item_list
        def #{tag_type}_list
          tag_list_on('#{tags_type}')
        end
    
        # ...
      RUBY
    end