Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Editing many-to-many relations in Activeadmin

I am looking for a way to edit/add keywords related to an article, inline in Activeadmin.

I have defined a simple many-to-many setup:

class Area < ActiveRecord::Base
  has_many :area_keywords
  has_many :keywords, :through => :area_keywords
  accepts_nested_attributes_for :keywords, :reject_if => :all_blank, :allow_destroy => true
end

class AreaKeyword < ActiveRecord::Base
  belongs_to :area
  belongs_to :keyword
end

class Keyword < ActiveRecord::Base
  has_many :area_keywords
  has_many :areas, :through => :area_keywords
end

I would like to add and edit the keywords in en Area form, so I setup this in Aciveadmin:

ActiveAdmin.register Area do
  form do |f|
    f.inputs "Area details" do
      f.input :title
      f.input :description
    end
    f.has_many :keywords do |k|
      if k.object.nil?
        k.input :word, :label => 'Keyword'
      else
        k.input :word, :label => k.object.word
        k.input :_destroy, :as => :boolean, :label => "delete"
      end
    end
  end
end

This works as expected.

But if I add the same Keyword to two different areas, the Keyword will just be created twice.

When entering a new keyword (in the Area form), I would like it to automatically create a relation to an existing keyword, or create a new keyword, if it does not exist. What would be the best way to go about it?

like image 547
Martin Poulsen Avatar asked Dec 03 '12 16:12

Martin Poulsen


1 Answers

This is a pretty late answer :) but I actually have encountered kind of a similar issue in one of my projects...I had to add keywords/tags to two different models, but they could share them. At first I did just like you, and it was creating a record for each time you "attach" a keyword/tag to a model.

A better way to handle it is to use a tagging system. And I achieved a pretty neat system by combining two really good gems: 'acts-as-taggable-on' (https://github.com/mbleigh/acts-as-taggable-on) and 'select2-rails' (https://github.com/argerim/select2-rails)

In my own project, I actually did something similar to you and created a model just to have a list of all the appropriate keywords I wanted. But 'act-as-taggable-on' doesn't necesarilly requires a list of accepted keywords...so you can create them on the fly, and it will automatically handle duplicates, counts etc.

'select2-rails' just allows you to have an nice interface to add and remove keywords in one field, rather than using checkboxes, select options, or a text input where you would have to manually separate your string with commas or any separators.

If anyone need more details on how I implemented all, I would be more than glad to provide more code .. but the documentation for both of them are pretty straightforward!

EDIT: Well, I have a feeling some code would actually be useful :)

Bundle install both gem in your Gemfile

gem 'acts-as-taggable-on'
gem 'select2-rails'

In your Area model, you could add the following and do something like

class Area < ActiveRecord::Base
    # .. your code

    attr_accessible :area_keyword_list

    acts_as_taggable_on :area_keywords
end

And in your ActiveAdmin file

ActiveAdmin.register Area do

    form do |f|
      f.inputs do
        # .. whatever fields you have
        f.input :area_keyword_list,
          :as => :select,
          :multiple => :true,
          :collection => # here either a list of accepted keyword..or just left open,
          :input_html => { :class => "multiple-select" }
      end
    end
end

and the JS for select2 is quite simple ...

$(".multiple-select").select2();

Voilà !

like image 197
rorofromfrance Avatar answered Oct 24 '22 22:10

rorofromfrance