china_region_fu 0.0.6 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|