jt-rails-address 1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5e7d7fb2db68c3f3e8695fd5a95522fc86f73316
4
+ data.tar.gz: 7041289c7bf68a1521b18b8469222fc49ca563cf
5
+ SHA512:
6
+ metadata.gz: a09f08c4ff694d0f80433916db56fb832fdfcedf0e7254d1166522f6db4f6776a883879c7dc94b70df31b5b92f61e79490dd4e540e475cdca8caad3869a0c4c0
7
+ data.tar.gz: e3b03d1954832b3180a25ec1036148c8f313e30924c3f8e2d0ce26d92cb8cfbe75b1f05ba61126891d46b4b403770a3067b61614f4b48fe5fc2c48b7c9102b82
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ *.gem
2
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2015 Jonathan Tribouharet
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,141 @@
1
+ # JTRailsAddress
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/jt-rails-address.svg)](http://badge.fury.io/rb/jt-rails-address)
4
+
5
+ JTRailsAddress simplify postal addresses management and geocoding with Google Maps API in Ruby On Rails and Javascript.
6
+
7
+ ## Installation
8
+
9
+ JTRailsAddress is distributed as a gem, which is how it should be used in your app.
10
+
11
+ Include the gem in your Gemfile:
12
+
13
+ gem 'jt-rails-address', '~> 1.0'
14
+
15
+ ## Usage
16
+
17
+ ### Basic usage
18
+
19
+ In your migration file:
20
+
21
+ ```ruby
22
+ class CreateUsers < ActiveRecord::Migration
23
+ def change
24
+ create_table :users do |t|
25
+
26
+ t.string :username, null: false
27
+ t.string :email, null: false
28
+ t.string :password_digest
29
+
30
+ t.address :address
31
+
32
+ t.timestamps null: false
33
+ end
34
+ end
35
+ end
36
+ ```
37
+
38
+ It will create all the fields you need for address management:
39
+
40
+ - `formatted_address`, "Empire State Building, 350 5th Ave, New York, NY 10118"
41
+ - `street_number`, "350"
42
+ - `street_name`, "5th Ave"
43
+ - `street`, "350 5th Ave", it's a concatenation of `street_number` and `street_name`
44
+ - `city`
45
+ - `zip_code`
46
+ - `department`
47
+ - `department_code`
48
+ - `state`
49
+ - `state_code`
50
+ - `country`
51
+ - `country_code`
52
+ - `lat`, GPS latitude
53
+ - `lng`, GPS longitude
54
+
55
+ In your model:
56
+ ```ruby
57
+ class User < ActiveRecord::Base
58
+
59
+ has_address :address
60
+
61
+ end
62
+ ```
63
+
64
+ It will only add a virtual field named `address`.
65
+
66
+ ### Javascript usage with Google Maps API
67
+
68
+ You probably want to use an autocompletion service like Google Maps API.
69
+
70
+ In your HTML:
71
+ ```html
72
+ <!-- Basic form, address is just a virtual field used for searching the address on Google Maps API -->
73
+ <%= form_for @user do |f| %>
74
+
75
+ <div class="jt-address-autocomplete">
76
+ <%= f.text_field :address, class: 'jt-address-search' %>
77
+
78
+ <% for attr in JT::Rails::Address.fields %>
79
+ <%= f.hidden_field "address_#{attr}", class: "jt-address-field-#{attr}" %>
80
+ <% end %>
81
+ </div>
82
+
83
+ <%= f.submit %>
84
+
85
+ <% end %>
86
+
87
+ <!-- Load Google Maps -->
88
+ <script async type="text/javascript" src="//maps.googleapis.com/maps/api/js?libraries=places&callback=googleMapInitialize"></script>
89
+ ```
90
+
91
+ In your `applicaton.js` you have to add:
92
+ ```javascript
93
+ //= require jt_address
94
+
95
+ // This function is call when Google Maps is loaded
96
+ window.googleMapInitialize = function(){
97
+
98
+ // Simple usage
99
+ $('.jt-address-autocomplete').jt_address();
100
+
101
+ // Advacned usage
102
+ $('.jt-address-autocomplete').jt_address({
103
+ types: ['geocode'],
104
+ componentRestrictions: { country: 'fr' }
105
+ });
106
+
107
+ };
108
+ ```
109
+
110
+ Each time the data for the address change, an event `jt:address:data_changed` is triggered.
111
+ You can catch it with:
112
+
113
+ ```javascript
114
+ $('.jt-address-autocomplete').on('jt:address:data_changed', function(data){
115
+ console.log(data);
116
+ });
117
+
118
+ ```
119
+
120
+ ### Google Maps API in Ruby
121
+
122
+ Thanks to [graticule](https://github.com/collectiveidea/graticule), there is a simple way to use autocomplete in Ruby.
123
+
124
+ ```ruby
125
+ # Simple usage
126
+ data = JT::Rails::Address.search("Eiffel Tower", "YOUR GOOGLE API KEY")
127
+
128
+ # Advanced usage
129
+ data = JT::Rails::Address.search("Eiffel Tower", "YOUR GOOGLE API KEY", {components: 'country:fr'})
130
+
131
+ # Use the data retrieve from Google Maps API
132
+ my_instance.load_address(:address, data)
133
+ ```
134
+
135
+ ## Author
136
+
137
+ - [Jonathan Tribouharet](https://github.com/jonathantribouharet) ([@johntribouharet](https://twitter.com/johntribouharet))
138
+
139
+ ## License
140
+
141
+ JTRailsAddress is released under the MIT license. See the LICENSE file for more info.
@@ -0,0 +1,15 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'jt-rails-address'
3
+ s.summary = "Postal addresses management in Ruby On Rails and Javascript"
4
+ s.description = "JTRailsAddress simplify postal addresses management and geocoding with Google Maps in Ruby On Rails and Javascript."
5
+ s.homepage = 'https://github.com/jonathantribouharet/jt-rails-address'
6
+ s.version = '1.0.0'
7
+ s.files = `git ls-files`.split("\n")
8
+ s.require_paths = ['lib']
9
+ s.authors = ['Jonathan TRIBOUHARET']
10
+ s.email = 'jonathan.tribouharet@gmail.com'
11
+ s.license = 'MIT'
12
+ s.platform = Gem::Platform::RUBY
13
+
14
+ s.add_dependency('graticule', '> 2.0')
15
+ end
@@ -0,0 +1,93 @@
1
+ module JT
2
+ module Rails
3
+ module Address
4
+ end
5
+ end
6
+ end
7
+
8
+ require 'graticule'
9
+ require 'schema'
10
+ require 'validators'
11
+
12
+ module JT::Rails::Address
13
+
14
+ module Rails
15
+ class Engine < ::Rails::Engine
16
+ # Get rails to add app, lib, vendor to load path
17
+ end
18
+ end
19
+
20
+ class Railtie < ::Rails::Railtie
21
+ initializer 'jt_rails_addresses.insert_into_active_record' do |app|
22
+ ActiveSupport.on_load :active_record do
23
+ ActiveRecord::ConnectionAdapters::Table.send :include, JT::Rails::Address::Schema::TableDefinition
24
+ ActiveRecord::ConnectionAdapters::TableDefinition.send :include, JT::Rails::Address::Schema::TableDefinition
25
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.send :include, JT::Rails::Address::Schema::Statements
26
+
27
+ ActiveRecord::Base.send :include, JT::Rails::Address::Validators
28
+ end
29
+ end
30
+ end
31
+
32
+ def self.fields
33
+ JT::Rails::Address::Schema::COLUMNS.keys
34
+ end
35
+
36
+ def self.search(text, google_api_key, options = {})
37
+ geocoder = Graticule.service(:google).new(google_api_key)
38
+
39
+ begin
40
+ request_params = options.merge({ address: text })
41
+ response = geocoder.send('make_url', request_params).open('User-Agent' => Graticule::Geocoder::Base::USER_AGENT).read
42
+ json = JSON.parse(response)
43
+
44
+ return nil if !json['results'] || json['results'].size == 0
45
+
46
+ place = json['results'][0]
47
+
48
+ data = {}
49
+ data['lat'] = place['geometry']['location']['lat']
50
+ data['lng'] = place['geometry']['location']['lng']
51
+
52
+ data['formatted_address'] = place['formatted_address']
53
+
54
+ for address_component in place['address_components']
55
+
56
+ if address_component['types'][0] == 'street_number'
57
+ data['street_number'] = address_component['long_name']
58
+ elsif address_component['types'][0] == 'route'
59
+ data['street_name'] = address_component['long_name']
60
+ elsif address_component['types'][0] == 'country'
61
+ data['country'] = address_component['long_name']
62
+ data['country_code'] = address_component['short_name']
63
+ elsif address_component['types'][0] == 'administrative_area_level_1'
64
+ data['state'] = address_component['long_name']
65
+ data['state_code'] = address_component['short_name']
66
+ elsif address_component['types'][0] == 'administrative_area_level_2'
67
+ data['department'] = address_component['long_name']
68
+ data['department_code'] = address_component['short_name']
69
+ elsif address_component['types'][0] == 'locality' || address_component['types'][0] == 'administrative_area3'
70
+ data['city'] = address_component['long_name']
71
+ elsif address_component['types'][0] == 'postal_code'
72
+ data['zip_code'] = address_component['long_name']
73
+ end
74
+
75
+ end
76
+
77
+ if !data['street_name'].blank?
78
+ if !data['street_number'].blank?
79
+ data['street'] = "#{data['street_number']} #{data['street_name']}"
80
+ else
81
+ data['street'] = data['street_name']
82
+ end
83
+ end
84
+
85
+ return data
86
+ rescue Exception => e
87
+ STDERR.puts e.message
88
+ end
89
+
90
+ return nil
91
+ end
92
+
93
+ end
data/lib/schema.rb ADDED
@@ -0,0 +1,54 @@
1
+ module JT::Rails::Address::Schema
2
+
3
+ COLUMNS = {
4
+ formatted_address: :string,
5
+ street_number: :string,
6
+ street_name: :string,
7
+ street: :string,
8
+ city: :string,
9
+ zip_code: :string,
10
+ department: :string,
11
+ department_code: :string,
12
+ state: :string,
13
+ state_code: :string,
14
+ country: :string,
15
+ country_code: :string,
16
+ lat: :float,
17
+ lng: :float,
18
+ }
19
+
20
+ module Statements
21
+ def add_address(table_name, *arguments)
22
+ raise ArgumentError, "Please specify name in your add_address call in your migration." if arguments.empty?
23
+
24
+ arguments.each do |prefix|
25
+ COLUMNS.each_pair do |column_name, column_type|
26
+ add_column(table_name, "#{prefix}_#{column_name}", column_type)
27
+ end
28
+ end
29
+ end
30
+
31
+ def remove_address(table_name, *arguments)
32
+ raise ArgumentError, "Please specify name in your remove_address call in your migration." if arguments.empty?
33
+
34
+ arguments.each do |prefix|
35
+ COLUMNS.each_pair do |column_name, column_type|
36
+ remove_column(table_name, "#{prefix}_#{column_name}", column_type)
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ module TableDefinition
43
+ def address(*arguments)
44
+ raise ArgumentError, "Please specify name in your address call in your migration." if arguments.empty?
45
+
46
+ arguments.each do |prefix|
47
+ COLUMNS.each_pair do |column_name, column_type|
48
+ column("#{prefix}_#{column_name}", column_type)
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ end
data/lib/validators.rb ADDED
@@ -0,0 +1,23 @@
1
+ module JT::Rails::Address::Validators
2
+
3
+ extend ActiveSupport::Concern
4
+
5
+ class_methods do
6
+
7
+ def has_address(prefix, options = {})
8
+ attr_accessor prefix
9
+ end
10
+
11
+ end
12
+
13
+ def load_address(prefix, data)
14
+ for field in JT::Rails::Address.fields
15
+ self["#{prefix}_#{field}"] = nil
16
+ end
17
+
18
+ for key, value in data
19
+ self["#{prefix}_#{key}"] = value
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,106 @@
1
+ ;(function($){
2
+
3
+ $.fn.jt_address = function(options) {
4
+
5
+ return this.each(function() {
6
+ setupInput($(this), options);
7
+ });
8
+
9
+ function setupInput($container, options){
10
+ var $input = $container.find('input[type="text"].jt-address-search').first();
11
+ if($input.length == 0){
12
+ $input = $container.find('input[type="text"]').first();
13
+ }
14
+
15
+ $input.on('input', function(){
16
+ inputChanged($container);
17
+ });
18
+
19
+ $input.on('change', function(){
20
+ inputChanged($container);
21
+ });
22
+
23
+ var autocomplete = new google.maps.places.Autocomplete($input[0], options);
24
+
25
+ google.maps.event.addListener(autocomplete, 'place_changed', function(){
26
+ var place = autocomplete.getPlace();
27
+ var data = {};
28
+
29
+ if(!place.geometry){
30
+ dataChanged($container, {});
31
+ return;
32
+ }
33
+
34
+ data['lat'] = place.geometry.location.lat();
35
+ data['lng'] = place.geometry.location.lng();
36
+
37
+ data['formatted_address'] = place['formatted_address'];
38
+
39
+ for(var i = 0; i < place.address_components.length; ++i){
40
+ if(place.address_components[i].types[0] == 'street_number'){
41
+ data['street_number'] = place.address_components[i].long_name;
42
+ }
43
+ else if(place.address_components[i].types[0] == 'route'){
44
+ data['street_name'] = place.address_components[i].long_name;
45
+ }
46
+ else if(place.address_components[i].types[0] == 'country'){
47
+ data['country'] = place.address_components[i].long_name;
48
+ data['country_code'] = place.address_components[i].short_name;
49
+ }
50
+ else if(place.address_components[i].types[0] == 'administrative_area_level_1'){
51
+ data['state'] = place.address_components[i].long_name;
52
+ data['state_code'] = place.address_components[i].short_name;
53
+ }
54
+ else if(place.address_components[i].types[0] == 'administrative_area_level_2'){
55
+ data['department'] = place.address_components[i].long_name;
56
+ data['department_code'] = place.address_components[i].short_name;
57
+ }
58
+ else if(place.address_components[i].types[0] == 'locality' ||
59
+ place.address_components[i].types[0] == 'administrative_area3'){
60
+ data['city'] = place.address_components[i].long_name;
61
+ }
62
+ else if(place.address_components[i].types[0] == 'postal_code'){
63
+ data['zip_code'] = place.address_components[i].long_name;
64
+ }
65
+ }
66
+
67
+ if(data['street_name']){
68
+ if(data['street_number']){
69
+ data['street'] = data['street_number'] + ' ' + data['street_name'];
70
+ }
71
+ else{
72
+ data['street'] = data['street_name'];
73
+ }
74
+ }
75
+
76
+ dataChanged($container, data);
77
+ });
78
+ }
79
+
80
+ // Reset values if input value is reset
81
+ function inputChanged($container){
82
+ var $input = $container.find('input[type="text"]');
83
+
84
+ if($input.val().length == 0){
85
+ dataChanged($container, {});
86
+ }
87
+ }
88
+
89
+ function dataChanged($container, data){
90
+ updateInputs($container, data);
91
+ $container.trigger('jt:address:data_changed', data);
92
+ }
93
+
94
+ function updateInputs($container, data){
95
+ // Reset all fields
96
+ $container.find('[class*="jt-address-field"]').val('');
97
+
98
+ for(var attr in data){
99
+ var value = data[attr];
100
+ $container.find('.jt-address-field-' + attr).val(value);
101
+ }
102
+ }
103
+
104
+ }
105
+
106
+ })(jQuery);
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jt-rails-address
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jonathan TRIBOUHARET
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-07-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: graticule
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>'
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>'
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ description: JTRailsAddress simplify postal addresses management and geocoding with
28
+ Google Maps in Ruby On Rails and Javascript.
29
+ email: jonathan.tribouharet@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - .gitignore
35
+ - Gemfile
36
+ - LICENSE
37
+ - README.md
38
+ - jt-rails-address.gemspec
39
+ - lib/jt-rails-address.rb
40
+ - lib/schema.rb
41
+ - lib/validators.rb
42
+ - vendor/assets/javascripts/jt_address.js
43
+ homepage: https://github.com/jonathantribouharet/jt-rails-address
44
+ licenses:
45
+ - MIT
46
+ metadata: {}
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ requirements: []
62
+ rubyforge_project:
63
+ rubygems_version: 2.0.14
64
+ signing_key:
65
+ specification_version: 4
66
+ summary: Postal addresses management in Ruby On Rails and Javascript
67
+ test_files: []