china_regions 0.1.0 → 0.4.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.
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