Permalink
Browse files

Refactor region_options_for_select to take a collection of regions in…

…stead of a parent_ragion_code.
  • Loading branch information...
jim committed May 21, 2012
1 parent ae1333b commit ada9fc20b65123629fb0831b5997f81f9bfb2a5e
Showing with 148 additions and 19 deletions.
  1. +6 −1 CHANGELOG.md
  2. +25 −4 README.md
  3. +92 −14 lib/carmen/rails/action_view/form_helper.rb
  4. +25 −0 spec/carmen/action_view/helpers/form_helper_spec.rb
View
@@ -1,9 +1,11 @@
### HEAD
+### 1.0.0.beta 3
+
Bug Fixes
* Removed some 1.9 syntax taht prevented the gem from running on Ruby 1.8
-*
+
Enhancements
* Region select options are now sorted (lukast-akra)
@@ -12,3 +14,6 @@ API Changes
* region_options_for_select now takes priority region codes in an options hash
under the key 'priority'.
+* The API for region_options_for_select now expects a collection of Carmen::Regions
+ as its second argument instead of a parent region. This makes it simple to provide
+ a custom collection of regions to build a select from.
View
@@ -9,7 +9,7 @@ carmen-rails is a Rails 3 plugin that supplies two new form helper methods:
Just add carmen-rails to your Gemfile:
```ruby
-gem 'carmen-rails', '1.0.0.pre'
+gem 'carmen-rails', '1.0.0.beta3'
```
## Usage
@@ -18,14 +18,35 @@ gem 'carmen-rails', '1.0.0.pre'
<%= form_for(@order) do |f| %>
<div class="field">
<%= f.label :country_code %><br />
- <%= f.country_select :country_code, priority: %w(US CA), prompt: 'Please select a country' %>
+ <%= f.country_select :country_code, {priority: %w(US CA)}, prompt: 'Please select a country' %>
</div>
<% end %>
```
-More docs coming soon.
+## How do I only display a subset of countries/regions?
+
+Carmen had a concept of excluded countries in the old days, where you could
+specify certain countries or regions to not include in a select.
+
+The new (and much more flexible) way to handle this is to write a helper method
+that returns the subset of regions you want to provide:
+
+``` ruby
+def only_us_and_canada
+ Carmen::Country.all.select{|c| %w{US CA}.include?(c.code)}
+end
+```
+
+And then in your form something like this:
+
+``` erb
+<%= f.select :country, region_options_for_select(only_us_and_canada) %>
+```
+
+More docs coming soon. In the meantime, all of the public methods in
+carmen-rails [have been thoroughly TomDoc'ed](https://github.com/jim/carmen-rails/blob/master/lib/carmen/rails/action_view/form_helper.rb).
### Demo app
There is a [live demo app](http://carmen-rails-demo.herokuapp.com) that shows
-carmen-rails in action.
+carmen-rails in action, and includes a [step-by-step setup guide](https://github.com/jim/carmen-demo-app#readme).
@@ -2,40 +2,80 @@ module ActionView
module Helpers
module FormOptionsHelper
- # Return select and subregion option tags for the given object and method.
+ # Generate select and subregion option tags for the given object and method. A
+ # common use of this would be to allow users to select a state subregion within
+ # a given country.
+ #
+ # object - The model object to generate the select for
+ # method - The attribute on the object
+ # parent_region_or_code - An instance of Carmen::Region or a 2-character
+ # country code.
+ # options - Other options pertaining to option tag generation. See
+ # `region_options_for_select`.
+ # html_options - Options to use when generating the select tag- class,
+ # id, etc.
#
# Uses region_options_or_select to generate the list of option tags.
+ #
+ # Example:
+ #
+ # subregion_select(@object, :region, {priority: ['US', 'CA']}, class: 'region')
+ #
+ # Returns an `html_safe` string containing the HTML for a select element.
def subregion_select(object, method, parent_region_or_code, options={}, html_options={})
parent_region = determine_parent(parent_region_or_code)
tag = InstanceTag.new(object, method, self, options.delete(:object))
tag.to_region_select_tag(parent_region, options, html_options)
end
- # Return select and country option tags for the given object and method.
+ # Generate select and country option tags for the given object and method. A
+ # common use of this would be to allow users to select a state subregion within
+ # a given country.
+ #
+ # object - The model object to generate the select for
+ # method - The attribute on the object
+ # options - Other options pertaining to option tag generation. See
+ # `region_options_for_select`.
+ # html_options - Options to use when generating the select tag- class,
+ # id, etc.
#
# Uses region_options_or_select to generate the list of option tags.
+ #
+ # Example:
+ #
+ # country_select(@object, :region, {priority: ['US', 'CA']}, class: 'region')
+ #
+ # Returns an `html_safe` string containing the HTML for a select element.
def country_select(object, method, options={}, html_options={})
tag = InstanceTag.new(object, method, self, options.delete(:object))
tag.to_region_select_tag(Carmen::World.instance, options, html_options)
end
- # Generate option tags for the subregions of a region.
+ # Generate option tags for a collection of regions.
+ #
+ # regions - An array or Carmen::RegionCollection containing Carmen::Regions
+ # selected - the code of the region that should be selected
+ # options - The hash of options used to customize the output (default: {}):
#
# To use priority regions (which are included in a special section at the
# top of the list), provide an array of region codes at the :priority
# option:
#
- # region_options_for_select(@region, 'US', priority: ['US', 'CA'])
+ # region_options_for_select(@region.subregions, 'US', priority: ['US', 'CA'])
#
# Returns an `html_safe` string containing option tags.
- def region_options_for_select(parent_region, selected=nil, options={})
+ def region_options_for_select(regions, selected=nil, options={})
options.stringify_keys!
priority_region_codes = options['priority'] || []
region_options = ""
unless priority_region_codes.empty?
+ unless regions.respond_to?(:coded)
+ regions = Carmen::RegionCollection.new(regions)
+ end
+
priority_regions = priority_region_codes.map do |code|
- region = parent_region.subregions.coded(code)
+ region = regions.coded(code)
[region.name, region.code] if region
end.compact
unless priority_regions.empty?
@@ -44,29 +84,57 @@ def region_options_for_select(parent_region, selected=nil, options={})
end
end
- main_options = parent_region.subregions.map { |r| [r.name, r.code] }
+ main_options = regions.map { |r| [r.name, r.code] }
main_options.sort!{|a, b| a.first.unpack('U').to_s <=> b.first.unpack('U').to_s}
region_options += options_for_select(main_options, selected)
region_options.html_safe
end
- # Return select tag with the name provided containing country option
- # tags.
+ # Generate select and country option tags with the provided name. A
+ # common use of this would be to allow users to select a country name
+ # inside a web form.
+ #
+ # name - The name attribute for the select element.
+ # options - Other options pertaining to option tag generation. See
+ # `region_options_for_select`.
+ # html_options - Options to use when generating the select tag- class,
+ # id, etc.
#
# Uses region_options_or_select to generate the list of option tags.
+ #
+ # Example:
+ #
+ # country_select_tag('country_code', {priority: ['US', 'CA']}, class: 'region')
+ #
+ # Returns an `html_safe` string containing the HTML for a select element.
def country_select_tag(name, value, options={})
subregion_select_tag(name, value, Carmen::World.instance, options)
end
+
+ # Generate select and subregion option tags for the given object and method. A
+ # common use of this would be to allow users to select a state subregion within
+ # a given country.
#
- # Return select tag with the name provided containing subregion option
- # tags.
+ # name - The name attribute for the select element.
+ # parent_region_or_code - An instance of Carmen::Region or a 2-character
+ # country code.
+ # options - Other options pertaining to option tag generation. See
+ # `region_options_for_select`.
+ # html_options - Options to use when generating the select tag- class,
+ # id, etc.
#
# Uses region_options_or_select to generate the list of option tags.
- def subregion_select_tag(name, value, parent_region_or_code, options = {})
+ #
+ # Example:
+ #
+ # subregion_select_tag('state_code', 'US', {priority: ['US', 'CA']}, class: 'region')
+ #
+ # Returns an `html_safe` string containing the HTML for a select element.
+ def subregion_select_tag(name, value, parent_region_or_code, options = {}, html_options = {})
options.stringify_keys!
parent_region = determine_parent(parent_region_or_code)
priority_regions = options.delete(:priority) || []
- opts = region_options_for_select(parent_region, value, :priority => priority_regions)
+ opts = region_options_for_select(parent_region.subregions, value, :priority => priority_regions)
html_options = {"name" => name,
"id" => sanitize_to_id(name)}.update(options.stringify_keys)
content_tag(:select, opts, html_options)
@@ -94,17 +162,27 @@ def to_region_select_tag(parent_region, options, html_options)
add_default_name_and_id(html_options)
priority_regions = options[:priority] || []
value = value(object)
- opts = add_options(region_options_for_select(parent_region, value, :priority => priority_regions), options, value)
+ opts = add_options(region_options_for_select(parent_region.subregions, value, :priority => priority_regions), options, value)
content_tag("select", opts, html_options)
end
end
class FormBuilder
+ # Generate select and country option tags with the provided name. A
+ # common use of this would be to allow users to select a country name inside a
+ # web form.
+ #
+ # See `FormOptionsHelper::country_select` for more information.
def country_select(method, options = {}, html_options = {})
@template.country_select(@object_name, method,
options.merge(:object => @object), html_options)
end
+ # Generate select and subregion option tags with the provided name. A
+ # common use of this would be to allow users to select a state subregion within
+ # a given country.
+ #
+ # See `FormOptionsHelper::subregion_select` for more information.
def subregion_select(method, parent_region_or_code, options={}, html_options={})
@template.subregion_select(@object_name, method, parent_region_or_code,
options.merge(:object => @object), html_options)
@@ -125,6 +125,31 @@ def test_basic_subregion_select
assert_equal_markup(expected, html)
end
+ def test_region_options_for_select
+ regions = Carmen::Country.all
+ expected = <<-HTML
+ <option value="ES">Eastasia</option>
+ <option value="EU">Eurasia</option>
+ <option value="OC" selected="selected">Oceania</option>
+ HTML
+ html = region_options_for_select(regions, 'OC')
+
+ assert_equal_markup(expected, html)
+ end
+
+ def test_region_options_for_select_with_array_of_regions_and_priority
+ regions = [Carmen::Country.coded('ES'), Carmen::Country.coded('EU')]
+ expected = <<-HTML
+ <option value="ES">Eastasia</option>
+ <option disabled>-------------</option>
+ <option value="ES">Eastasia</option>
+ <option value="EU">Eurasia</option>
+ HTML
+ html = region_options_for_select(regions, nil, :priority => ['ES'])
+
+ assert_equal_markup(expected, html)
+ end
+
def method_missing(method, *args)
fail "method_missing #{method}"
end

0 comments on commit ada9fc2

Please sign in to comment.