china_region_fu 0.0.6 → 0.1.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 +4 -4
- data/.gitignore +12 -5
- data/.rspec +2 -1
- data/.rubocop.yml +101 -0
- data/.travis.yml +4 -2
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +10 -4
- data/LICENSE.txt +21 -0
- data/README.en.md +212 -0
- data/README.md +103 -68
- data/Rakefile +1 -1
- data/app/controllers/china_region_fu/fetch_options_controller.rb +64 -28
- data/app/models/city.rb +1 -11
- data/app/models/district.rb +1 -11
- data/app/models/province.rb +4 -4
- data/bin/console +14 -0
- data/bin/rspec +17 -0
- data/bin/setup +8 -0
- data/china_region_fu.gemspec +20 -19
- data/db/migrate/20111111111111_create_china_region_tables.rb +19 -17
- data/lib/china_region_fu.rb +4 -3
- data/lib/china_region_fu/engine.rb +11 -9
- data/lib/china_region_fu/errors.rb +5 -0
- data/lib/china_region_fu/helpers/formtastic.rb +4 -6
- data/lib/china_region_fu/helpers/helpers.rb +44 -53
- data/lib/china_region_fu/helpers/simple_form.rb +15 -14
- data/lib/china_region_fu/helpers/utils.rb +82 -0
- data/lib/china_region_fu/version.rb +1 -1
- data/lib/generators/china_region_fu/models/USAGE +1 -1
- data/lib/generators/china_region_fu/models/models_generator.rb +3 -3
- data/lib/tasks/{region.rake → china_region_fu_tasks.rake} +8 -14
- data/spec/china_region_fu_spec.rb +3 -7
- data/spec/helpers/helpers_spec.rb +113 -0
- data/spec/helpers/utils_spec.rb +87 -0
- data/spec/spec_helper.rb +6 -1
- data/spec/support/models.rb +39 -0
- metadata +50 -61
- data/LICENSE +0 -22
- data/lib/china_region_fu/exceptions.rb +0 -7
- data/lib/china_region_fu/helpers/utilities.rb +0 -54
data/bin/setup
ADDED
data/china_region_fu.gemspec
CHANGED
@@ -1,27 +1,28 @@
|
|
1
|
-
# coding: utf-8
|
2
1
|
lib = File.expand_path('../lib', __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'china_region_fu/version'
|
5
4
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
6
|
+
spec.name = 'china_region_fu'
|
8
7
|
spec.version = ChinaRegionFu::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.
|
12
|
-
spec.
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
15
|
-
|
16
|
-
|
8
|
+
spec.authors = ['Xuhao']
|
9
|
+
spec.email = ['xuhao@rubyfans.com']
|
10
|
+
spec.summary = 'china_region_fu provides simple helpers to get an HTML select list of countries, cities and districts.'
|
11
|
+
spec.description = 'china_region_fu provides simple helpers to get an HTML select list of countries, cities and districts.'
|
12
|
+
spec.homepage = 'https://github.com/Xuhao/china_region_fu'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
15
|
+
f.match(%r{^(test|spec|features)/})
|
16
|
+
end
|
17
|
+
spec.bindir = 'bin'
|
17
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
-
spec.test_files = spec
|
19
|
-
spec.require_paths = [
|
19
|
+
spec.test_files = Dir['spec/**/*']
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
spec.required_ruby_version = '>= 2.2.2'
|
22
|
+
spec.required_rubygems_version = '>= 1.8.11'
|
20
23
|
|
21
|
-
spec.add_development_dependency
|
22
|
-
spec.add_development_dependency
|
23
|
-
spec.
|
24
|
-
spec.add_dependency '
|
25
|
-
|
26
|
-
spec.add_dependency 'httparty'
|
27
|
-
end
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.13'
|
25
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
26
|
+
spec.add_dependency 'activesupport', '>= 4.0'
|
27
|
+
spec.add_dependency 'httparty', '~> 0.14.0'
|
28
|
+
end
|
@@ -7,12 +7,12 @@ class CreateChinaRegionTables < ActiveRecord::Migration
|
|
7
7
|
t.string :pinyin_abbr
|
8
8
|
t.timestamps
|
9
9
|
end
|
10
|
-
|
11
|
-
add_index :provinces, :name
|
12
|
-
add_index :provinces, :pinyin
|
13
|
-
add_index :provinces, :pinyin_abbr
|
10
|
+
|
11
|
+
add_index(:provinces, :name) unless index_exists?(:provinces, :name)
|
12
|
+
add_index(:provinces, :pinyin) unless index_exists?(:provinces, :pinyin)
|
13
|
+
add_index(:provinces, :pinyin_abbr) unless index_exists?(:provinces, :pinyin_abbr)
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
unless table_exists? 'cities'
|
17
17
|
create_table :cities do |t|
|
18
18
|
t.string :name
|
@@ -23,14 +23,15 @@ class CreateChinaRegionTables < ActiveRecord::Migration
|
|
23
23
|
t.string :pinyin_abbr
|
24
24
|
t.timestamps
|
25
25
|
end
|
26
|
-
|
27
|
-
add_index :cities, :
|
28
|
-
add_index :cities, :
|
29
|
-
add_index :cities, :
|
30
|
-
add_index :cities, :
|
31
|
-
add_index :cities, :
|
26
|
+
|
27
|
+
add_index(:cities, :name) unless index_exists?(:cities, :name)
|
28
|
+
add_index(:cities, :province_id) unless index_exists?(:cities, :province_id)
|
29
|
+
add_index(:cities, :level) unless index_exists?(:cities, :level)
|
30
|
+
add_index(:cities, :zip_code) unless index_exists?(:cities, :zip_code)
|
31
|
+
add_index(:cities, :pinyin) unless index_exists?(:cities, :pinyin)
|
32
|
+
add_index(:cities, :pinyin_abbr) unless index_exists?(:cities, :pinyin_abbr)
|
32
33
|
end
|
33
|
-
|
34
|
+
|
34
35
|
unless table_exists? 'districts'
|
35
36
|
create_table :districts do |t|
|
36
37
|
t.string :name
|
@@ -39,10 +40,11 @@ class CreateChinaRegionTables < ActiveRecord::Migration
|
|
39
40
|
t.string :pinyin_abbr
|
40
41
|
t.timestamps
|
41
42
|
end
|
42
|
-
|
43
|
-
add_index :districts, :
|
44
|
-
add_index :districts, :
|
45
|
-
add_index :districts, :
|
43
|
+
|
44
|
+
add_index(:districts, :name) unless index_exists?(:districts, :name)
|
45
|
+
add_index(:districts, :city_id) unless index_exists?(:districts, :city_id)
|
46
|
+
add_index(:districts, :pinyin) unless index_exists?(:districts, :pinyin)
|
47
|
+
add_index(:districts, :pinyin_abbr) unless index_exists?(:districts, :pinyin_abbr)
|
46
48
|
end
|
47
49
|
end
|
48
|
-
end
|
50
|
+
end
|
data/lib/china_region_fu.rb
CHANGED
@@ -1,18 +1,20 @@
|
|
1
|
-
require
|
1
|
+
require 'rails'
|
2
2
|
require 'china_region_fu/helpers/helpers'
|
3
3
|
|
4
4
|
module ChinaRegionFu
|
5
|
-
class Engine < Rails::Engine
|
6
|
-
|
5
|
+
class Engine < ::Rails::Engine
|
6
|
+
isolate_namespace ChinaRegionFu
|
7
|
+
|
8
|
+
initializer 'china_region_fu: form helper extensions' do
|
7
9
|
ActiveSupport.on_load :action_view do
|
8
|
-
ActionView::Base.send :include, ChinaRegionFu::Helpers
|
9
|
-
ActionView::Helpers::FormBuilder.send :include, ChinaRegionFu::FormBuilder
|
10
|
+
ActionView::Base.send :include, ChinaRegionFu::Helpers::FormHelper
|
11
|
+
ActionView::Helpers::FormBuilder.send :include, ChinaRegionFu::Helpers::FormBuilder
|
10
12
|
end
|
11
13
|
end
|
12
14
|
|
13
|
-
initializer
|
14
|
-
require
|
15
|
-
require
|
15
|
+
initializer 'china_region_fu: third-party extensions' do
|
16
|
+
require 'china_region_fu/helpers/simple_form' if Object.const_defined?('SimpleForm')
|
17
|
+
require 'china_region_fu/helpers/formtastic' if Object.const_defined?('Formtastic')
|
16
18
|
end
|
17
19
|
end
|
18
|
-
end
|
20
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require 'china_region_fu/helpers/
|
1
|
+
require 'china_region_fu/helpers/utils'
|
2
2
|
|
3
3
|
class RegionInput < Formtastic::Inputs::SelectInput
|
4
|
-
include ChinaRegionFu::
|
4
|
+
include ChinaRegionFu::Utils
|
5
5
|
|
6
6
|
def collection_from_options
|
7
7
|
return [] unless options.key?(:collection)
|
@@ -9,8 +9,6 @@ class RegionInput < Formtastic::Inputs::SelectInput
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def input_html_options
|
12
|
-
|
13
|
-
the_options = set_html_options(object_name, input_name, the_options, input_options.delete(:sub_region).to_s.sub(/_id\Z/, '').foreign_key) if input_options.key?(:sub_region)
|
14
|
-
the_options
|
12
|
+
append_html_options(input_name, input_options.delete(:sub_region), super)
|
15
13
|
end
|
16
|
-
end
|
14
|
+
end
|
@@ -1,70 +1,61 @@
|
|
1
|
-
require 'china_region_fu/
|
2
|
-
require 'china_region_fu/helpers/
|
1
|
+
require 'china_region_fu/errors'
|
2
|
+
require 'china_region_fu/helpers/utils'
|
3
|
+
require 'active_support/core_ext/object/blank'
|
3
4
|
|
4
5
|
module ChinaRegionFu
|
5
6
|
module Helpers
|
6
|
-
|
7
|
+
module FormHelper
|
8
|
+
include Utils
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
if Array === names
|
12
|
-
output = ActiveSupport::SafeBuffer.new
|
13
|
-
names.each_with_index do |name, index|
|
14
|
-
if klass = to_class(name)
|
15
|
-
choices = index == 0 ? options_from_collection_for_select(klass.select('id, name'), "id", "name") : ''
|
16
|
-
next_name = names.at(index + 1)
|
17
|
-
set_html_options(nil, name, options, next_name)
|
10
|
+
def region_select_tag(regions, options = {})
|
11
|
+
render_region_select_tags(nil, regions, ActiveSupport::SafeBuffer.new, options)
|
12
|
+
end
|
18
13
|
|
19
|
-
|
20
|
-
|
21
|
-
raise InvalidAttributeError
|
22
|
-
end
|
23
|
-
end
|
24
|
-
output << js_for_region_ajax if names.size > 1
|
25
|
-
output
|
26
|
-
else
|
27
|
-
if klass = to_class(names)
|
28
|
-
select_tag(names, options_from_collection_for_select(klass.select('id, name'), "id", "name"), options)
|
29
|
-
else
|
30
|
-
raise InvalidAttributeError
|
31
|
-
end
|
14
|
+
def region_select(object, methods, options = {}, html_options = {})
|
15
|
+
render_region_select_tags(object, methods, ActiveSupport::SafeBuffer.new, options, html_options)
|
32
16
|
end
|
33
|
-
end
|
34
17
|
|
35
|
-
|
36
|
-
options.symbolize_keys!
|
37
|
-
html_options.symbolize_keys!
|
38
|
-
append_region_class(html_options)
|
18
|
+
private
|
39
19
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
20
|
+
def render_region_select_tags(object, regions, buffer = ActiveSupport::SafeBuffer.new, options = {}, html_options = {})
|
21
|
+
regions = (regions.is_a?(Symbol) || regions.is_a?(String)) ? [regions] : regions.to_a
|
22
|
+
regions.each_with_index do |region, index|
|
23
|
+
if klass = region.to_s.sub(/_id\Z/, '').classify.safe_constantize
|
24
|
+
buffer << content_tag(:div, make_select(object, klass, region, regions.at(index + 1), index, options, html_options), class: "input region #{region}")
|
25
|
+
else
|
26
|
+
raise ChinaRegionFu::InvalidFieldError, "Invalid region field: `#{region}`, valid fields are: province, province_id, city, city_id, district and district_id."
|
27
|
+
end
|
28
|
+
end
|
29
|
+
content_for(:china_region_fu_js) { china_region_fu_js }
|
30
|
+
buffer
|
31
|
+
end
|
47
32
|
|
48
|
-
|
33
|
+
def make_select(object, klass, region, sub_region, order_index, options = {}, html_options = {})
|
34
|
+
choices = order_index == 0 ? klass.pluck(:name, :id) : get_choices(object, klass, region, options[:object])
|
35
|
+
if object
|
36
|
+
select(object, region, choices, append_prompt(region, options), append_html_options(region, sub_region, html_options))
|
49
37
|
else
|
50
|
-
|
38
|
+
select_tag(region, options_for_select(choices), append_html_options(region, sub_region, append_prompt(region, options)))
|
51
39
|
end
|
52
40
|
end
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
41
|
+
|
42
|
+
def get_choices(object, klass, region, ar_object)
|
43
|
+
return [] if object.blank?
|
44
|
+
return [] if !ar_object.is_a?(ActiveRecord::Base)
|
45
|
+
if %w(city city_id).include?(region.to_s) && ar_object.province_id.present?
|
46
|
+
klass.where(province_id: ar_object.province_id).pluck(:name, :id)
|
47
|
+
elsif %w(district district_id).include?(region.to_s) && ar_object.city_id.present?
|
48
|
+
klass.where(city_id: ar_object.city_id).pluck(:name, :id)
|
49
|
+
else
|
50
|
+
[]
|
51
|
+
end
|
60
52
|
end
|
61
|
-
end
|
62
53
|
end
|
63
|
-
end
|
64
54
|
|
65
|
-
|
66
|
-
|
67
|
-
|
55
|
+
module FormBuilder
|
56
|
+
def region_select(methods, options = {}, html_options = {})
|
57
|
+
@template.region_select(@object_name, methods, objectify_options(options), @default_options.merge(html_options))
|
58
|
+
end
|
68
59
|
end
|
69
60
|
end
|
70
|
-
end
|
61
|
+
end
|
@@ -1,23 +1,24 @@
|
|
1
|
-
require 'china_region_fu/helpers/
|
1
|
+
require 'china_region_fu/helpers/utils'
|
2
2
|
|
3
3
|
module ChinaRegionFu
|
4
4
|
module SimpleForm
|
5
|
-
class RegionInput < ::SimpleForm::Inputs::
|
6
|
-
include ChinaRegionFu::
|
5
|
+
class RegionInput < ::SimpleForm::Inputs::CollectionSelectInput
|
6
|
+
include ChinaRegionFu::Utils
|
7
|
+
def input_html_options
|
8
|
+
append_html_options(attribute_name, sub_region, super)
|
9
|
+
end
|
7
10
|
|
8
|
-
def
|
9
|
-
|
10
|
-
append_region_class(input_html_options)
|
11
|
-
set_html_options(object_name, attribute_name, input_html_options, input_options.delete(:sub_region)) if input_options.key?(:sub_region)
|
12
|
-
region_collection = collection
|
13
|
-
region_collection = [] if region_collection == ::SimpleForm::Inputs::CollectionInput.boolean_collection
|
14
|
-
@builder.collection_select(
|
15
|
-
attribute_name, region_collection, value_method, label_method,
|
16
|
-
input_options, input_html_options
|
17
|
-
)
|
11
|
+
def collection
|
12
|
+
@collection ||= options.delete(:collection) || []
|
18
13
|
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def sub_region
|
18
|
+
@sub_region ||= input_options.delete(:sub_region)
|
19
|
+
end
|
19
20
|
end
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
23
|
-
::SimpleForm::FormBuilder.map_type :region, to: ChinaRegionFu::SimpleForm::RegionInput
|
24
|
+
::SimpleForm::FormBuilder.map_type :region, to: ChinaRegionFu::SimpleForm::RegionInput
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'active_support/core_ext/object/deep_dup'
|
2
|
+
require 'active_support/core_ext/string/output_safety'
|
3
|
+
|
4
|
+
module ChinaRegionFu
|
5
|
+
module Utils
|
6
|
+
def china_region_fu_js
|
7
|
+
js = <<-JAVASCRIPT
|
8
|
+
<script type="text/javascript">
|
9
|
+
//<![CDATA[
|
10
|
+
window.chinaRegionFu = window.chinaRegionFu || {};
|
11
|
+
$(function(){
|
12
|
+
$('body').off('change', '.china-region-select').on('change', '.china-region-select', function(event) {
|
13
|
+
var $self = $(event.currentTarget),
|
14
|
+
$subRegionDom = $('[data-region-name="' + $self.data('sub-region') + '"]'),
|
15
|
+
subName = $self.data('sub-region'),
|
16
|
+
parentName = $self.data('region-name'),
|
17
|
+
parentId = $self.val();
|
18
|
+
if ($subRegionDom.size() > 0 && subName && parentName && parentId) {
|
19
|
+
$.getJSON('/china_region_fu/fetch_options', {
|
20
|
+
columns: window.chinaRegionFu.fetchColumns || 'id,name',
|
21
|
+
sub_name: subName,
|
22
|
+
parent_name: parentName,
|
23
|
+
parent_id: parentId
|
24
|
+
}, function(json) {
|
25
|
+
if (window.chinaRegionFu.ajaxDone) {
|
26
|
+
window.chinaRegionFu.ajaxDone(json);
|
27
|
+
} else {
|
28
|
+
var options = [];
|
29
|
+
$self.parent().nextAll().find('.china-region-select > option[value!=""]').remove()
|
30
|
+
$.each(json.data, function(_, value) {
|
31
|
+
options.push("<option value='" + value.id + "'>" + value.name + "</option>");
|
32
|
+
});
|
33
|
+
$subRegionDom.append(options.join(''));
|
34
|
+
}
|
35
|
+
}).fail(function(xhr, textStatus, error) {
|
36
|
+
window.chinaRegionFu.ajaxFail && window.chinaRegionFu.ajaxFail(xhr, textStatus, error);
|
37
|
+
}).always(function(event, xhr, settings) {
|
38
|
+
window.chinaRegionFu.ajaxAlways && window.chinaRegionFu.ajaxAlways(event, xhr, settings);
|
39
|
+
});
|
40
|
+
}
|
41
|
+
});
|
42
|
+
});
|
43
|
+
//]]>
|
44
|
+
</script>
|
45
|
+
JAVASCRIPT
|
46
|
+
js.html_safe
|
47
|
+
end
|
48
|
+
|
49
|
+
def append_html_class_option(html_options)
|
50
|
+
_html_options = html_options.deep_dup
|
51
|
+
_html_options[:class] ||= ''
|
52
|
+
_html_options[:class] << ' china-region-select' unless _html_options[:class].include?('china-region-select')
|
53
|
+
_html_options
|
54
|
+
end
|
55
|
+
|
56
|
+
def append_html_data_option(current_region, sub_region, html_options)
|
57
|
+
_html_options = html_options.deep_dup
|
58
|
+
_html_options[:data] ||= {}
|
59
|
+
_html_options[:data][:region_name] = current_region
|
60
|
+
if sub_region
|
61
|
+
_html_options[:data][:sub_region] = sub_region
|
62
|
+
else
|
63
|
+
_html_options[:data].delete(:sub_region)
|
64
|
+
end
|
65
|
+
_html_options
|
66
|
+
end
|
67
|
+
|
68
|
+
def append_html_options(current_region, sub_region, html_options)
|
69
|
+
_html_options = html_options.deep_dup
|
70
|
+
_html_options = append_html_class_option(_html_options)
|
71
|
+
_html_options = append_html_data_option(current_region, sub_region, _html_options)
|
72
|
+
_html_options
|
73
|
+
end
|
74
|
+
|
75
|
+
def append_prompt(current_region, options)
|
76
|
+
current_name = current_region.to_s.sub(/_id\Z/, '')
|
77
|
+
options_without_prompt = options.except(:province_prompt, :city_prompt, :district_prompt)
|
78
|
+
options_without_prompt[:prompt] = options["#{current_name}_prompt".to_sym]
|
79
|
+
options_without_prompt
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -3,9 +3,9 @@ module ChinaRegionFu
|
|
3
3
|
source_root File.expand_path('../../../../../app', __FILE__)
|
4
4
|
|
5
5
|
def copy_model_files
|
6
|
-
copy_file
|
7
|
-
copy_file
|
8
|
-
copy_file
|
6
|
+
copy_file 'models/province.rb', 'app/models/province.rb'
|
7
|
+
copy_file 'models/city.rb', 'app/models/city.rb'
|
8
|
+
copy_file 'models/district.rb', 'app/models/district.rb'
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|