AssignsHasManyThroughRelations
Rails Engine that provides a management UI to assign models to each other in the case where they are associated in a has_many :through style relationship.
For example, given a pair of models Location and User, we will consider Location to be the left side relation and User to be the right side relation. This UI provides a 3 column Bootstrap view where the left most column displays all Locations where the user can select one from the list. The 2 other columns are the Assigned and Unnassigned columns. These display Users that either have a join model with the selected Location or not, respectively. The user can then select Users from the Unnassigned column and the form PUT will create the join models necessary to move the Unnassigned Users to the middle Assigned column, effectively associating the selected Users from the right most column to the selected Location.
What You Get

In the above example, clicking on "Assign Selected" will move the selected Users to the middle column by creating the locations_user join model between them and the selected Location "Home".
You'll notice there's a Filter text input, this will filter the corresponding list as you type. Hitting ESC will clear the text field.
Installation
Add this line to your application's Gemfile:
gem 'assigns_has_many_through_relations'
And then execute:
$ bundle
Or install it yourself as:
$ gem install assigns_has_many_through_relations
Dependencies
- Twitter Bootstrap (if you want the UI to be pre-styled).
- jQuery (for the list Filter).
Usage
Declare the routes:
YourApp::Application.routes.draw do
AssignsHasManyThroughRelations.routes_for :locations, :users, self
end
Declare the plugin and options in your models:
class Location < ActiveRecord::Base
extend AssignsHasManyThroughRelations::ModelConcern
assigns_has_many_relationships_with :location, :user
end
class User < ActiveRecord::Base
has_many :locations_users, dependent: :delete_all
has_many :locations, through: :locations_users
end
And a controller to handle the requests:
class LocationsUsersController < ApplicationController
extend AssignsHasManyThroughRelations::ControllerConcern
assigns_has_many_relationships_with :location, :user
end
Finally, render the management UI partial in a view template in app/views/locations_users/index.html.erb:
<div id="locations_users">
<h1>Assign Users To Location</h1>
<%= render '/assigns_has_many_through_relations' %>
</div>
You'll have to provide the user with a link to locations_users_path. And that's it. Now you'll be able to assign and unassign Users to Locations.
You can configure the engine to run a controller authorization method as you would a controller macro e.g like Cancan's load_and_authorize_resource:
# config/initializers/assigns_has_many_through_relations.rb
AHMTR.configure do
auth_filter :load_and_authorize_resource
end
Todo
- Write specs.
Contributing
- Fork it ( https://github.com/[my-github-username]/assigns_has_many_through_relations/fork )
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create a new Pull Request