effective_addresses 1.2.4 → 1.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 41c69251c76730e7fe6cf466b4d892e39cdc9569
4
- data.tar.gz: 9561541536799e5f8f4d3fab9a8f23390c9d45d5
3
+ metadata.gz: 1e67a2c4ca21e0c16b9d61346e05f3533ba09b31
4
+ data.tar.gz: 659e413366e47d7c3c8b2469c8c0887f7cbade9a
5
5
  SHA512:
6
- metadata.gz: f135e6e8b0d6512f62df507af47590ca7b7aa2ab9a1960337afac042809b94099c025731542b698c342c9fd4c0f3eacc4e3041a1b5a33fbcfabae9160a6f0a14
7
- data.tar.gz: 4e49543e8691690ac0978dc2ae5b15dd0427c6450769f2660f0b7c4c982e9addb856495918c4b5d9c4173b68a3d01145e2d22868422671a769ed893ab838eb06
6
+ metadata.gz: 23c02018590042e590c457e702a9178cbbdd34b9f90bfb92bf610e9519cb9067f9212af07d77e4c0aec1ef8f1b9f91010b45c709e1fa890b1b6b4e066ced7025
7
+ data.tar.gz: ba069457c8055a65af00fc91fdd77a3a5a55cd54737d211262e38bbaad0551147fe012665bc78122c29799b6eb70ed90a46106a2d7c00335aadd37a1d9960924
data/README.md CHANGED
@@ -165,7 +165,13 @@ The actual permitted parameters are:
165
165
 
166
166
  ### Form Helpers
167
167
 
168
- Use the helper in a Formtastic or SimpleForm form to quickly create the address fields. This example is in HAML:
168
+ Use the helper in a Formtastic or SimpleForm form to quickly create the address fields. Currently only supports Formtastic and SimpleForm.
169
+
170
+ When you select a country from the select input an AJAX GET request will be made to `effective_addresses.address_subregions_path` (`/addresses/subregions/:country_code`)
171
+ which populates the province/state dropdown with the selected country's states or provinces.
172
+
173
+
174
+ #### Formtastic
169
175
 
170
176
  ```ruby
171
177
  = semantic_form_for @user do |f|
@@ -173,7 +179,11 @@ Use the helper in a Formtastic or SimpleForm form to quickly create the address
173
179
  = effective_address_fields(f, :billing_address)
174
180
 
175
181
  = f.action :submit
182
+ ```
176
183
 
184
+ #### SimpleForm
185
+
186
+ ```ruby
177
187
  = simple_form_for @user do |f|
178
188
  %h3 Billing Address
179
189
  = effective_address_fields(f, :billing_address)
@@ -181,9 +191,57 @@ Use the helper in a Formtastic or SimpleForm form to quickly create the address
181
191
  = f.submit 'Save'
182
192
  ```
183
193
 
184
- Currently only supports Formtastic and SimpleForm.
194
+ #### Field Ordering
195
+ You may choose to order fields different than the default, such as putting the country first. You can do so with the `:field_order` option, for example:
196
+ ```ruby
197
+ = simple_form_for @user do |f|
198
+ %h3 Billing Address
199
+ = effective_address_fields(f, :billing_address, :field_order => [:country_code, :full_name, :address1, :address2, :city, :state_code, :postal_code])
200
+
201
+ = f.submit 'Save'
202
+ ```
185
203
 
186
- When you select a country from the select input an AJAX GET request will be made to `effective_addresses.address_subregions_path` (`/addresses/subregions/:country_code`) which populates the province/state dropdown with the selected country's states or provinces.
204
+ ## Geocoder option
205
+
206
+ Effective addresses has an optional integration with [Geocoder](https://github.com/alexreisner/geocoder). At it's simplest, this provides preselection and prefill of `country`, `state`, `city`, and `postal_code` based on the user's IP address. See [Geocoder](https://github.com/alexreisner/geocoder) for
207
+ a complete list of possibilities.
208
+
209
+ ### Installation and Setup
210
+
211
+ ```ruby
212
+ gem 'geocoder'
213
+ ```
214
+
215
+ Add `config/initializer/geocoder.rb`, below is a sample:
216
+
217
+ ```ruby
218
+ Geocoder.configure(
219
+ # geocoding options
220
+
221
+ # IP address geocoding service (see below for supported options):
222
+ # https://github.com/alexreisner/geocoder#ip-address-services
223
+ ip_lookup: :telize,
224
+ cache: Rails.cache,
225
+ cache_prefix: 'geocoder:'
226
+ )
227
+
228
+ # Provide a hardcoded ip of 1.2.3.4 when in developmnt/test and the ip address resolves as localhost
229
+ if %w(development test).include? Rails.env
230
+ module Geocoder
231
+ module Request
232
+ def geocoder_spoofable_ip_with_localhost_override
233
+ ip_candidate = geocoder_spoofable_ip_without_localhost_override
234
+ if ip_candidate == '127.0.0.1'
235
+ '1.2.3.4'
236
+ else
237
+ ip_candidate
238
+ end
239
+ end
240
+ alias_method_chain :geocoder_spoofable_ip, :localhost_override
241
+ end
242
+ end
243
+ end
244
+ ```
187
245
 
188
246
 
189
247
  ## License
@@ -1,9 +1,15 @@
1
1
  $(document).on 'change', "select[data-effective-address-country]", (event) ->
2
2
  country_code = $(this).val()
3
3
  uuid = $(this).data('effective-address-country')
4
+ form = $(this).closest('form')
4
5
 
6
+ # clear postal_code and city values on country change
7
+ form.find("input[data-effective-address-postal-code='#{uuid}']").val('')
8
+ form.find("input[data-effective-address-city='#{uuid}']").val('')
9
+
10
+ # load state options
5
11
  url = "/addresses/subregions/#{country_code}"
6
- state_select = $(this).closest('form').find("select[data-effective-address-state='#{uuid}']").first()
12
+ state_select = form.find("select[data-effective-address-state='#{uuid}']").first()
7
13
 
8
14
  if country_code.length == 0
9
15
  state_select.prop('disabled', true).addClass('disabled').parent('.form-group').addClass('disabled')
@@ -1,6 +1,8 @@
1
1
  require 'carmen-rails'
2
2
 
3
3
  module EffectiveAddressesHelper
4
+ @@use_geocoder = defined?(Geocoder)
5
+
4
6
  def effective_address_fields(form, method = 'billing', options = {})
5
7
  method = (method.to_s.include?('_address') ? method.to_s : "#{method}_address")
6
8
 
@@ -8,13 +10,9 @@ module EffectiveAddressesHelper
8
10
  use_full_name = form.object._validators[method.to_sym].any? { |v| v.kind_of?(EffectiveAddressFullNamePresenceValidator) }
9
11
 
10
12
  address = form.object.send(method) || form.object.addresses.build(:category => method.to_s.gsub('_address', ''))
13
+ effective_address_pre_select(address) if address.new_record?
11
14
 
12
- if address.new_record? && EffectiveAddresses.pre_selected_country.present?
13
- address.country = EffectiveAddresses.pre_selected_country
14
- address.state = EffectiveAddresses.pre_selected_state if (address.country.present? && EffectiveAddresses.pre_selected_state.present?)
15
- end
16
-
17
- opts = {:required => required, :use_full_name => use_full_name}.merge(options).merge({:f => form, :address => address, :method => method})
15
+ opts = {:required => required, :use_full_name => use_full_name, :field_order => [:full_name, :address1, :address2, :city, :country_code, :state_code, :postal_code]}.merge(options).merge({:f => form, :address => address, :method => method})
18
16
 
19
17
  if form.class.name == 'SimpleForm::FormBuilder'
20
18
  render :partial => 'effective/addresses/address_fields_simple_form', :locals => opts
@@ -25,6 +23,19 @@ module EffectiveAddressesHelper
25
23
  end
26
24
  end
27
25
 
26
+ def effective_address_pre_select(address)
27
+ if EffectiveAddresses.pre_selected_country.present?
28
+ address.country = EffectiveAddresses.pre_selected_country
29
+ address.state = EffectiveAddresses.pre_selected_state if (result[0].present? && EffectiveAddresses.pre_selected_state.present?)
30
+ elsif @@use_geocoder && request.location.present?
31
+ data = request.location.data
32
+ address.country = data['country_code']
33
+ address.state = data['region_code']
34
+ address.postal_code = data['postal_code']
35
+ address.city = data['city']
36
+ end
37
+ end
38
+
28
39
  def region_options_for_simple_form_select(regions = nil)
29
40
  if regions.present?
30
41
  countries = regions
@@ -9,23 +9,7 @@ module Effective
9
9
 
10
10
  belongs_to :addressable, :polymorphic => true, :touch => true
11
11
 
12
- structure do
13
- category :string, :validates => [:presence]
14
-
15
- full_name :string
16
-
17
- address1 :string, :validates => [:presence]
18
- address2 :string
19
-
20
- city :string, :validates => [:presence]
21
-
22
- state_code :string
23
- country_code :string, :validates => [:presence]
24
-
25
- postal_code :string, :validates => [:presence]
26
-
27
- timestamps
28
- end
12
+ validates_presence_of :category, :address1, :city, :country_code, :postal_code
29
13
 
30
14
  validates_presence_of :state_code, :if => Proc.new { |address| address.country_code.blank? || Carmen::Country.coded(address.country_code).try(:subregions).present? }
31
15
 
@@ -5,28 +5,41 @@
5
5
  - if ((f.object.errors.include?(method) && !f.object.errors.include?(:addresses)) rescue false)
6
6
  - fa.object.errors.add(:address1, f.object.errors[method].first)
7
7
 
8
- - if use_full_name || fa.object.errors.include?(:full_name)
9
- = fa.input :full_name, :required => true, :label => 'Full name', :placeholder => 'Full name'
10
-
11
- = fa.input :address1, :placeholder => 'Address', :label => "Address 1"
12
- = fa.input :address2, :label => 'Address 2'
13
- = fa.input :city, :placeholder => 'City'
14
- = fa.input :country_code,
15
- :as => :select,
16
- :label => 'Country',
17
- :prompt => 'Country...',
18
- :collection => region_options_for_select(EffectiveAddresses.country_codes == :all ? Carmen::Country.all : Carmen::Country.all.select{ |c| EffectiveAddresses.country_codes.include?(c.code) rescue true}, fa.object.country_code, :priority => EffectiveAddresses.country_codes_priority),
19
- :input_html => { 'data-effective-address-country' => uuid }
20
-
21
- - if fa.object.country_code.present?
22
- = fa.input :state_code, :as => :select, :label => 'Province / State',
23
- :collection => region_options_for_select(Carmen::Country.coded(fa.object.country_code).subregions, fa.object.state_code),
24
- :prompt => 'please select a country',
25
- :input_html => { 'data-effective-address-state' => uuid }
26
- - else
27
- = fa.input :state_code, :as => :select, :label => 'Province / State',
28
- :collection => [],
29
- :prompt => 'please select a country',
30
- :input_html => {:disabled => 'disabled', 'data-effective-address-state' => uuid}
31
-
32
- = fa.input :postal_code, :label => 'Postal / Zip code', :placeholder => 'Postal / Zip code'
8
+ - field_order.each do |field|
9
+
10
+ - case field
11
+ - when :full_name
12
+ - if use_full_name || fa.object.errors.include?(:full_name)
13
+ = fa.input :full_name, :required => true, :label => 'Full name', :placeholder => 'Full name'
14
+
15
+ - when :address1
16
+ = fa.input :address1, :placeholder => 'Address', :label => "Address 1"
17
+
18
+ - when :address2
19
+ = fa.input :address2, :label => 'Address 2'
20
+
21
+ - when :city
22
+ = fa.input :city, :placeholder => 'City'
23
+
24
+ - when :country_code
25
+ = fa.input :country_code,
26
+ :as => :select,
27
+ :label => 'Country',
28
+ :prompt => 'Country...',
29
+ :collection => region_options_for_select(EffectiveAddresses.country_codes == :all ? Carmen::Country.all : Carmen::Country.all.select{ |c| EffectiveAddresses.country_codes.include?(c.code) rescue true}, fa.object.country_code, :priority => EffectiveAddresses.country_codes_priority),
30
+ :input_html => { 'data-effective-address-country' => uuid }
31
+
32
+ - when :state_code
33
+ - if fa.object.country_code.present?
34
+ = fa.input :state_code, :as => :select, :label => 'Province / State',
35
+ :collection => region_options_for_select(Carmen::Country.coded(fa.object.country_code).subregions, fa.object.state_code),
36
+ :prompt => 'please select a country',
37
+ :input_html => { 'data-effective-address-state' => uuid }
38
+ - else
39
+ = fa.input :state_code, :as => :select, :label => 'Province / State',
40
+ :collection => [],
41
+ :prompt => 'please select a country',
42
+ :input_html => {:disabled => 'disabled', 'data-effective-address-state' => uuid}
43
+
44
+ - when :postal_code
45
+ = fa.input :postal_code, :label => 'Postal / Zip code', :placeholder => 'Postal / Zip code'
@@ -5,19 +5,30 @@
5
5
  - if ((f.object.errors.include?(method) && !f.object.errors.include?(:addresses)) rescue false)
6
6
  - fa.object.errors.add(:address1, f.object.errors[method].first)
7
7
 
8
- - if use_full_name || fa.object.errors.include?(:full_name)
9
- = fa.input :full_name, :required => required
8
+ - field_order.each do |field|
10
9
 
10
+ - case field
11
+ - when :full_name
12
+ - if use_full_name || fa.object.errors.include?(:full_name)
13
+ = fa.input :full_name, :required => required
11
14
 
12
- = fa.input :address1, :required => required
13
- = fa.input :address2
14
- = fa.input :city, :required => required
15
+ - when :address1
16
+ = fa.input :address1, :required => required
15
17
 
16
- = fa.input :country_code, :as => :select, :collection => region_options_for_simple_form_select(), :input_html => {'data-effective-address-country' => uuid}, :required => required
18
+ - when :address2
19
+ = fa.input :address2
17
20
 
18
- - if fa.object.try(:country_code).present?
19
- = fa.input :state_code, :as => :select, :collection => region_options_for_simple_form_select(Carmen::Country.coded(fa.object.country_code).subregions), :input_html => {'data-effective-address-state' => uuid}, :required => required
20
- - else
21
- = fa.input :state_code, :as => :select, :disabled => true, :collection => [], :input_html => { 'data-effective-address-state' => uuid }, :required => required
21
+ - when :city
22
+ = fa.input :city, :input_html => { 'data-effective-address-city' => uuid }, :required => required
22
23
 
23
- = fa.input :postal_code, :required => required
24
+ - when :country_code
25
+ = fa.input :country_code, :as => :select, :collection => region_options_for_simple_form_select(), :input_html => {'data-effective-address-country' => uuid}, :required => required
26
+
27
+ - when :state_code
28
+ - if fa.object.try(:country_code).present?
29
+ = fa.input :state_code, :as => :select, :collection => region_options_for_simple_form_select(Carmen::Country.coded(fa.object.country_code).subregions), :input_html => {'data-effective-address-state' => uuid}, :required => required
30
+ - else
31
+ = fa.input :state_code, :as => :select, :disabled => true, :collection => [], :input_html => { 'data-effective-address-state' => uuid }, :required => required
32
+
33
+ - when :postal_code
34
+ = fa.input :postal_code, :input_html => { 'data-effective-address-postal-code' => uuid }, :required => required
@@ -1,6 +1,5 @@
1
1
  require "effective_addresses/engine"
2
2
  require "effective_addresses/version"
3
- require 'migrant' # Required for rspec to run properly
4
3
 
5
4
  module EffectiveAddresses
6
5
 
@@ -1,3 +1,3 @@
1
1
  module EffectiveAddresses
2
- VERSION = '1.2.4'.freeze
2
+ VERSION = '1.3.0'.freeze
3
3
  end
@@ -13,13 +13,15 @@ EffectiveAddresses.setup do |config|
13
13
  # Select these countries ontop of the others
14
14
  config.country_codes_priority = ['US', 'CA'] # nil for no priority countries
15
15
 
16
- # Preselect this country on any new address forms
17
- # Valid values are: country code, country name, or nil
16
+ # Force this country to be preselected on any new address forms.
17
+ # Valid values are: country code, country name, or nil.
18
+ # Leave nil if using Geocoder for IP based discovery.
18
19
  config.pre_selected_country = nil
19
20
 
20
- # Preselect this state on any new address forms
21
+ # Force this state to be preselected on any new address forms.
21
22
  # Must also define pre_selected_country for this to take affect
22
- # Valid values are: state code, state name, or nil
23
+ # Valid values are: state code, state name, or nil.
24
+ # Leave nil if using Geocoder for IP based discovery.
23
25
  config.pre_selected_state = nil
24
26
 
25
27
  # Validate that the postal/zip code format is correct for these countries
@@ -1,24 +1,24 @@
1
1
  class User < ActiveRecord::Base
2
- structure do
3
- # Devise attributes
4
- encrypted_password :string
5
- reset_password_token :string
6
- reset_password_sent_at :datetime
7
- remember_created_at :datetime
8
- confirmation_sent_at :datetime
9
- confirmed_at :datetime
10
- confirmation_token :string
11
- unconfirmed_email :string
12
- sign_in_count :integer, :default => 0
13
- current_sign_in_at :datetime
14
- last_sign_in_at :datetime
15
- current_sign_in_ip :string
16
- last_sign_in_ip :string
17
-
18
- email :string
19
- first_name :string
20
- last_name :string
21
-
22
- timestamps
23
- end
2
+ # structure do
3
+ # # Devise attributes
4
+ # encrypted_password :string
5
+ # reset_password_token :string
6
+ # reset_password_sent_at :datetime
7
+ # remember_created_at :datetime
8
+ # confirmation_sent_at :datetime
9
+ # confirmed_at :datetime
10
+ # confirmation_token :string
11
+ # unconfirmed_email :string
12
+ # sign_in_count :integer, :default => 0
13
+ # current_sign_in_at :datetime
14
+ # last_sign_in_at :datetime
15
+ # current_sign_in_ip :string
16
+ # last_sign_in_ip :string
17
+ #
18
+ # email :string
19
+ # first_name :string
20
+ # last_name :string
21
+ #
22
+ # timestamps
23
+ # end
24
24
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_addresses
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.4
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-14 00:00:00.000000000 Z
11
+ date: 2015-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -80,20 +80,6 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: migrant
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :runtime
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: rspec-rails
99
85
  requirement: !ruby/object:Gem::Requirement