china_regions 0.0.1
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/.gitignore +5 -0
- data/Gemfile +4 -0
- data/LICENSE +5 -0
- data/README.md +46 -0
- data/Rakefile +2 -0
- data/app/controllers/china_regions/fetch_options_controller.rb +30 -0
- data/app/models/city.rb +20 -0
- data/app/models/district.rb +20 -0
- data/app/models/province.rb +1 -0
- data/china_regions.gemspec +19 -0
- data/config/routes.rb +3 -0
- data/lib/china_regions/engine.rb +5 -0
- data/lib/china_regions/helper.rb +101 -0
- data/lib/china_regions/version.rb +3 -0
- data/lib/china_regions.rb +6 -0
- data/lib/generators/china_regions/install/install_generator.rb +32 -0
- data/lib/generators/china_regions/install/templates/cities.yml +10829 -0
- data/lib/generators/china_regions/install/templates/migration.rb +50 -0
- data/lib/generators/china_regions/regions/regions_generator.rb +13 -0
- data/lib/tasks/china_region.rake +46 -0
- metadata +81 -0
data/Gemfile
ADDED
data/LICENSE
ADDED
data/README.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# ChinaRegions
|
2
|
+
|
3
|
+
中国省份,城市,地区[地级市]. 紧支持 Ruby on Rails 程序.
|
4
|
+
|
5
|
+
|
6
|
+
## How to use it
|
7
|
+
|
8
|
+
添加一下代码到你的 Gemfile:
|
9
|
+
|
10
|
+
gem 'china_regions', :git => 'git://github.com/encoreshao/china_regions.git'
|
11
|
+
|
12
|
+
bundle install
|
13
|
+
|
14
|
+
执行:
|
15
|
+
|
16
|
+
rails g china_regions:install
|
17
|
+
|
18
|
+
随后你可以看到控制台:
|
19
|
+
* 复制 数据源cities 到 config 目录. config/cities.yml
|
20
|
+
* 创建 migration 文件到db/migrate 目录 db/migrate/create_china_regions_tables.rb
|
21
|
+
* 执行 `rake db:migrate` 添加三张表(provinces, cities, districts).
|
22
|
+
* 执行 `rake china_regions:import` 导入数据.
|
23
|
+
|
24
|
+
|
25
|
+
此时 你可能需要添加三个model[`Province`, `City`, `District`]到你应用中:
|
26
|
+
|
27
|
+
你可以执行 `rails g` 查看到 generator LIST.
|
28
|
+
|
29
|
+
执行 rails g china_regions:regions models
|
30
|
+
|
31
|
+
查看 app/models:
|
32
|
+
|
33
|
+
create app/models/province.rb
|
34
|
+
create app/models/city.rb
|
35
|
+
create app/models/district.rb
|
36
|
+
|
37
|
+
|
38
|
+
## Contributing
|
39
|
+
|
40
|
+
Thank you for XuHao
|
41
|
+
|
42
|
+
|
43
|
+
## License
|
44
|
+
|
45
|
+
ChinaRegions is released under the MIT license.
|
46
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
module ChinaRegions
|
2
|
+
class FetchOptionsController < ::ActionController::Metal
|
3
|
+
|
4
|
+
def index
|
5
|
+
if params_valid?(params) and parent_klass = params[:parent_klass].classify.safe_constantize.find(params[:parent_id])
|
6
|
+
table_name = params[:klass].tableize
|
7
|
+
regions = parent_klass.__send__(table_name).select("#{table_name}.id, #{table_name}.name")
|
8
|
+
if has_level_column?(params[:klass])
|
9
|
+
regions = regions.order('level ASC')
|
10
|
+
else
|
11
|
+
regions = regions.order('name ASC')
|
12
|
+
end
|
13
|
+
self.response_body = regions.to_json
|
14
|
+
else
|
15
|
+
self.response_body = [].to_json
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
protected
|
21
|
+
def has_level_column?(klass_name)
|
22
|
+
klass_name.classify.safe_constantize.try(:column_names).to_a.include?('level')
|
23
|
+
end
|
24
|
+
|
25
|
+
def params_valid?(params)
|
26
|
+
params[:klass].present? and params[:parent_klass] =~ /^province|city$/i and params[:parent_id].present?
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
data/app/models/city.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
class City < ActiveRecord::Base
|
4
|
+
|
5
|
+
attr_accessible :name, :province_id, :level, :zip_code, :name_en, :name_abbr
|
6
|
+
|
7
|
+
belongs_to :province
|
8
|
+
has_many :districts, dependent: :destroy
|
9
|
+
|
10
|
+
scope :with_province, ->(province) { where(province_id: province) }
|
11
|
+
|
12
|
+
def short_name
|
13
|
+
@short_name ||= name.gsub(/市|自治州|地区|特别行政区/, '')
|
14
|
+
end
|
15
|
+
|
16
|
+
def siblings
|
17
|
+
@siblings ||= scoped.with_province(self.province_id)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
class District < ActiveRecord::Base
|
4
|
+
|
5
|
+
attr_accessible :name, :city_id, :name_en, :name_abbr
|
6
|
+
|
7
|
+
belongs_to :city
|
8
|
+
belongs_to :province
|
9
|
+
|
10
|
+
scope :with_city, ->(city) { where(city_id: city) }
|
11
|
+
|
12
|
+
def short_name
|
13
|
+
@short_name ||= name.gsub(/区|县|市|自治县/, '')
|
14
|
+
end
|
15
|
+
|
16
|
+
def siblings
|
17
|
+
@siblings ||= scoped.with_city(self.city_id)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path('../lib/china_regions/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Encore Shao"]
|
6
|
+
gem.email = ["encore.shao@gmail.com"]
|
7
|
+
gem.description = %q{China regions Ruby on rails interface}
|
8
|
+
gem.summary = %q{China regions Ruby on rails interface}
|
9
|
+
gem.homepage = "http://github.com/encoreshao"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "china_regions"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = ChinaRegions::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency 'jquery-rails'
|
19
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module ChinaRegions
|
4
|
+
module Helper
|
5
|
+
|
6
|
+
module FormHelper
|
7
|
+
def region_select(object, methods, options = {}, html_options = {})
|
8
|
+
output = ''
|
9
|
+
|
10
|
+
html_options[:class] ?
|
11
|
+
(html_options[:class].prepend('region_select ')) :
|
12
|
+
(html_options[:class] = 'region_select')
|
13
|
+
|
14
|
+
if Array === methods
|
15
|
+
methods.each_with_index do |method, index|
|
16
|
+
if klass = method.to_s.classify.safe_constantize
|
17
|
+
choices = index == 0 ? klass.all.collect {|p| [ p.name, p.id ] } : []
|
18
|
+
next_method = methods.at(index + 1)
|
19
|
+
|
20
|
+
set_options(method, options, klass)
|
21
|
+
set_html_options(object, method, html_options, next_method)
|
22
|
+
|
23
|
+
output << select(object, "#{method.to_s}_id", choices, options = options, html_options = html_options)
|
24
|
+
else
|
25
|
+
raise "Method '#{method}' is not a vaild attribute of #{object}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
else
|
29
|
+
if klass = methods.to_s.classify.safe_constantize
|
30
|
+
options[:prompt] = region_prompt(klass)
|
31
|
+
output << select(object, methods, klass.all.collect {|p| [ p.name, p.id ] }, options = options, html_options = html_options)
|
32
|
+
else
|
33
|
+
raise "Method '#{method}' is not a vaild attribute of #{object}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
output << javascript_tag(js_output)
|
38
|
+
output.html_safe
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def set_options(method, options, region_klass)
|
45
|
+
if respond_to?("#{method}_select_prompt")
|
46
|
+
options[:prompt] = __send__("#{method}_select_prompt")
|
47
|
+
else
|
48
|
+
options[:prompt] = region_prompt(region_klass)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_html_options(object, method, html_options, next_region)
|
53
|
+
html_options[:data] ? (html_options[:data][:region_klass] = "#{method.to_s}") : (html_options[:data] = { region_klass: "#{method.to_s}" })
|
54
|
+
if next_region
|
55
|
+
html_options[:data].merge!(region_target: "#{object}_#{next_region.to_s}_id", region_target_kalss: next_region.to_s)
|
56
|
+
else
|
57
|
+
html_options[:data].delete(:region_target)
|
58
|
+
html_options[:data].delete(:region_target_kalss)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def region_prompt(region_klass)
|
63
|
+
human_name = region_klass.model_name.human
|
64
|
+
"请选择#{human_name}"
|
65
|
+
end
|
66
|
+
|
67
|
+
def js_output
|
68
|
+
%~
|
69
|
+
$(function(){
|
70
|
+
$('body').on('change', '.region_select', function(event) {
|
71
|
+
var self, targetDom;
|
72
|
+
self = $(event.currentTarget);
|
73
|
+
targetDom = $('#' + self.data('region-target'));
|
74
|
+
if (targetDom.size() > 0) {
|
75
|
+
$.getJSON('/china_regions/fetch_options', {klass: self.data('region-target-kalss'), parent_klass: self.data('region-klass'), parent_id: self.val()}, function(data) {
|
76
|
+
$('option[value!=""]', targetDom).remove();
|
77
|
+
$.each(data, function(index, value) {
|
78
|
+
targetDom.append("<option value='" + value.id + "'>" + value.name + "</option>");
|
79
|
+
});
|
80
|
+
})
|
81
|
+
}
|
82
|
+
});
|
83
|
+
});
|
84
|
+
~
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
module FormBuilder
|
91
|
+
def region_select(methods, options = {}, html_options = {})
|
92
|
+
@template.region_select(@object_name, methods, options = options, html_options = html_options)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
ActionView::Base.send :include, ChinaRegions::Helper::FormHelper
|
101
|
+
ActionView::Helpers::FormBuilder.send :include, ChinaRegions::Helper::FormBuilder
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module ChinaRegions
|
4
|
+
class InstallGenerator < Rails::Generators::Base
|
5
|
+
include Rails::Generators::Migration
|
6
|
+
source_root File.expand_path('../templates', __FILE__)
|
7
|
+
|
8
|
+
def capy_migration_file
|
9
|
+
migration_template "migration.rb", "db/migrate/create_china_regions_tables.rb"
|
10
|
+
end
|
11
|
+
|
12
|
+
def capy_cities_file
|
13
|
+
copy_file 'cities.yml', 'config/cities.yml'
|
14
|
+
end
|
15
|
+
|
16
|
+
def execute_migrate
|
17
|
+
rake("db:migrate")
|
18
|
+
end
|
19
|
+
|
20
|
+
def import_cities_to_database
|
21
|
+
rake('china_regions:import')
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.next_migration_number(dirname)
|
25
|
+
if ActiveRecord::Base.timestamped_migrations
|
26
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
27
|
+
else
|
28
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|