effective_addresses 1.2.4 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +61 -3
- data/app/assets/javascripts/effective_addresses/address_fields.js.coffee +7 -1
- data/app/helpers/effective_addresses_helper.rb +17 -6
- data/app/models/effective/address.rb +1 -17
- data/app/views/effective/addresses/_address_fields_formtastic.html.haml +38 -25
- data/app/views/effective/addresses/_address_fields_simple_form.html.haml +22 -11
- data/lib/effective_addresses.rb +0 -1
- data/lib/effective_addresses/version.rb +1 -1
- data/lib/generators/templates/effective_addresses.rb +6 -4
- data/spec/dummy/app/models/user.rb +22 -22
- metadata +2 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e67a2c4ca21e0c16b9d61346e05f3533ba09b31
|
4
|
+
data.tar.gz: 659e413366e47d7c3c8b2469c8c0887f7cbade9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
-
|
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
|
-
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
-
-
|
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
|
-
|
13
|
-
|
14
|
-
= fa.input :city, :required => required
|
15
|
+
- when :address1
|
16
|
+
= fa.input :address1, :required => required
|
15
17
|
|
16
|
-
|
18
|
+
- when :address2
|
19
|
+
= fa.input :address2
|
17
20
|
|
18
|
-
|
19
|
-
|
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
|
-
|
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
|
data/lib/effective_addresses.rb
CHANGED
@@ -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
|
-
#
|
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
|
-
#
|
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
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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.
|
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-
|
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
|