direct_address 0.0.2
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.
- data/.document +5 -0
- data/.gitignore +25 -0
- data/LICENSE +20 -0
- data/README.rdoc +87 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/direct_address.gemspec +76 -0
- data/generators/direct_address/direct_address_generator.rb +24 -0
- data/generators/direct_address/templates/controllers/regions_controller.rb +10 -0
- data/generators/direct_address/templates/js/country_select.js +33 -0
- data/generators/direct_address/templates/migrations/direct_address_migration.rb +39 -0
- data/generators/direct_address/templates/models/address.rb +24 -0
- data/generators/direct_address/templates/models/country.rb +18 -0
- data/generators/direct_address/templates/models/region.rb +9 -0
- data/generators/direct_address/templates/tasks/harvest.rake +13 -0
- data/generators/direct_address/templates/views/index.json.erb +1 -0
- data/lib/direct_address/acts_as_addressable.rb +20 -0
- data/lib/direct_address/form_builder.rb +25 -0
- data/lib/direct_address/form_helper.rb +30 -0
- data/lib/direct_address/harvester/extend_string.rb +85 -0
- data/lib/direct_address/harvester/geoname.rb +105 -0
- data/lib/direct_address.rb +5 -0
- data/spec/database.yml +7 -0
- data/spec/debug.log +412 -0
- data/spec/direct_address_spec.rb +42 -0
- data/spec/model/user.rb +5 -0
- data/spec/schema.rb +31 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +25 -0
- metadata +97 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Mike Nelson
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
= direct_address
|
2
|
+
|
3
|
+
Direct Address provides a rails app with simple address features. This is a streamlined implementation of address functionality. Direct Address provides you with address, country, and region classes. It also provides a generator which generates the necessary javascript and rake tasks to implement properly. You'll also get form helpers to easily implement Direct Address in your views. A rake task is provided that allows up to date country and region information to be downloaded from geoname.org.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
Add direct_address to your environment.rb
|
8
|
+
|
9
|
+
config.gem 'direct_address'
|
10
|
+
|
11
|
+
Then install the gem:
|
12
|
+
|
13
|
+
rake gems:install
|
14
|
+
|
15
|
+
After you've installed the gem, you'll need to generate your classes, javascript, and rake task.
|
16
|
+
|
17
|
+
script/generate direct_address
|
18
|
+
|
19
|
+
Once that's complete, migrate your database
|
20
|
+
|
21
|
+
rake db:migrate
|
22
|
+
|
23
|
+
Now you're ready to download up-to-date country and region information from geoname.org
|
24
|
+
|
25
|
+
rake direct_address:pull
|
26
|
+
|
27
|
+
<b>This will take a few minutes and should be done on a decent connection.</b>
|
28
|
+
|
29
|
+
== Usage
|
30
|
+
|
31
|
+
Once you've run the generators there's not much you need to do. You can utilize the classes as they are or you can use the acts_as_addressable option. To use acts_as_addressable, include it in your class like this:
|
32
|
+
|
33
|
+
class User < ActiveRecord::Base
|
34
|
+
acts_as_addressable
|
35
|
+
end
|
36
|
+
|
37
|
+
By doing this you are giving the user a single address. One thing to note is that the generator didn't create an addresses_controller or add any routes regarding addresses. By default, it is expected that the address form will be nested in the parent form. For this reason, the accepts_nested_attributes_for and attr_accessors are included in acts_as_addressable. If you'd like to implement things differently, create a controller and implement your models to your liking.
|
38
|
+
|
39
|
+
== Form Helpers
|
40
|
+
|
41
|
+
By including Direct Address in your project you've added a few form helpers. Their implementation is very easy. You can either use it within a form_for like this:
|
42
|
+
|
43
|
+
<% form_for @user do |user_form| %>
|
44
|
+
...
|
45
|
+
<% user_form.fields_for :address do |address_form| %>
|
46
|
+
...
|
47
|
+
<%= address_form.country_select %>
|
48
|
+
...
|
49
|
+
<% end %>
|
50
|
+
...
|
51
|
+
<% end %>
|
52
|
+
|
53
|
+
Or you can use it via a tag helper like this:
|
54
|
+
|
55
|
+
<%= country_select_tag 'user[account]' %>
|
56
|
+
|
57
|
+
Either way produces the same exact thing. Take note that this does require loading at least prototype *beforehand* and the country_select file before the page load is complete. If you do like to defer the loading of extra scripts, feel free to do so with country_select. The setup doesn't occur until the window.onload event is fired. An example load order would be:
|
58
|
+
|
59
|
+
<script type="text/javascript" src="javascripts/prototype.js"></script>
|
60
|
+
|
61
|
+
POINT A
|
62
|
+
|
63
|
+
...
|
64
|
+
<% form... %>
|
65
|
+
<%= f.country_select %>
|
66
|
+
<% end %>
|
67
|
+
...
|
68
|
+
|
69
|
+
POINT B
|
70
|
+
|
71
|
+
Where the following call could be at either POINT A or POINT B:
|
72
|
+
|
73
|
+
<script type="text/javascript" src="javascripts/country_select.js"></script>
|
74
|
+
|
75
|
+
== Note on Patches/Pull Requests
|
76
|
+
|
77
|
+
* Fork the project.
|
78
|
+
* Make your feature addition or bug fix.
|
79
|
+
* Add tests for it. This is important so I don't break it in a
|
80
|
+
future version unintentionally.
|
81
|
+
* Commit, do not mess with rakefile, version, or history.
|
82
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
83
|
+
* Send me a pull request. Bonus points for topic branches.
|
84
|
+
|
85
|
+
== Copyright
|
86
|
+
|
87
|
+
Copyright (c) 2010 Mike Nelson. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "direct_address"
|
8
|
+
gem.summary = "short summary"
|
9
|
+
gem.description = "long summary"
|
10
|
+
gem.email = "mn@mcaddie.com"
|
11
|
+
gem.homepage = "http://github.com/mnelson/direct_address"
|
12
|
+
gem.authors = ["Mike Nelson"]
|
13
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'spec/rake/spectask'
|
22
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
23
|
+
spec.libs << 'lib' << 'spec'
|
24
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
25
|
+
end
|
26
|
+
|
27
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
28
|
+
spec.libs << 'lib' << 'spec'
|
29
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
30
|
+
spec.rcov = true
|
31
|
+
end
|
32
|
+
|
33
|
+
task :spec => :check_dependencies
|
34
|
+
|
35
|
+
task :default => :spec
|
36
|
+
|
37
|
+
require 'rake/rdoctask'
|
38
|
+
Rake::RDocTask.new do |rdoc|
|
39
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
40
|
+
|
41
|
+
rdoc.rdoc_dir = 'rdoc'
|
42
|
+
rdoc.title = "direct_address #{version}"
|
43
|
+
rdoc.rdoc_files.include('README*')
|
44
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
45
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.2
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{direct_address}
|
8
|
+
s.version = "0.0.2"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Mike Nelson"]
|
12
|
+
s.date = %q{2010-02-17}
|
13
|
+
s.description = %q{long summary}
|
14
|
+
s.email = %q{mn@mcaddie.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"direct_address-0.0.2.gem",
|
27
|
+
"direct_address.gemspec",
|
28
|
+
"generators/direct_address/direct_address_generator.rb",
|
29
|
+
"generators/direct_address/templates/controllers/regions_controller.rb",
|
30
|
+
"generators/direct_address/templates/js/country_select.js",
|
31
|
+
"generators/direct_address/templates/migrations/direct_address_migration.rb",
|
32
|
+
"generators/direct_address/templates/models/address.rb",
|
33
|
+
"generators/direct_address/templates/models/country.rb",
|
34
|
+
"generators/direct_address/templates/models/region.rb",
|
35
|
+
"generators/direct_address/templates/tasks/harvest.rake",
|
36
|
+
"generators/direct_address/templates/views/index.json.erb",
|
37
|
+
"lib/direct_address.rb",
|
38
|
+
"lib/direct_address/acts_as_addressable.rb",
|
39
|
+
"lib/direct_address/form_builder.rb",
|
40
|
+
"lib/direct_address/form_helper.rb",
|
41
|
+
"lib/direct_address/harvester/extend_string.rb",
|
42
|
+
"lib/direct_address/harvester/geoname.rb",
|
43
|
+
"spec/database.yml",
|
44
|
+
"spec/debug.log",
|
45
|
+
"spec/direct_address_spec.rb",
|
46
|
+
"spec/model/user.rb",
|
47
|
+
"spec/schema.rb",
|
48
|
+
"spec/spec.opts",
|
49
|
+
"spec/spec_helper.rb"
|
50
|
+
]
|
51
|
+
s.homepage = %q{http://github.com/mnelson/direct_address}
|
52
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
53
|
+
s.require_paths = ["lib"]
|
54
|
+
s.rubygems_version = %q{1.3.5}
|
55
|
+
s.summary = %q{short summary}
|
56
|
+
s.test_files = [
|
57
|
+
"spec/direct_address_spec.rb",
|
58
|
+
"spec/model/user.rb",
|
59
|
+
"spec/schema.rb",
|
60
|
+
"spec/spec_helper.rb"
|
61
|
+
]
|
62
|
+
|
63
|
+
if s.respond_to? :specification_version then
|
64
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
65
|
+
s.specification_version = 3
|
66
|
+
|
67
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
68
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
69
|
+
else
|
70
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
71
|
+
end
|
72
|
+
else
|
73
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class DirectAddressGenerator < Rails::Generator::Base
|
2
|
+
def manifest
|
3
|
+
record do |m|
|
4
|
+
|
5
|
+
m.file "js/country_select.js", "public/javascripts/country_select.js"
|
6
|
+
|
7
|
+
m.directory "app/views/regions"
|
8
|
+
m.file "views/index.json.erb", "app/views/regions/index.json.erb"
|
9
|
+
|
10
|
+
m.file "controllers/regions_controller.rb", "app/controllers/regions_controller.rb"
|
11
|
+
|
12
|
+
%w(address country region).each do |model|
|
13
|
+
m.file "models/#{model}.rb", "app/models/#{model}.rb"
|
14
|
+
end
|
15
|
+
|
16
|
+
m.route_resources :regions
|
17
|
+
|
18
|
+
m.migration_template "migrations/direct_address_migration.rb", "db/migrate", {:migration_file_name => "direct_address_migration"}
|
19
|
+
|
20
|
+
m.file "tasks/harvest.rake", "lib/tasks/direct_address_harvest.rake"
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
if(typeof(Prototype) != 'undefined'){
|
2
|
+
|
3
|
+
CountrySelect = Class.create({
|
4
|
+
initialize : function(args){
|
5
|
+
this.country_select = $(args['country_select_id']);
|
6
|
+
this.region_select = $(args['region_select_id']);
|
7
|
+
this.country_select.observe('change', this.update_regions.bind(this));
|
8
|
+
},
|
9
|
+
update_regions : function(event){
|
10
|
+
this.region_select.selectedIndex = -1;
|
11
|
+
var country_id = this.selected_country()[0];
|
12
|
+
new Ajax.Request('/regions.json?country_id=' + country_id, {method : 'get', onComplete : function(transport){
|
13
|
+
var regions = transport.responseJSON;
|
14
|
+
this.populate_regions(regions);
|
15
|
+
}.bind(this)});
|
16
|
+
},
|
17
|
+
selected_country : function(){
|
18
|
+
var elem = this.country_select.childElements()[this.country_select.selectedIndex];
|
19
|
+
return [elem.value, elem.innerHTML]
|
20
|
+
},
|
21
|
+
populate_regions : function(regions){
|
22
|
+
var html = ['<option value="">Select a Region</option>', regions.collect(function(region){
|
23
|
+
return '<option value="' + region.id + '">' + region.name + '</option>';
|
24
|
+
})].flatten().join('');
|
25
|
+
this.region_select.update(html);
|
26
|
+
if(regions.length == 0)
|
27
|
+
this.region_select.hide();
|
28
|
+
else
|
29
|
+
this.region_select.show();
|
30
|
+
}
|
31
|
+
});
|
32
|
+
|
33
|
+
} else { try{ console.log('Prototype must be preloaded for country_select.js to work properly.'); } catch (e) {}}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class DirectAddressMigration < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :regions do |t|
|
4
|
+
t.references :country
|
5
|
+
t.string :name
|
6
|
+
t.timestamps
|
7
|
+
end
|
8
|
+
|
9
|
+
add_index :regions, :country_id
|
10
|
+
|
11
|
+
create_table :addresses do |t|
|
12
|
+
t.references :addressable, :polymorphic => true, :null => false
|
13
|
+
t.references :country
|
14
|
+
t.references :region
|
15
|
+
t.string :street1
|
16
|
+
t.string :street2
|
17
|
+
t.string :city
|
18
|
+
t.string :postal
|
19
|
+
t.timestamps
|
20
|
+
end
|
21
|
+
|
22
|
+
add_index :addresses, [:addressable_id, :addressable_type]
|
23
|
+
add_index :addresses, [:country_id]
|
24
|
+
add_index :addresses, [:region_id]
|
25
|
+
|
26
|
+
create_table :countries do |t|
|
27
|
+
t.string :abbreviation
|
28
|
+
t.string :name
|
29
|
+
t.timestamps
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.down
|
35
|
+
drop_table :regions
|
36
|
+
drop_table :countries
|
37
|
+
drop_table :addresses
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Address < ActiveRecord::Base
|
2
|
+
|
3
|
+
belongs_to :addressable, :polymorphic => true
|
4
|
+
belongs_to :country
|
5
|
+
belongs_to :region
|
6
|
+
|
7
|
+
|
8
|
+
def single_line
|
9
|
+
multiline.join(', ')
|
10
|
+
end
|
11
|
+
|
12
|
+
def multiline
|
13
|
+
[street1, street2, [city, region_name, postal].compact.join(' '), country_abbrev].compact.collect{|s| s.length > 0 && s}
|
14
|
+
end
|
15
|
+
|
16
|
+
def region_name
|
17
|
+
self.region && self.region.name || nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def country_abbrev
|
21
|
+
self.country && self.country.abbrev || nil
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Country < ActiveRecord::Base
|
2
|
+
|
3
|
+
has_many :regions
|
4
|
+
|
5
|
+
validates_presence_of :abbreviation, :name
|
6
|
+
validates_length_of :abbreviation, :is => 2
|
7
|
+
alias_attribute :abbrev, :abbreviation
|
8
|
+
|
9
|
+
default_scope :order => 'name ASC'
|
10
|
+
|
11
|
+
before_create :format_abbreviation
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def format_abbreviation
|
16
|
+
self.abbreviation = self.abbreviation.upcase
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class Region < ActiveRecord::Base
|
2
|
+
|
3
|
+
belongs_to :country
|
4
|
+
validates_presence_of :name, :country
|
5
|
+
|
6
|
+
default_scope :order => 'name ASC'
|
7
|
+
|
8
|
+
named_scope :by_country, lambda {|country| country && (country.is_a?(Country) && (country = country.id) || true) && {:conditions => ['country_id = ?', country]} || {}}
|
9
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
|
2
|
+
begin
|
3
|
+
require File.dirname(__FILE__) + '/../../config/environment.rb'
|
4
|
+
|
5
|
+
namespace :direct_address do
|
6
|
+
desc "pulls up to date country and region data from geonames.org"
|
7
|
+
task :pull do
|
8
|
+
Geoname.retrieve_to_db
|
9
|
+
end
|
10
|
+
end
|
11
|
+
rescue
|
12
|
+
puts "Direct address harvester not properly installed"
|
13
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= @regions.collect{|region| {:id => region.id, :name => region.name}}.to_json %>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Direct
|
2
|
+
module Address
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ::Direct::Address::ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
|
10
|
+
def acts_as_addressable
|
11
|
+
has_one :address, :as => :addressable
|
12
|
+
accepts_nested_attributes_for :address
|
13
|
+
attr_accessible :address_attributes
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
::ActiveRecord::Base.send(:include, ::Direct::Address)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ActionView
|
2
|
+
module Helpers
|
3
|
+
module CountryAndRegion
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.class_eval do
|
7
|
+
include ActionView::Helpers::CountryAndRegion::InstanceMethods
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module InstanceMethods
|
12
|
+
def country_select
|
13
|
+
@countries ||= Country.all
|
14
|
+
sanitized_object_id = self.object_name.split('[').collect{|s| (s = s.gsub(']','')) && s.size > 0 && s || nil}.compact.join('_')
|
15
|
+
html = self.select(:country_id, ([['Select a Country', nil]] + @countries.collect{|country| [country.name, country.id]}))
|
16
|
+
html << self.select(:region_id, ([['Select a Region', nil]] + (self.object && self.object.country && self.object.country.regions.collect{|region| [region.name, region.id]} || [])))
|
17
|
+
html << "<script type=\"text/javascript\">if(typeof(Prototype) != 'undefined'){Element.observe(window, 'load', function(){if(typeof(CountrySelect) == 'undefined'){try{console.log('country_select.js not loaded.');} catch (e) {};return;};new CountrySelect({country_select_id : '#{sanitized_object_id}_country_id', region_select_id : '#{sanitized_object_id}_region_id'})});}else{document.getElementById('#{sanitized_object_id}_country_id').style.display = 'none';document.getElementById('#{sanitized_object_id}_region_id').style.display = 'none';}</script>"
|
18
|
+
html
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
::ActionView::Helpers::FormBuilder.send :include, ActionView::Helpers::CountryAndRegion
|
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
module ActionView
|
3
|
+
module Helpers
|
4
|
+
module CountryAndRegionHelper
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.class_eval do
|
8
|
+
include ActionView::Helpers::CountryAndRegionHelper::InstanceMethods
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module InstanceMethods
|
13
|
+
def country_select_tag(object_string, country_id = nil, region_id = nil)
|
14
|
+
object_string = object_string.to_s
|
15
|
+
object_id = object_string.split('[').collect{|s| (s = s.gsub(']','')) && s.size > 0 && s || nil}.compact.join('_')
|
16
|
+
@countries ||= Country.all
|
17
|
+
@regions = !country_id.nil? && Region.by_country(country_id) || []
|
18
|
+
country_options = options_for_select([['Select a Country', nil]] + @countries.collect{|country| [country.name, country.id]}, country_id)
|
19
|
+
region_options = options_for_select([['Select a Region', nil]] + @regions.collect{|region| [region.name, region.id]}, region_id)
|
20
|
+
html = select_tag("#{object_string}[country_id]", country_options, :id => "#{object_id}_country_id")
|
21
|
+
html << select_tag("#{object_string}[region_id]", region_options, :id => "#{object_id}_region_id")
|
22
|
+
html << "<script type=\"text/javascript\">if(typeof(Prototype) != 'undefined'){Element.observe(window, 'load', function(){if(typeof(CountrySelect) == 'undefined'){try{console.log('country_select.js not loaded.');} catch (e) {};return;};new CountrySelect({country_select_id : '#{object_id}_country_id', region_select_id : '#{object_id}_region_id'});});}else{document.getElementById('#{object_id}_country_id').style.display = 'none';document.getElementById('#{object_id}_region_id').style.display = 'none';}</script>"
|
23
|
+
html
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
::ActionView::Base.send :include, ActionView::Helpers::CountryAndRegionHelper
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# RemoveAccents version 1.0.3 (c) 2008-2009 Solutions Informatiques Techniconseils inc.
|
2
|
+
#
|
3
|
+
# This module adds 2 methods to the string class.
|
4
|
+
# Up-to-date version and documentation available at:
|
5
|
+
#
|
6
|
+
# http://www.techniconseils.ca/en/scripts-remove-accents-ruby.php
|
7
|
+
#
|
8
|
+
# This script is available under the following license :
|
9
|
+
# Creative Commons Attribution-Share Alike 2.5.
|
10
|
+
#
|
11
|
+
# See full license and details at :
|
12
|
+
# http://creativecommons.org/licenses/by-sa/2.5/ca/
|
13
|
+
#
|
14
|
+
# Version history:
|
15
|
+
# * 1.0.3 : July 23 2009
|
16
|
+
# Corrected some incorrect character codes. Source is now wikipedia at:
|
17
|
+
# http://en.wikipedia.org/wiki/ISO/IEC_8859-1#Related_character_maps
|
18
|
+
# Thanks to Raimon Fernandez for pointing out the incorrect codes.
|
19
|
+
# * 1.0.2 : October 29 2008
|
20
|
+
# Slightly optimized version of urlize - Jonathan Grenier (jgrenier@techniconseils.ca)
|
21
|
+
# * 1.0.1 : October 29 2008
|
22
|
+
# First public revision - Jonathan Grenier (jgrenier@techniconseils.ca)
|
23
|
+
#
|
24
|
+
|
25
|
+
class String
|
26
|
+
# The extended characters map used by removeaccents. The accented characters
|
27
|
+
# are coded here using their numerical equivalent to sidestep encoding issues.
|
28
|
+
# These correspond to ISO-8859-1 encoding.
|
29
|
+
ACCENTS_MAPPING = {
|
30
|
+
'E' => [200,201,202,203],
|
31
|
+
'e' => [232,233,234,235],
|
32
|
+
'A' => [192,193,194,195,196,197],
|
33
|
+
'a' => [224,225,226,227,228,229,230],
|
34
|
+
'C' => [199],
|
35
|
+
'c' => [231],
|
36
|
+
'O' => [210,211,212,213,214,216],
|
37
|
+
'o' => [242,243,244,245,246,248],
|
38
|
+
'I' => [204,205,206,207],
|
39
|
+
'i' => [236,237,238,239],
|
40
|
+
'U' => [217,218,219,220],
|
41
|
+
'u' => [249,250,251,252],
|
42
|
+
'N' => [209],
|
43
|
+
'n' => [241],
|
44
|
+
'Y' => [221],
|
45
|
+
'y' => [253,255],
|
46
|
+
'AE' => [306],
|
47
|
+
'ae' => [346],
|
48
|
+
'OE' => [188],
|
49
|
+
'oe' => [189]
|
50
|
+
}
|
51
|
+
|
52
|
+
|
53
|
+
# Remove the accents from the string. Uses String::ACCENTS_MAPPING as the source map.
|
54
|
+
def removeaccents
|
55
|
+
str = String.new(self)
|
56
|
+
String::ACCENTS_MAPPING.each {|letter,accents|
|
57
|
+
packed = accents.pack('U*')
|
58
|
+
rxp = Regexp.new("[#{packed}]", nil, 'U')
|
59
|
+
str.gsub!(rxp, letter)
|
60
|
+
}
|
61
|
+
|
62
|
+
str
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
# Convert a string to a format suitable for a URL without ever using escaped characters.
|
67
|
+
# It calls strip, removeaccents, downcase (optional) then removes the spaces (optional)
|
68
|
+
# and finally removes any characters matching the default regexp (/[^-_A-Za-z0-9]/).
|
69
|
+
#
|
70
|
+
# Options
|
71
|
+
#
|
72
|
+
# * :downcase => call downcase on the string (defaults to true)
|
73
|
+
# * :convert_spaces => Convert space to underscore (defaults to false)
|
74
|
+
# * :regexp => The regexp matching characters that will be converting to an empty string (defaults to /[^-_A-Za-z0-9]/)
|
75
|
+
def urlize(options = {})
|
76
|
+
options[:downcase] ||= true
|
77
|
+
options[:convert_spaces] ||= false
|
78
|
+
options[:regexp] ||= /[^-_A-Za-z0-9]/
|
79
|
+
|
80
|
+
str = self.strip.removeaccents
|
81
|
+
str.downcase! if options[:downcase]
|
82
|
+
str.gsub!(/\ /,'_') if options[:convert_spaces]
|
83
|
+
str.gsub(options[:regexp], '')
|
84
|
+
end
|
85
|
+
end
|