This is a simple Rails extension that allows you to create polymorphic select inputs for relationships that are polymorphic. It takes advantage of Rails 4.2 Global ID
Ruby HTML CSS JavaScript
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
bin
lib
spec
.gitignore
.rspec
.travis.yml
Gemfile
Gemfile.lock
MIT-LICENSE
README.md
Rakefile
rails_polymorphic_select.gemspec

README.md

Rails Polymorphic Select

Build Status Code Climate

This is a simple Rails extension that allows you to create polymorphic select inputs for relationships that are polymorphic.

Install

Just add this to your Gemfile and then bundle install:

gem 'rails_polymorphic_select'

Usage

When using any ActionView::Helpers::FormBuilder object (either from the form_for helper method or a custom FormBuilder object) you can now call the method polymorphic_select like so:

<%= form.polymorphic_select :association_name_global_id, [News, Event, Photo] %>

The first argument it accepts is a method name (like all FormBuilder input methods), except you'll notice it's a *_global_id method. This library will automatically add these methods on all polymorphic relationships you create in your app. So if I have a Tagging model and I have a polymorphic relationship named taggable like this:

class Tagging
  belongs_to :tag
  belongs_to :taggable, :polymorphic => true
end

This will create a taggable_global_id method and a taggable_global_id= method for reading and setting the taggable item by it's Global ID. However, it will not add these methods for non-polymorphic relationships (like tag in this case). Rails added GlobalID functionality in 4.2, so now all ActiveRecord models have a to_global_id method that will return a GlobalID object that can be used to find the record.

The second argument polymorphic_select takes is an Array of ActiveRecord model classes that are valid options for this polymorphic relationship.

The third argument is an options argument and this gets passed to the FormBuilder#select. Before that however there's one extra option that polymorphic_select accepts: :label_method. This is used as the method to call on individual records to get the value that users would see on the form select input for each record. By default it tries to find a good method (name, title, to_s, etc). If you prefer you can define a to_label or display_name method on the model(s), and these will be used.

The fourth argument is a html_options argument and this gets passed directly unaltered to FormBuilder#select.

Worth noting is this greats a grouped selct input. So the records will be grouped by model class. The polymorphic_select method will use ModelClass.model_name.human to label the group. You can modify the name it supplies by manually editing the i18n value for the model.

Advanced usage

Perhaps you have a Tag model with taggings but you want to access and set the individual taggables. In this case you could create your own *_global_ids methods and use this on with polymorphic_select. Say your Tag model looks like this:

class Tag
  has_many :taggings

  def taggables
    taggings.map(&:taggable)
  end

  def taggable_global_ids
    taggables.map(&:to_global_id)
  end

  def taggalbe_global_ids=(global_ids)
    # your own code that at some point uses GlobalID::Locator.locate(global_id_value) to set the taggings
  end
end

Then in your form you could do:

<%= form.polymorphic_select :taggable_global_ids, [News, Event, Photo] %>

and it would just work!

Contributing to RailsPolymorphicSelect

  • Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
  • Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
  • Fork the project.
  • Start a feature/bugfix branch.
  • Commit and push until you are happy with your contribution.
  • Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
  • Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.

Copyright

Copyright (c) 2015 Brian Landau (Viget Labs). See MIT_LICENSE for further details.


Code At Viget

Visit code.viget.com to see more projects from Viget.