
Security News
New Website “Is It Really FOSS?” Tracks Transparency in Open Source Distribution Models
A new site reviews software projects to reveal if they’re truly FOSS, making complex licensing and distribution models easy to understand.
=dependent_select
This package extends rails with some helpers that allow "selects that update dynamically depending on other fields"
Demo application can be found in http://github.com/splendeo/dependent_select
Mailing list on http://groups.google.com/group/dependent_select/
==Quick example: Store with country and province
On your layout: <%= javascript_include_tag :defaults %> <%= dependent_select_includes %>
On your new/edit views:
<% form_for :store do |f| %>
Country:<br/>
<% f.collection_select :country_id, @countries, :id, :name, :include_blanks => true %> <br />
Province:<br/>
<% f.dependent_collection_select :province_id, @provinces, :id, :name, :country_id, :include_blanks => true %> <br />
City:<br/>
<% f.dependent_collection_select :city_id, @cities, :id, :name, :province_id, :include_blanks => true %> <br />
<% end %>
In order for this to work properly, the Store model must have methods for +country_id+ and +store_id+. The best way I've found for implementing this is by using +delegate+. So the model would be:
class Store < ActiveRecord::Base
belongs_to :city, :include => [{:province => :country}] #useful to preload these
delegate :country, :country_id, :country_id=, :to =>:city
delegate :province, :province_id, :province_id=, :to =>:city
end
Notice that I've delegated the country to the city - so the city should probably have another +delegate+ line:
class City < ActiveRecord::Base
belongs_to :province, :include => [:country] #again, useful but not needed
delegate :country, :country_id, :country_id=, :to =>:province
end
Finally, the controller might look like this:
class StoresController < ApplicationController
before_filter :fill_selects :only => [:new, :edit, :update, :create]
{...} # Standard scaffold-generated methods
protected
def fill_selects
@countries = Country.find(:all, :order => 'name ASC')
@provinces = Province.find(:all, :order => 'name ASC') # all provinces for all countries
@cities = City.find(:all, :order => 'name ASC') # all cities for all provinces
end
end
This will generate a regular +collection_select+ for the country and a +dependent_collection_select+ for province. The later will be a regular +collection_select+ followed by a js +
Note that this will not work if you haven't followed the installation procedure - see below
There's a more complex example at the end of this document.
==Installation
===As a gem Copy this on config/environment.erb, inside the gems section config.gem "dependent_select" Then execute rake gems:install
The first time you initialize your server after this (presumably with script/server) the necesary javascript files and css will be copied to the public/ directory.
===As a plug-in I actually haven't tried this, sorry I don't know how to do it.
==Re-installation ===As a gem Several steps are needed:
In other words: sudo gem uninstall dependent_select rm public/javascripts/dependent_select/dependent_select.js rake gems:install
===As a plug-in I haven't looked into that yet.
==No AJAX? I can't sent the client all my cities!
No AJAX for now, sorry. Just plain old javascript.
However, it might interest you that you'll be generating this:
<script>
var whatever = [['opt1',1,1],['opt2',2,1],['opt3',3,1]...];
</script>
Instead of this :
<option value='1'>opt1</option>
<option value='2'>opt2</option>
<option value='3'>opt3</option>
In our tests, generating information for 8000 cities took arond 20k - the size of a small image.
Make the test and then decide. It will not take you more than 10 minutes.
==Complex example: Employee with home city and work city
On this case we have an employee model with 2 relationships with cities. So the employee model might look like the one below. Notice that the +delegates+ get a bit more complicated.
class Employee < ActiveRecord::Base
belongs_to :home_city, :class_name => "City", :include => [{:province => :country}]
delegate :country, :country_id, :country_id=, :to =>:home_city,
:allow_nil => true, :prefix => :home
delegate :province, :province_id, :province_id=, :to =>:home_city,
:allow_nil => true, :prefix => :home
belongs_to :work_city, :class_name => "City", :include => [{:province => :country}]
delegate :country, :country_id, :country_id=, :to =>:work_city,
:allow_nil => true, :prefix => :work
delegate :province, :province_id, :province_id=, :to =>:work_city,
:allow_nil => true, :prefix => :home
end
On your layout: <%= javascript_include_tag :defaults %> <%= dependent_select_includes %>
On your new/edit views, the "filter" for provinces isn't +:country_id+ any more, but +:home_country_id+ or +:work_country_id+. The same happens with the cities and the provinces. You have to tell the selects where to find the right filter fields, using the +filter_field+ option.
<% form_for :employee do |f| %>
Home Country:<br/>
<% f.collection_select :home_country_id, @countries, :id, :name, :include_blanks => true %> <br />
Home Province:<br/>
<% f.dependent_collection_select :home_province_id, @provinces, :id, :name, :country_id,
:filter_field => :home_country_id,
:include_blanks => true %> <br />
Home City:<br/>
<% f.dependent_collection_select :home_city_id, @cities, :id, :name, :city_id,
:filter_field => :home_province_id,
:include_blanks => true %> <br />
Work Country:<br/>
<% f.collection_select :work_country_id, @countries, :id, :name, :include_blanks => true %> <br />
Work Province:<br/>
<% f.dependent_collection_select :work_province_id, @provinces, :id, :name, :country_id,
:filter_field => :work_country_id,
:include_blanks => true %> <br />
Work City:<br/>
<% f.dependent_collection_select :work_city_id, @cities, :id, :name, :city_id,
:filter_field => :work_province_id,
:include_blanks => true %> <br />
<% end %>
On your controller:
class EmployeesController < ApplicationController
before_filter :fill_selects :only => [:new, :edit, :update, :create]
{...} # Standard scaffold-generated methods
protected
def fill_selects
@countries = Country.find(:all, :order => 'name ASC')
@provinces = Province.find(:all, :order => 'name ASC') # all provinces for all countries
@cities = City.find(:all, :order => 'name ASC') # all cities for all provinces
end
end
FAQs
Unknown package
We found that dependent_select demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
A new site reviews software projects to reveal if they’re truly FOSS, making complex licensing and distribution models easy to understand.
Security News
Astral unveils pyx, a Python-native package registry in beta, designed to speed installs, enhance security, and integrate deeply with uv.
Security News
The Latio podcast explores how static and runtime reachability help teams prioritize exploitable vulnerabilities and streamline AppSec workflows.