country_select 1.2.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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