china_regions 0.1.0 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 42ebe2926674e82aeebf73c5111a62a20e182eda
4
- data.tar.gz: d7ef3319973190e74f2e17d70a656db38d22a133
3
+ metadata.gz: 2bb6a315cde1ce4bf6543b865aea9508887d48e9
4
+ data.tar.gz: ed1e49662e8b1cd04208df7d4d7f4482c630e6b3
5
5
  SHA512:
6
- metadata.gz: 389e838506bd0821046b6879a11fe63fa8d996afb8f32c03fec9347d8aba079e48d2f3e30f4aeb4e99366e18751e717c5d82cc2cd8207c3a822c83b6dfb2cdcb
7
- data.tar.gz: a2924b8c593fbb8a9f6044d29dc84b8b8b5d091daf3e77a1e33fbce5f490633d4dd7dc500d8a29a0146ffb573a190ed3260a1581347a79f5a87fa9e210daf420
6
+ metadata.gz: 95a372effc18e54b543adfb17ebf25527744e6ed7b50ba2fd4608ecd9b049dbc1a3b6189fa2cd8c811249e5f86fd56d436f84c8c0b83a494a9539674b47682e2
7
+ data.tar.gz: 6a1a1268ed726a94b1280252a2f52a0916d39a2629770e11eeef55cc0e407e4f2fbc9eb632a9e7b219dbdfb90c6458af02aa74a9da61092673e06b0eaa9f82a9
data/README.md CHANGED
@@ -1,45 +1,53 @@
1
1
  # ChinaRegions
2
2
 
3
- 中国省份,城市,地区[地级市]. 紧支持 Ruby on Rails 程序. Ruby Version ( > 1.9.x ) Rails Version ( > 3.2.x )
4
-
3
+ 中国省份,城市,地区[地级市]
4
+ Ruby on Rails 程式代码, Ruby ( > 1.9.x ) And Rails (> 4.0)
5
+
6
+ ## How to update
7
+
8
+ If you are using ChinaRegions version 0.1.x be sure to run:
9
+
10
+ rails g china_regions:regions
11
+
12
+ to have the javascript file copied over into your project.
5
13
 
6
14
  ## How to use it
7
15
 
8
- 添加一下代码到你的 Gemfile:
16
+ 添加以下代码到你的 Gemfile:
9
17
 
10
18
  gem 'china_regions'
11
19
 
12
- or
20
+ OR
13
21
 
14
- gem 'china_regions', :git => 'git://github.com/encoreshao/china_regions.git'
22
+ gem 'china_regions', github: 'encoreshao/china_regions'
15
23
 
16
24
  bundle install
17
25
 
18
26
  执行:
19
27
 
20
28
  rails g china_regions:install
21
-
22
- 随后你可以看到控制台:
23
- * 创建 migration 文件到db/migrate 目录 db/migrate/xxxxxxxxxxx_create_china_regions_tables.rb
24
- * 创建 数据源 cities.yml 到 config 目录. config/cities.yml
25
- * 创建 regions.en.yml 和 regions.zh.yml 文件到 config/locales 文件下
26
- * 执行 `rake db:migrate` 添加三张表(provinces, cities, districts).
29
+
30
+ 随后你可以看到控制台发生的变化:
31
+ * 复制 db/migrate/xxxxxxxxxxx_create_china_regions_tables.rb 文件到db/migrate 目录
32
+ * 复制 数据源 cities.yml 到 config 目录. config/cities.yml
33
+ * 复制 regions.en.yml 和 regions.zh.yml 文件到 config/locales 目录
34
+ * 执行 `rake db:migrate` 创建所需的表 (provinces, cities, districts).
27
35
  * 执行 `rake china_regions:import` 导入数据.
28
36
 
29
37
 
30
38
  此时 你可能需要添加三个 models[`Province`, `City`, `District`] 到你应用中:
31
-
39
+
32
40
  你可以执行 `rails g` 查看到 generator LIST.
33
41
 
34
- 执行 rails g china_regions:regions models
42
+ 执行 rails g china_regions:regions
35
43
 
36
44
  查看 app/models:
37
-
45
+
38
46
  create app/models/province.rb
39
47
  create app/models/city.rb
40
48
  create app/models/district.rb
41
49
 
42
- ## How to view
50
+ ## How to view
43
51
 
44
52
  范例:
45
53
 
@@ -57,7 +65,7 @@ bundle install
57
65
  = region_select :article, :province
58
66
  = region_select :article, :city
59
67
  = region_select :article, :district
60
-
68
+
61
69
  = f.submit class: 'btn'
62
70
 
63
71
  添加前缀名:
@@ -66,11 +74,29 @@ bundle install
66
74
 
67
75
  = f.region_select [:province, :city, :district], :prefix => "home"
68
76
  = f.region_select [:province, :city, :district], :prefix => "work"
69
-
77
+
78
+
79
+ Preselect Province:
80
+
81
+ = form_for @article do |f|
82
+
83
+ = f.region_select [:province, :city, :district], province: "chongqing"
84
+
85
+ OR
86
+
87
+ = f.region_select [:province, :city, :district], province: "重庆市"
88
+
89
+ Prioritize Choice:
90
+
91
+ = form_for @article do |f|
92
+
93
+ = f.region_select [:province, :city, :district], priority: { province: ["重庆市"], district: %w(巴南区 北碚区 渝北区) }
70
94
 
71
95
  ## Contributing
72
96
 
73
- Thank you for XuHao
97
+ We have a list of valued contributors. Check them all at:
98
+
99
+ https://github.com/encoreshao/china_regions/graphs/contributors
74
100
 
75
101
 
76
102
  ## License
@@ -0,0 +1,48 @@
1
+ $(function() {
2
+ $('body').on('change', '.region_select', function(event) {
3
+ var changed_object = $(event.currentTarget);
4
+ var target_dom = get_target(changed_object);
5
+
6
+ if (target_dom.size() > 0) {
7
+ get_options(changed_object, target_dom, deal_with_second_target);
8
+ }
9
+ });
10
+
11
+ function get_target(dom_object) {
12
+ return $('#' + dom_object.data('region-target'));
13
+ }
14
+
15
+ function deal_with_second_target(changed_obj, target) {
16
+ var updated_target = get_target(changed_obj);
17
+ var second_target = get_target(updated_target);
18
+
19
+ // Just clear out the second dropdown if it exists,
20
+ // they should start from the beginning
21
+ if (second_target.size() > 0) {
22
+ $('option[value!=""]', second_target).remove();
23
+
24
+ // If the updated target has only one entry ensure that all districts
25
+ // are loaded so that we can get those options since.
26
+ if ($('option', updated_target).size() == 1) {
27
+ get_options(updated_target, second_target);
28
+ }
29
+ }
30
+ }
31
+
32
+ // Retrieve options and allow a callback to be included to perform additonal
33
+ // stuff on success
34
+ function get_options(changed_object, target, additional_success_callback) {
35
+ $.getJSON('/china_regions/fetch_options', {
36
+ klass: changed_object.data('region-target-klass'),
37
+ parent_klass: changed_object.data('region-klass'),
38
+ parent_id: changed_object.val() }, function(data) {
39
+
40
+ $('option[value!=""]', target).remove();
41
+ $.each(data, function(index, value) {
42
+ target.append("<option value='" + value.id + "'>" + value.name + "</option>");
43
+ });
44
+
45
+ typeof additional_success_callback === 'function' && additional_success_callback(changed_object, target);
46
+ });
47
+ }
48
+ });
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module ChinaRegions
2
4
  class FetchOptionsController < ::ActionController::Metal
3
5
 
@@ -17,12 +19,13 @@ module ChinaRegions
17
19
  end
18
20
 
19
21
  protected
20
- def has_level_column?(klass_name)
21
- klass_name.classify.safe_constantize.try(:column_names).to_a.include?('level')
22
- end
22
+ def has_level_column?(klass_name)
23
+ klass_name.classify.safe_constantize.try(:column_names).to_a.include?('level')
24
+ end
25
+
26
+ def params_valid?(params)
27
+ params[:klass].present? and params[:parent_klass] =~ /^province|city$/i and params[:parent_id].present?
28
+ end
23
29
 
24
- def params_valid?(params)
25
- params[:klass].present? and params[:parent_klass] =~ /^province|city$/i and params[:parent_id].present?
26
- end
27
30
  end
28
31
  end
data/app/models/city.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  class City < ActiveRecord::Base
4
+
4
5
  belongs_to :province
5
6
  has_many :districts, dependent: :destroy
6
7
 
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  class District < ActiveRecord::Base
4
+
4
5
  belongs_to :city
5
6
 
6
7
  scope :with_city, ->(city) { where(city_id: city) }
@@ -1,6 +1,8 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  class Province < ActiveRecord::Base
4
+
4
5
  has_many :cities, dependent: :destroy
5
6
  has_many :districts, through: :cities
7
+
6
8
  end
@@ -25,4 +25,4 @@ zh:
25
25
  city_id: 城市
26
26
  city: 城市
27
27
  name_en: 拼音
28
- name_abbr: 简称
28
+ name_abbr: 简称
@@ -1,35 +1,41 @@
1
1
  # encoding: utf-8
2
-
3
2
  module ChinaRegions
4
3
  module Helpers
5
4
  module FormHelper
6
- def region_select(object, methods, options = {}, html_options = {})
5
+ def region_select(object_name, methods, options = {}, html_options = {})
7
6
  output = ''
8
7
 
9
- html_options[:class] ?
10
- (html_options[:class].prepend('region_select ')) :
8
+ preselected_choices = set_regions_options(options)
9
+
10
+ html_options[:class] ?
11
+ (html_options[:class].prepend('region_select ')) :
11
12
  (html_options[:class] = 'region_select')
12
13
 
13
- dropdown_prefix = options[:prefix].to_s + "_" || ""
14
+ dropdown_prefix = options[:prefix] ? options[:prefix].to_s + "_" : ""
14
15
 
15
16
  if Array === methods
16
17
  methods.each_with_index do |method, index|
17
18
  if region_klass = method.to_s.classify.safe_constantize
18
- choices = (index == 0 ? region_klass.where(nil).collect {|p| [ p.name, p.id ] } : [])
19
+ choices = get_choices(region_klass, method, preselected_choices, index)
20
+ choices = prioritize_choices(options[:priority][method], choices) if options[:priority].try(:[], method)
21
+
19
22
  next_method = methods.at(index + 1)
20
23
 
21
- set_options(method, options, region_klass)
22
- set_html_options(object, method, html_options, next_method, dropdown_prefix)
24
+ set_prompt(method, options, region_klass)
25
+ set_html_options(object_name, method, html_options, next_method, dropdown_prefix)
23
26
 
24
- output << select(object, "#{dropdown_prefix}#{method.to_s}_id", choices, options = options, html_options = html_options)
27
+ if options[:default] && options[:default][method]
28
+ options[:selected] = options[:default][method] if options[:default][method]
29
+ end
30
+
31
+ output << select(object_name, "#{dropdown_prefix}#{method.to_s}_id", choices, options, html_options)
25
32
  else
26
- raise "Method '#{method}' is not a vaild attribute of #{object}"
33
+ raise "Method '#{method}' is not a vaild attribute of #{object_name}"
27
34
  end
28
35
  end
29
36
  else
30
-
31
37
  _methods = unless methods.to_s.include?('_id')
32
- (methods.to_s + ('_id')).to_sym
38
+ (methods.to_s + ('_id')).to_sym
33
39
  else
34
40
  _methods = methods
35
41
  methods = methods.to_s.gsub(/(_id)$/, '')
@@ -39,20 +45,68 @@ module ChinaRegions
39
45
  if region_klass = methods.to_s.classify.safe_constantize
40
46
  options[:prompt] = region_prompt(region_klass)
41
47
 
42
- output << select(object, _methods, region_klass.where(nil).collect {|p| [ p.name, p.id ] }, options = options, html_options = html_options)
48
+ if methods == :province && preselected_choices[:province_id]
49
+ options[:selected] = preselected_choices[:province_id]
50
+ end
51
+
52
+ output << select(object_name, _methods, region_klass.where(nil).collect {|p| [ p.name, p.id ] }, options = options, html_options = html_options)
43
53
  else
44
- raise "Method '#{method}' is not a vaild attribute of #{object}"
54
+ raise "Method '#{method}' is not a vaild attribute of #{object_name}"
45
55
  end
46
56
  end
47
-
48
- output << javascript_tag(js_output)
49
57
  output.html_safe
50
58
  end
51
59
 
52
-
53
60
  private
54
61
 
55
- def set_options(method, options, region_klass)
62
+ def get_choices(region_klass, method, preselected_choices, index)
63
+ return preselected_choices[method] if preselected_choices[method]
64
+
65
+ if index == 0
66
+ region_klass.where(nil).collect { |p| [p.name, p.id] }
67
+ else
68
+ []
69
+ end
70
+ end
71
+
72
+ def prioritize_choices(priorities, choices)
73
+ return choices if priorities.empty?
74
+
75
+ temp_choices = []
76
+ priority_choices = []
77
+ sorting_map = {}
78
+
79
+ priorities.each_with_index do |value, i|
80
+ sorting_map[value.to_sym] = i
81
+ end
82
+
83
+ choices.each do |name, id|
84
+ if sorting_map[name.to_sym]
85
+ priority_choices[sorting_map[name.to_sym]] = [name, id]
86
+ else
87
+ temp_choices.push([name, id])
88
+ end
89
+ end
90
+ priority_choices.compact + temp_choices
91
+ end
92
+
93
+ def set_regions_options(options)
94
+ return {} unless options[:default] && options[:default][:province]
95
+
96
+ #TODO: Add validator to check if the passed province, city or district exists within the models
97
+
98
+ province_id = get_province_id(options[:default][:province])
99
+ cities = City.where(province_id: province_id)
100
+ districts = District.where(city_id: cities)
101
+
102
+ {
103
+ province_id: province_id,
104
+ city: cities.collect { |c| [ c.name, c.id ] },
105
+ district: districts.collect { |d| [ d.name, d.id ] }
106
+ }
107
+ end
108
+
109
+ def set_prompt(method, options, region_klass)
56
110
  if respond_to?("#{method}_select_prompt")
57
111
  options[:prompt] = __send__("#{method}_select_prompt")
58
112
  else
@@ -60,10 +114,17 @@ module ChinaRegions
60
114
  end
61
115
  end
62
116
 
63
- def set_html_options(object, method, html_options, next_region, prefix)
117
+ def get_province_id(province)
118
+ return province if province.to_s =~ /\A[0-9]*\z/
119
+ Province.where('name_en = ? OR name = ?', province.downcase, province).first.id
120
+ end
121
+
122
+ def set_html_options(object_name, method, html_options, next_region, prefix)
64
123
  html_options[:data] ? (html_options[:data][:region_klass] = "#{method.to_s}") : (html_options[:data] = { region_klass: "#{method.to_s}" })
65
124
  if next_region
66
- html_options[:data].merge!(region_target: "#{object}_#{prefix}#{next_region.to_s}_id", region_target_klass: next_region.to_s)
125
+ object_name = object_name.dup.gsub(/\[/, '_')
126
+ object_name = object_name.dup.gsub(/\]/, '')
127
+ html_options[:data].merge!(region_target: "#{object_name}_#{prefix}#{next_region.to_s}_id", region_target_klass: next_region.to_s)
67
128
  else
68
129
  html_options[:data].delete(:region_target)
69
130
  html_options[:data].delete(:region_target_klass)
@@ -73,38 +134,11 @@ module ChinaRegions
73
134
  def region_prompt(region_klass)
74
135
  t('views.select', model: region_klass.model_name.human)
75
136
  end
76
-
77
- def js_output
78
- %~
79
- $(function(){
80
- $('body').on('change', '.region_select', function(event) {
81
- var changedObj, targetDom;
82
- changedObj = $(event.currentTarget);
83
- targetDom = $('#' + changedObj.data('region-target'));
84
- if (targetDom.size() > 0) {
85
- $.getJSON('/china_regions/fetch_options', {klass: changedObj.data('region-target-klass'), parent_klass: changedObj.data('region-klass'), parent_id: changedObj.val()}, function(data) {
86
- $('option[value!=""]', targetDom).remove();
87
- $.each(data, function(index, value) {
88
- targetDom.append("<option value='" + value.id + "'>" + value.name + "</option>");
89
- });
90
- })
91
- // just clear out the second dropdown if it exists, they should start from the beginning
92
- secondTargetDom = $('#' + targetDom.data('region-target'));
93
- if (secondTargetDom.size() > 0) {
94
- $('option[value!=""]', secondTargetDom).remove();
95
- }
96
- }
97
- });
98
- });
99
- ~
100
- end
101
-
102
137
  end
103
138
 
104
-
105
139
  module FormBuilder
106
140
  def region_select(methods, options = {}, html_options = {})
107
- @template.region_select(@object_name, methods, options = options, html_options = html_options)
141
+ @template.region_select(@object_name.to_s, methods, options = options, html_options = html_options)
108
142
  end
109
143
  end
110
144
 
@@ -1,3 +1,3 @@
1
1
  module ChinaRegions
2
- VERSION = "0.1.0"
2
+ VERSION = "0.4.2"
3
3
  end
@@ -7,6 +7,7 @@ module ChinaRegions
7
7
 
8
8
  def copy_migration
9
9
  Dir["db/migrate/*_china_regions_tables.rb"].each{ |file| File.delete(file) }
10
+
10
11
  migration_template "migration.rb", "db/migrate/create_china_regions_tables.rb"
11
12
  end
12
13
 
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module ChinaRegions
4
- class RegionsGenerator < Rails::Generators::NamedBase
4
+ class RegionsGenerator < Rails::Generators::Base
5
5
  source_root File.expand_path('../../../../app', __FILE__)
6
6
 
7
7
  def copy_models_file
@@ -9,5 +9,9 @@ module ChinaRegions
9
9
  copy_file "models/city.rb", "app/models/city.rb"
10
10
  copy_file "models/district.rb", "app/models/district.rb"
11
11
  end
12
+
13
+ def copy_js_file
14
+ copy_file "assets/javascripts/region_select.js", "app/assets/javascripts/region_select.js"
15
+ end
12
16
  end
13
17
  end
@@ -70,7 +70,7 @@
70
70
  天津市:
71
71
  name_en: tianjin
72
72
  name_abbr: tj
73
- zip_code: '100000'
73
+ zip_code: '300000'
74
74
  level: 1
75
75
  districts:
76
76
  和平区:
@@ -11,8 +11,6 @@ class CreateChinaRegionsTables < ActiveRecord::Migration
11
11
  end
12
12
 
13
13
  add_index :provinces, :name
14
- add_index :provinces, :name_en
15
- add_index :provinces, :name_abbr
16
14
  end
17
15
 
18
16
  unless table_exists? 'cities'
@@ -25,15 +23,11 @@ class CreateChinaRegionsTables < ActiveRecord::Migration
25
23
  t.string :name_abbr
26
24
  t.timestamps
27
25
  end
26
+
28
27
  add_index :cities, :name
29
- add_index :cities, :province_id
30
- add_index :cities, :level
31
- add_index :cities, :zip_code
32
- add_index :cities, :name_en
33
- add_index :cities, :name_abbr
34
28
  end
35
29
 
36
- unless table_exists? 'districts'
30
+ unless table_exists? 'districts'
37
31
  create_table :districts do |t|
38
32
  t.string :name
39
33
  t.integer :city_id
@@ -42,9 +36,6 @@ class CreateChinaRegionsTables < ActiveRecord::Migration
42
36
  t.timestamps
43
37
  end
44
38
  add_index :districts, :name
45
- add_index :districts, :city_id
46
- add_index :districts, :name_en
47
- add_index :districts, :name_abbr
48
39
  end
49
40
  end
50
41
  end
@@ -9,6 +9,7 @@ namespace :china_regions do
9
9
  file_path = File.join(Rails.root, 'config', 'cities.yml')
10
10
  data = File.open(file_path) { |file| YAML.load(file) }
11
11
  remove_china_regions && load_to_db(data)
12
+
12
13
  puts "\n China's provinces, city, region data import is complete."
13
14
  end
14
15
 
@@ -19,8 +20,8 @@ namespace :china_regions do
19
20
  def load_to_db(data)
20
21
  data.each do |province_name, province_hash|
21
22
  province_parameters = province_params({
22
- name: province_name,
23
- name_en: province_hash['name_en'],
23
+ name: province_name,
24
+ name_en: province_hash['name_en'],
24
25
  name_abbr: province_hash['name_abbr']
25
26
  })
26
27
  province = Province.create(province_parameters)
@@ -28,9 +29,9 @@ namespace :china_regions do
28
29
  province_hash['cities'].each do |city_name, city_hash|
29
30
  city_parameters = city_params({
30
31
  province_id: province.id,
31
- name: city_name,
32
- name_en: city_hash['name_en'],
33
- name_abbr: city_hash['name_abbr'],
32
+ name: city_name,
33
+ name_en: city_hash['name_en'],
34
+ name_abbr: city_hash['name_abbr'],
34
35
  zip_code: city_hash['zip_code'],
35
36
  level: city_hash['level'] || 4
36
37
  })
@@ -40,8 +41,8 @@ namespace :china_regions do
40
41
  districts_hash.each do |district_name, district_hash|
41
42
  district_parameters = district_params({
42
43
  city_id: city.id,
43
- name: district_name,
44
- name_en: district_hash['name_en'],
44
+ name: district_name,
45
+ name_en: district_hash['name_en'],
45
46
  name_abbr: district_hash['name_abbr']
46
47
  })
47
48
  District.create(district_parameters)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: china_regions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Encore Shao
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-04-12 00:00:00.000000000 Z
12
+ date: 2015-10-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: jquery-rails
@@ -38,6 +38,7 @@ files:
38
38
  - LICENSE
39
39
  - README.md
40
40
  - Rakefile
41
+ - app/assets/javascripts/region_select.js
41
42
  - app/controllers/china_regions/fetch_options_controller.rb
42
43
  - app/models/city.rb
43
44
  - app/models/district.rb
@@ -74,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
74
75
  version: '0'
75
76
  requirements: []
76
77
  rubyforge_project:
77
- rubygems_version: 2.2.0.rc.1
78
+ rubygems_version: 2.4.5
78
79
  signing_key:
79
80
  specification_version: 4
80
81
  summary: Rails 4 version of dropdowns for all provinces, cities, and districts in