country_select 1.2.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -1
  3. data/.rspec +1 -0
  4. data/.travis.yml +35 -11
  5. data/CHANGELOG.md +74 -1
  6. data/Gemfile +6 -1
  7. data/Gemfile.lock +300 -0
  8. data/README.md +138 -25
  9. data/Rakefile +3 -17
  10. data/UPGRADING.md +69 -0
  11. data/country_select.gemspec +11 -9
  12. data/gemfiles/actionpack.edge.gemfile +15 -0
  13. data/gemfiles/actionpack.edge.gemfile.lock +310 -0
  14. data/gemfiles/actionpack3.2.gemfile +8 -4
  15. data/gemfiles/actionpack3.2.gemfile.lock +265 -39
  16. data/gemfiles/actionpack4.0.gemfile +7 -3
  17. data/gemfiles/actionpack4.0.gemfile.lock +260 -36
  18. data/gemfiles/actionpack4.1.gemfile +11 -0
  19. data/gemfiles/actionpack4.1.gemfile.lock +290 -0
  20. data/gemfiles/actionpack4.2.gemfile +14 -0
  21. data/gemfiles/actionpack4.2.gemfile.lock +306 -0
  22. data/gemfiles/actionpack5.0.gemfile +12 -0
  23. data/gemfiles/actionpack5.0.gemfile.lock +311 -0
  24. data/gemfiles/actionpack5.1.gemfile +12 -0
  25. data/gemfiles/actionpack5.1.gemfile.lock +311 -0
  26. data/gemfiles/actionpack5.2.gemfile +12 -0
  27. data/gemfiles/actionpack5.2.gemfile.lock +312 -0
  28. data/lib/country_select.rb +10 -118
  29. data/lib/country_select/country_select_helper.rb +38 -0
  30. data/lib/country_select/formats.rb +7 -0
  31. data/lib/country_select/rails3/country_select_helper.rb +39 -0
  32. data/lib/country_select/tag_helper.rb +118 -0
  33. data/lib/country_select/version.rb +1 -1
  34. data/lib/country_select_without_sort_alphabetical.rb +13 -0
  35. data/spec/country_select_spec.rb +239 -111
  36. data/spec/spec_helper.rb +85 -7
  37. metadata +88 -42
  38. data/Appraisals +0 -19
  39. data/gemfiles/actionpack3.0.gemfile +0 -7
  40. data/gemfiles/actionpack3.0.gemfile.lock +0 -64
  41. data/gemfiles/actionpack3.1.gemfile +0 -7
  42. data/gemfiles/actionpack3.1.gemfile.lock +0 -72
  43. data/lib/country_select/countries.rb +0 -256
@@ -0,0 +1,38 @@
1
+ module ActionView
2
+ module Helpers
3
+ class FormBuilder
4
+ def country_select(method, priority_or_options = {}, options = {}, html_options = {})
5
+ if Hash === priority_or_options
6
+ html_options = options
7
+ options = priority_or_options
8
+ else
9
+ options[:priority_countries] = priority_or_options
10
+ end
11
+
12
+ @template.country_select(@object_name, method, objectify_options(options), @default_options.merge(html_options))
13
+ end
14
+ end
15
+
16
+ module FormOptionsHelper
17
+ def country_select(object, method, options = {}, html_options = {})
18
+ Tags::CountrySelect.new(object, method, self, options, html_options).render
19
+ end
20
+ end
21
+
22
+ module Tags
23
+ class CountrySelect < Base
24
+ include ::CountrySelect::TagHelper
25
+
26
+ def initialize(object_name, method_name, template_object, options, html_options)
27
+ @html_options = html_options
28
+
29
+ super(object_name, method_name, template_object, options)
30
+ end
31
+
32
+ def render
33
+ select_content_tag(country_option_tags, @options, @html_options)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,7 @@
1
+ module CountrySelect
2
+ FORMATS = {}
3
+
4
+ FORMATS[:default] = lambda do |country|
5
+ country.translations[I18n.locale.to_s] || country.name
6
+ end
7
+ end
@@ -0,0 +1,39 @@
1
+ module ActionView
2
+ module Helpers
3
+ class FormBuilder
4
+ def country_select(method, priority_or_options = {}, options = {}, html_options = {})
5
+ if Hash === priority_or_options
6
+ html_options = options
7
+ options = priority_or_options
8
+ else
9
+ options[:priority_countries] = priority_or_options
10
+ end
11
+
12
+ @template.country_select(@object_name, method, objectify_options(options), @default_options.merge(html_options))
13
+ end
14
+ end
15
+
16
+ module FormOptionsHelper
17
+ def country_select(object, method, options = {}, html_options = {})
18
+ CountrySelect.new(object, method, self, options.delete(:object)).render(options, html_options)
19
+ end
20
+ end
21
+
22
+ class CountrySelect < InstanceTag
23
+ include ::CountrySelect::TagHelper
24
+
25
+ def render(options, html_options)
26
+ @options = options
27
+ @html_options = html_options
28
+
29
+ if self.respond_to?(:select_content_tag)
30
+ select_content_tag(country_option_tags, @options, @html_options)
31
+ else
32
+ html_options = @html_options.stringify_keys
33
+ add_default_name_and_id(html_options)
34
+ content_tag(:select, add_options(country_option_tags, options, value(object)), html_options)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,118 @@
1
+ module CountrySelect
2
+ class CountryNotFoundError < StandardError;end
3
+ module TagHelper
4
+ def country_option_tags
5
+ # In Rails 5.2+, `value` accepts no arguments and must also be called
6
+ # called with parens to avoid the local variable of the same name
7
+ # https://github.com/rails/rails/pull/29791
8
+ selected_option = @options.fetch(:selected) do
9
+ if self.method(:value).arity == 0
10
+ value()
11
+ else
12
+ value(@object)
13
+ end
14
+ end
15
+
16
+ option_tags_options = {
17
+ :selected => selected_option,
18
+ :disabled => @options[:disabled]
19
+ }
20
+
21
+ if priority_countries.present?
22
+ priority_countries_options = country_options_for(priority_countries, false)
23
+
24
+ option_tags = options_for_select(priority_countries_options, option_tags_options)
25
+ option_tags += html_safe_newline + options_for_select([priority_countries_divider], disabled: priority_countries_divider)
26
+
27
+ option_tags_options[:selected] = [option_tags_options[:selected]] unless option_tags_options[:selected].kind_of?(Array)
28
+ option_tags_options[:selected].delete_if{|selected| priority_countries_options.map(&:second).include?(selected)}
29
+
30
+ option_tags += html_safe_newline + options_for_select(country_options, option_tags_options)
31
+ else
32
+ option_tags = options_for_select(country_options, option_tags_options)
33
+ end
34
+ end
35
+
36
+ private
37
+ def locale
38
+ @options[:locale]
39
+ end
40
+
41
+ def priority_countries
42
+ @options[:priority_countries]
43
+ end
44
+
45
+ def priority_countries_divider
46
+ @options[:priority_countries_divider] || "-"*15
47
+ end
48
+
49
+ def only_country_codes
50
+ @options[:only]
51
+ end
52
+
53
+ def except_country_codes
54
+ @options[:except]
55
+ end
56
+
57
+ def format
58
+ @options[:format] || :default
59
+ end
60
+
61
+ def country_options
62
+ country_options_for(all_country_codes, true)
63
+ end
64
+
65
+ def all_country_codes
66
+ codes = ISO3166::Country.codes
67
+
68
+ if only_country_codes.present?
69
+ codes & only_country_codes
70
+ elsif except_country_codes.present?
71
+ codes - except_country_codes
72
+ else
73
+ codes
74
+ end
75
+ end
76
+
77
+ def country_options_for(country_codes, sorted=true)
78
+ I18n.with_locale(locale) do
79
+ country_list = country_codes.map do |code_or_name|
80
+ if country = ISO3166::Country.new(code_or_name)
81
+ code = country.alpha2
82
+ elsif country = ISO3166::Country.find_by_name(code_or_name)
83
+ code = country.first
84
+ country = ISO3166::Country.new(code)
85
+ end
86
+
87
+ unless country.present?
88
+ msg = "Could not find Country with string '#{code_or_name}'"
89
+ raise CountryNotFoundError.new(msg)
90
+ end
91
+
92
+ formatted_country = ::CountrySelect::FORMATS[format].call(country)
93
+
94
+ if formatted_country.is_a?(Array)
95
+ formatted_country
96
+ else
97
+ [formatted_country, code]
98
+ end
99
+
100
+ end
101
+
102
+ if sorted
103
+ if country_list.respond_to?(:sort_alphabetical)
104
+ country_list.sort_alphabetical
105
+ else
106
+ country_list.sort
107
+ end
108
+ else
109
+ country_list
110
+ end
111
+ end
112
+ end
113
+
114
+ def html_safe_newline
115
+ "\n".html_safe
116
+ end
117
+ end
118
+ end
@@ -1,3 +1,3 @@
1
1
  module CountrySelect
2
- VERSION = "1.2.0"
2
+ VERSION = '4.0.0'
3
3
  end
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+ require 'countries'
4
+
5
+ require 'country_select/version'
6
+ require 'country_select/formats'
7
+ require 'country_select/tag_helper'
8
+
9
+ if defined?(ActionView::Helpers::Tags::Base)
10
+ require 'country_select/country_select_helper'
11
+ else
12
+ require 'country_select/rails3/country_select_helper'
13
+ end
@@ -1,133 +1,261 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  require 'action_view'
4
6
  require 'country_select'
5
7
 
6
- module ActionView
7
- module Helpers
8
+ describe "CountrySelect" do
9
+ include ActionView::Helpers::TagHelper
10
+ include ActionView::Helpers::FormOptionsHelper
8
11
 
9
- describe CountrySelect do
10
- include TagHelper
12
+ before do
13
+ I18n.available_locales = [:en]
14
+ I18n.locale = :en
15
+ ISO3166.reset
16
+ end
11
17
 
12
- class Walrus
13
- attr_accessor :country_name
14
- end
18
+ class Walrus
19
+ attr_accessor :country_code
20
+ end
15
21
 
16
- let(:walrus) { Walrus.new }
22
+ let(:walrus) { Walrus.new }
23
+ let!(:template) { ActionView::Base.new }
17
24
 
18
- let!(:template) { ActionView::Base.new }
25
+ let(:builder) do
26
+ if defined?(ActionView::Helpers::Tags::Base)
27
+ ActionView::Helpers::FormBuilder.new(:walrus, walrus, template, {})
28
+ else
29
+ ActionView::Helpers::FormBuilder.new(:walrus, walrus, template, {}, Proc.new { })
30
+ end
31
+ end
19
32
 
20
- let(:select_tag) do
21
- "<select id=\"walrus_country_name\" name=\"walrus[country_name]\">"
22
- end
33
+ let(:select_tag) do
34
+ <<-EOS.chomp.strip
35
+ <select id="walrus_country_code" name="walrus[country_code]">
36
+ EOS
37
+ end
23
38
 
24
- let(:selected_us_option) do
25
- if defined?(Tags::Base)
26
- content_tag(:option, 'United States', :selected => :selected, :value => "United States")
27
- else
28
- "<option value=\"United States\" selected=\"selected\">United States</option>"
29
- end
30
- end
39
+ it "selects the value of country_code" do
40
+ tag = options_for_select([['United States', 'US']], 'US')
41
+
42
+ walrus.country_code = 'US'
43
+ t = builder.country_select(:country_code)
44
+ expect(t).to include(tag)
45
+ end
46
+
47
+ it "uses the locale specified by I18n.locale" do
48
+ I18n.available_locales = [:en, :es]
49
+ ISO3166.reset
50
+
51
+ tag = options_for_select([['Estados Unidos', 'US']], 'US')
52
+
53
+ walrus.country_code = 'US'
54
+ original_locale = I18n.locale
55
+ begin
56
+ I18n.locale = :es
57
+ t = builder.country_select(:country_code)
58
+ expect(t).to include(tag)
59
+ ensure
60
+ I18n.locale = original_locale
61
+ end
62
+ end
63
+
64
+ it "accepts a locale option" do
65
+ I18n.available_locales = [:fr]
66
+ ISO3166.reset
67
+
68
+ tag = options_for_select([['États-Unis', 'US']], 'US')
69
+
70
+ walrus.country_code = 'US'
71
+ t = builder.country_select(:country_code, locale: :fr)
72
+ expect(t).to include(tag)
73
+ end
74
+
75
+ it "accepts priority countries" do
76
+ tag = options_for_select(
77
+ [
78
+ ['Latvia','LV'],
79
+ ['United States','US'],
80
+ ['Denmark', 'DK'],
81
+ ['-'*15,'-'*15]
82
+ ],
83
+ selected: 'US',
84
+ disabled: '-'*15
85
+ )
86
+
87
+ walrus.country_code = 'US'
88
+ t = builder.country_select(:country_code, priority_countries: ['LV','US','DK'])
89
+ expect(t).to include(tag)
90
+ end
91
+
92
+ describe "when selected options is not an array" do
93
+ it "selects only the first matching option" do
94
+ tag = options_for_select([["United States", "US"],["Uruguay", "UY"]], "US")
95
+ walrus.country_code = 'US'
96
+ t = builder.country_select(:country_code, priority_countries: ['LV','US'])
97
+ expect(t).to_not include(tag)
98
+ end
99
+ end
100
+
101
+ describe "when selected options is an array" do
102
+ it "selects all options but only once" do
103
+ tag = options_for_select([["United States", "US"],["Uruguay", "UY"],["Spain", "ES"]], "US")
104
+ walrus.country_code = 'US'
105
+ t = builder.country_select(:country_code, {priority_countries: ['LV','US','ES'], selected: ['UY', 'US']}, multiple: true)
106
+ expect(t.scan(options_for_select([["United States", "US"]], "US")).length).to be(1)
107
+ expect(t.scan(options_for_select([["Uruguay", "UY"]], "UY")).length).to be(1)
108
+ end
109
+ end
110
+
111
+ it "displays only the chosen countries" do
112
+ options = [["Denmark", "DK"],["Germany", "DE"]]
113
+ tag = builder.select(:country_code, options)
114
+ walrus.country_code = 'US'
115
+ t = builder.country_select(:country_code, only: ['DK','DE'])
116
+ expect(t).to eql(tag)
117
+ end
118
+
119
+ it "discards some countries" do
120
+ tag = options_for_select([["United States", "US"]])
121
+ walrus.country_code = 'DE'
122
+ t = builder.country_select(:country_code, except: ['US'])
123
+ expect(t).to_not include(tag)
124
+ end
31
125
 
32
- let(:selected_iso_us_option) do
33
- if defined?(Tags::Base)
34
- content_tag(:option, 'United States', :selected => :selected, :value => 'us')
35
- else
36
- "<option value=\"us\" selected=\"selected\">United States</option>"
37
- end
126
+ context "using old 1.x syntax" do
127
+ it "accepts priority countries" do
128
+ tag = options_for_select(
129
+ [
130
+ ['Latvia','LV'],
131
+ ['United States','US'],
132
+ ['Denmark', 'DK'],
133
+ ['-'*15,'-'*15]
134
+ ],
135
+ selected: 'US',
136
+ disabled: '-'*15
137
+ )
138
+
139
+ walrus.country_code = 'US'
140
+ t = builder.country_select(:country_code, ['LV','US','DK'])
141
+ expect(t).to include(tag)
142
+ end
143
+
144
+ it "selects only the first matching option" do
145
+ tag = options_for_select([["United States", "US"],["Uruguay", "UY"]], "US")
146
+ walrus.country_code = 'US'
147
+ t = builder.country_select(:country_code, ['LV','US'])
148
+ expect(t).to_not include(tag)
149
+ end
150
+
151
+ it "supports the country names as provided by default in Formtastic" do
152
+ tag = options_for_select([
153
+ ["Australia", "AU"],
154
+ ["Canada", "CA"],
155
+ ["United Kingdom", "GB"],
156
+ ["United States", "US"]
157
+ ])
158
+ country_names = ["Australia", "Canada", "United Kingdom", "United States"]
159
+ t = builder.country_select(:country_code, country_names)
160
+ expect(t).to include(tag)
161
+ end
162
+
163
+ it "raises an error when a country code or name is not found" do
164
+ country_names = [
165
+ "United States",
166
+ "Canada",
167
+ "United Kingdom",
168
+ "Mexico",
169
+ "Australia",
170
+ "Freedonia"
171
+ ]
172
+ error_msg = "Could not find Country with string 'Freedonia'"
173
+
174
+ expect do
175
+ builder.country_select(:country_code, country_names)
176
+ end.to raise_error(CountrySelect::CountryNotFoundError, error_msg)
177
+ end
178
+
179
+ it "supports the select prompt" do
180
+ tag = '<option value="">Select your country</option>'
181
+ t = builder.country_select(:country_code, prompt: 'Select your country')
182
+ expect(t).to include(tag)
183
+ end
184
+
185
+ it "supports the include_blank option" do
186
+ tag = '<option value=""></option>'
187
+ t = builder.country_select(:country_code, include_blank: true)
188
+ expect(t).to include(tag)
189
+ end
190
+ end
191
+
192
+ it 'sorts unicode' do
193
+ tag = builder.country_select(:country_code, only: ['AX', 'AL', 'AF', 'ZW'])
194
+ order = tag.scan(/value="(\w{2})"/).map { |o| o[0] }
195
+ expect(order).to eq(['AF', 'AX', 'AL', 'ZW'])
196
+ end
197
+
198
+ context "without sort_alphabetical" do
199
+ before do
200
+ Enumerable.send(:alias_method, :_sort_alphabetical, :sort_alphabetical)
201
+ Enumerable.send(:remove_method, :sort_alphabetical)
202
+ end
203
+
204
+ after do
205
+ Enumerable.send(:alias_method, :sort_alphabetical, :_sort_alphabetical)
206
+ end
207
+
208
+ it 'falls back to regular sort' do
209
+ tag = builder.country_select(:country_code, only: ['AX', 'AL', 'AF', 'ZW'])
210
+ order = tag.scan(/value="(\w{2})"/).map { |o| o[0] }
211
+ expect(order).to eq(['AF', 'AL', 'ZW', 'AX'])
212
+ end
213
+ end
214
+
215
+ describe "custom formats" do
216
+ it "accepts a custom formatter" do
217
+ ::CountrySelect::FORMATS[:with_alpha2] = lambda do |country|
218
+ "#{country.name} (#{country.alpha2})"
38
219
  end
39
220
 
40
- let(:builder) do
41
- if defined?(Tags::Base)
42
- FormBuilder.new(:walrus, walrus, template, {})
43
- else
44
- FormBuilder.new(:walrus, walrus, template, {}, Proc.new { })
45
- end
221
+ tag = options_for_select([['United States of America (US)', 'US']], 'US')
222
+
223
+ walrus.country_code = 'US'
224
+ t = builder.country_select(:country_code, format: :with_alpha2)
225
+ expect(t).to include(tag)
226
+ end
227
+
228
+ it "accepts an array for formatter" do
229
+ ::CountrySelect::FORMATS[:with_alpha3] = lambda do |country|
230
+ [country.name, country.alpha3]
46
231
  end
47
232
 
48
- context "iso codes disabled" do
49
- describe "#country_select" do
50
- let(:tag) { builder.country_select(:country_name) }
51
-
52
- it "creates a select tag" do
53
- tag.should include(select_tag)
54
- end
55
-
56
- it "creates option tags of the countries" do
57
- ::CountrySelect::COUNTRIES.each do |code,name|
58
- tag.should include(content_tag(:option, name, :value => name))
59
- end
60
- end
61
-
62
- it "selects the value of country_name" do
63
- walrus.country_name = 'United States'
64
- t = builder.country_select(:country_name)
65
- t.should include(selected_us_option)
66
- end
67
- end
68
-
69
- describe "#priority_countries" do
70
- let(:tag) { builder.country_select(:country_name, ['United States']) }
71
-
72
- it "puts the countries at the top" do
73
- tag.should include("#{select_tag}<option value=\"United States")
74
- end
75
-
76
- it "inserts a divider" do
77
- tag.should include(">United States</option><option value=\"\" disabled=\"disabled\">-------------</option>")
78
- end
79
-
80
- it "does not mark two countries as selected" do
81
- walrus.country_name = "United States"
82
- str = <<-EOS.strip
83
- </option>\n<option value="United States" selected="selected">United States</option>
84
- EOS
85
- tag.should_not include(str)
86
- end
87
- end
233
+ tag = options_for_select([['United States of America', 'USA']], 'USA')
234
+ walrus.country_code = 'USA'
235
+ t = builder.country_select(:country_code, format: :with_alpha3)
236
+ expect(t).to include(tag)
237
+ end
238
+
239
+ it "accepts an array for formatter + custom formatter" do
240
+ ::CountrySelect::FORMATS[:with_alpha3] = lambda do |country|
241
+ ["#{country.name} (#{country.alpha2})", country.alpha3]
88
242
  end
89
243
 
90
- context "iso codes enabled" do
91
- describe "#country_select" do
92
- let(:tag) { builder.country_select(:country_name, nil, :iso_codes => true) }
93
-
94
- it "creates a select tag" do
95
- tag.should include(select_tag)
96
- end
97
-
98
- it "creates option tags of the countries" do
99
- ::CountrySelect::COUNTRIES.each do |code,name|
100
- tag.should include(content_tag(:option, name, :value => code))
101
- end
102
- end
103
-
104
- it "selects the value of country_name" do
105
- walrus.country_name = 'us'
106
- t = builder.country_select(:country_name, nil, :iso_codes => true)
107
- t.should include(selected_iso_us_option)
108
- end
109
- end
110
-
111
- describe "#priority_countries" do
112
- let(:tag) { builder.country_select(:country_name, ['us'], :iso_codes => true) }
113
-
114
- it "puts the countries at the top" do
115
- tag.should include("#{select_tag}<option value=\"us")
116
- end
117
-
118
- it "inserts a divider" do
119
- tag.should include(">United States</option><option value=\"\" disabled=\"disabled\">-------------</option>")
120
- end
121
-
122
- it "does not mark two countries as selected" do
123
- walrus.country_name = "us"
124
- str = <<-EOS.strip
125
- </option>\n<option value="us" selected="selected">United States</option>
126
- EOS
127
- tag.should_not include(str)
128
- end
129
- end
244
+ tag = options_for_select([['United States of America (US)', 'USA']], 'USA')
245
+ walrus.country_code = 'USA'
246
+ t = builder.country_select(:country_code, format: :with_alpha3)
247
+ expect(t).to include(tag)
248
+ end
249
+
250
+ it "marks priority countries as selected only once" do
251
+ ::CountrySelect::FORMATS[:with_alpha3] = lambda do |country|
252
+ [country.name, country.alpha3]
130
253
  end
254
+
255
+ tag = options_for_select([['United States of America', 'USA']], 'USA')
256
+ walrus.country_code = 'USA'
257
+ t = builder.country_select(:country_code, format: :with_alpha3, priority_countries: ['US'])
258
+ expect(t.scan(Regexp.new(Regexp.escape(tag))).size).to eq 1
131
259
  end
132
260
  end
133
261
  end