activerecord-bixformer 0.1.1 → 0.2.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/README-ja.md +10 -10
- data/lib/activerecord-bixformer/assignable_attributes_normalizer.rb +125 -0
- data/lib/activerecord-bixformer/attribute/booletania.rb +4 -6
- data/lib/activerecord-bixformer/attribute/enumerize.rb +4 -2
- data/lib/activerecord-bixformer/autoload.rb +27 -0
- data/lib/activerecord-bixformer/compiler.rb +45 -0
- data/lib/activerecord-bixformer/format/csv.rb +20 -0
- data/lib/activerecord-bixformer/from/csv.rb +15 -0
- data/lib/activerecord-bixformer/import_value_validatable.rb +21 -0
- data/lib/activerecord-bixformer/model/base.rb +67 -81
- data/lib/activerecord-bixformer/model/csv/base.rb +31 -23
- data/lib/activerecord-bixformer/model/csv/indexed.rb +31 -24
- data/lib/activerecord-bixformer/plan.rb +56 -0
- data/lib/activerecord-bixformer/plan_accessor.rb +131 -0
- data/lib/activerecord-bixformer/to/csv.rb +56 -0
- data/lib/activerecord-bixformer/version.rb +1 -1
- data/lib/activerecord-bixformer.rb +2 -43
- metadata +11 -9
- data/lib/activerecord-bixformer/generator/active_record.rb +0 -170
- data/lib/activerecord-bixformer/generator/base.rb +0 -66
- data/lib/activerecord-bixformer/generator/csv_row.rb +0 -40
- data/lib/activerecord-bixformer/modeler/base.rb +0 -160
- data/lib/activerecord-bixformer/modeler/csv.rb +0 -11
- data/lib/activerecord-bixformer/runner/base.rb +0 -47
- data/lib/activerecord-bixformer/runner/csv.rb +0 -123
@@ -3,47 +3,54 @@ module ActiveRecord
|
|
3
3
|
module Model
|
4
4
|
module Csv
|
5
5
|
class Indexed < ::ActiveRecord::Bixformer::Model::Csv::Base
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
def initialize(model_or_association_name, options)
|
7
|
+
super
|
8
|
+
|
9
|
+
@options = options.is_a?(::Hash) ? options : {}
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
@options[:size] ||= 1
|
12
|
+
end
|
13
13
|
|
14
|
-
|
14
|
+
def make_export_value(activerecord_or_activerecords)
|
15
|
+
activerecord_or_activerecords ||= []
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
# has_many でしか使わない想定なので activerecord_or_activerecords は Array のはず
|
18
|
+
(1..options[:size]).inject({}) do |values, index|
|
19
|
+
update_translator(index)
|
20
|
+
|
21
|
+
values.merge(super(activerecord_or_activerecords[index-1]))
|
18
22
|
end
|
23
|
+
end
|
19
24
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
25
|
+
def make_import_value(csv_row, parent_activerecord_id = nil)
|
26
|
+
# has_many でしか使わない想定なので Array を返却
|
27
|
+
(1..options[:size]).map do |index|
|
28
|
+
update_translator(index)
|
24
29
|
|
25
|
-
|
26
|
-
|
30
|
+
super
|
31
|
+
end
|
32
|
+
end
|
27
33
|
|
28
|
-
|
34
|
+
def csv_titles
|
35
|
+
(1..options[:size]).flat_map do |index|
|
36
|
+
update_translator(index)
|
29
37
|
|
30
|
-
|
31
|
-
end
|
38
|
+
super
|
32
39
|
end
|
33
40
|
end
|
34
41
|
|
35
|
-
|
36
|
-
super
|
42
|
+
private
|
37
43
|
|
38
|
-
|
44
|
+
def update_translator(index)
|
45
|
+
@translator.model_arguments = { index: index }
|
39
46
|
|
40
|
-
@translator.attribute_arguments_map = @
|
41
|
-
[
|
47
|
+
@translator.attribute_arguments_map = @attributes.map do |attr|
|
48
|
+
[attr.name, { index: index }]
|
42
49
|
end.to_h
|
43
50
|
end
|
44
51
|
|
45
52
|
def csv_title(attribute_name)
|
46
|
-
if parents.find { |parent| parent.is_a?(ActiveRecord::Bixformer::Model::Csv::Indexed) }
|
53
|
+
if parents.find { |parent| parent.is_a?(::ActiveRecord::Bixformer::Model::Csv::Indexed) }
|
47
54
|
parents.map { |parent| parent.translator.translate_model }.join + super
|
48
55
|
else
|
49
56
|
super
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Bixformer
|
3
|
+
module Plan
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
attr_accessor :__bixformer_format
|
8
|
+
|
9
|
+
class_attribute :__bixformer_model
|
10
|
+
|
11
|
+
class_attribute :__bixformer_namespace
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
def bixformer_for(model_name)
|
16
|
+
self.__bixformer_model = model_name
|
17
|
+
end
|
18
|
+
|
19
|
+
def bixformer_load_namespace(namespace)
|
20
|
+
self.__bixformer_namespace = namespace
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def entry
|
25
|
+
{}
|
26
|
+
end
|
27
|
+
|
28
|
+
def optional_attributes
|
29
|
+
[]
|
30
|
+
end
|
31
|
+
|
32
|
+
def required_attributes
|
33
|
+
[]
|
34
|
+
end
|
35
|
+
|
36
|
+
def unique_indexes
|
37
|
+
[]
|
38
|
+
end
|
39
|
+
|
40
|
+
def required_condition
|
41
|
+
{}
|
42
|
+
end
|
43
|
+
|
44
|
+
def default_values
|
45
|
+
{}
|
46
|
+
end
|
47
|
+
|
48
|
+
def translation_config
|
49
|
+
{
|
50
|
+
scope: :bixformer,
|
51
|
+
extend_scopes: []
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Bixformer
|
3
|
+
class PlanAccessor
|
4
|
+
def initialize(plan)
|
5
|
+
@plan = plan
|
6
|
+
@module_constant_of = {}
|
7
|
+
@module_load_namespaces_of = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def raw_value
|
11
|
+
@plan
|
12
|
+
end
|
13
|
+
|
14
|
+
def value_of(config_name)
|
15
|
+
@plan.__send__(config_name)
|
16
|
+
end
|
17
|
+
|
18
|
+
def pickup_value_for(model, config_name, default_value = nil)
|
19
|
+
model_names_without_root = (model.parents.map(&:name) + [model.name]).drop(1)
|
20
|
+
|
21
|
+
# 指定された設定の全設定値を取得
|
22
|
+
entire_config_value = @plan.__send__(config_name)
|
23
|
+
|
24
|
+
if entire_config_value.is_a?(::Hash)
|
25
|
+
# Hashなら、with_indifferent_accessしておく
|
26
|
+
entire_config_value = entire_config_value.with_indifferent_access
|
27
|
+
elsif entire_config_value.is_a?(::Array) && entire_config_value.last.is_a?(::Hash)
|
28
|
+
# Arrayで最後の要素がHashなら、with_indifferent_accessしておく
|
29
|
+
config_value = entire_config_value.pop
|
30
|
+
|
31
|
+
entire_config_value.push config_value.with_indifferent_access
|
32
|
+
end
|
33
|
+
|
34
|
+
# その中から、指定のmodelに対応する設定部分を抽出
|
35
|
+
config_value = if config_name == :entry
|
36
|
+
find_entry(entire_config_value, model_names_without_root)
|
37
|
+
else
|
38
|
+
find_nested_config_value(entire_config_value, model_names_without_root)
|
39
|
+
end
|
40
|
+
|
41
|
+
if config_value.is_a?(::Array)
|
42
|
+
# Arrayで最後の要素がHashの場合、それは子要素の設定値なので、結果に含めない
|
43
|
+
config_value.pop if config_value.last.is_a?(::Hash)
|
44
|
+
|
45
|
+
# Arrayなら、要素は文字列化しておく
|
46
|
+
config_value = config_value.map { |v| v.to_s }
|
47
|
+
end
|
48
|
+
|
49
|
+
config_value || default_value
|
50
|
+
end
|
51
|
+
|
52
|
+
def new_module_instance(module_type, name_or_instance, *initializers)
|
53
|
+
name_or_instance = :base unless name_or_instance
|
54
|
+
|
55
|
+
name_or_instance = name_or_instance.to_s if name_or_instance.is_a?(::Symbol)
|
56
|
+
|
57
|
+
return name_or_instance unless name_or_instance.is_a?(::String)
|
58
|
+
|
59
|
+
if initializers.size > 0
|
60
|
+
find_module_constant(module_type, name_or_instance).new(*initializers)
|
61
|
+
else
|
62
|
+
find_module_constant(module_type, name_or_instance).new
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def find_module_constant(module_type, name)
|
67
|
+
name = :base unless name
|
68
|
+
|
69
|
+
module_constant = @module_constant_of["#{module_type}/#{name}"]
|
70
|
+
|
71
|
+
return module_constant if module_constant
|
72
|
+
|
73
|
+
namespaces = @module_load_namespaces_of[module_type] ||= module_load_namespaces(module_type)
|
74
|
+
|
75
|
+
namespaces.each do |namespace|
|
76
|
+
constant = "#{namespace}::#{name.to_s.camelize}".safe_constantize
|
77
|
+
|
78
|
+
return @module_constant_of["#{module_type}/#{name}"] = constant if constant
|
79
|
+
end
|
80
|
+
|
81
|
+
raise ::ArgumentError.new "Not found module named #{name.to_s.camelize} in module_load_namespaces('#{module_type}')"
|
82
|
+
end
|
83
|
+
|
84
|
+
def parse_to_type_and_options(value)
|
85
|
+
value = value.dup if value.is_a?(::Array) || value.is_a?(::Hash)
|
86
|
+
type = value.is_a?(::Array) ? value.shift : value
|
87
|
+
|
88
|
+
arguments = if value.is_a?(::Array) && value.size == 1 && value.first.is_a?(::Hash)
|
89
|
+
value.first
|
90
|
+
elsif value.is_a?(::Array)
|
91
|
+
value
|
92
|
+
else
|
93
|
+
nil
|
94
|
+
end
|
95
|
+
|
96
|
+
[type, arguments]
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def find_nested_config_value(config, keys)
|
102
|
+
return config ? config.dup : nil if keys.empty?
|
103
|
+
|
104
|
+
key = keys.shift
|
105
|
+
|
106
|
+
# config が Array なら、子要素は最後の要素にハッシュで定義してあるはず
|
107
|
+
config_map = config.is_a?(::Array) ? config.last : config
|
108
|
+
|
109
|
+
return nil unless config_map.is_a?(::Hash)
|
110
|
+
|
111
|
+
find_nested_config_value(config_map[key], keys)
|
112
|
+
end
|
113
|
+
|
114
|
+
def find_entry(config, keys)
|
115
|
+
return config ? config.dup : nil if keys.empty?
|
116
|
+
|
117
|
+
key = keys.shift
|
118
|
+
|
119
|
+
find_entry(config[:associations][key], keys)
|
120
|
+
end
|
121
|
+
|
122
|
+
def module_load_namespaces(module_type)
|
123
|
+
[
|
124
|
+
@plan.class.__bixformer_namespace,
|
125
|
+
"::ActiveRecord::Bixformer::#{module_type.to_s.camelize}::#{@plan.__bixformer_format.camelize}",
|
126
|
+
"::ActiveRecord::Bixformer::#{module_type.to_s.camelize}",
|
127
|
+
].compact
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Bixformer
|
3
|
+
module To
|
4
|
+
class Csv < ::ActiveRecord::Bixformer::Compiler
|
5
|
+
def initialize(plan)
|
6
|
+
super(:csv, plan)
|
7
|
+
end
|
8
|
+
|
9
|
+
def csv_title_row
|
10
|
+
compile.csv_titles
|
11
|
+
end
|
12
|
+
|
13
|
+
def csv_body_row(activerecord)
|
14
|
+
model = compile
|
15
|
+
body_map = model.make_export_value(activerecord)
|
16
|
+
|
17
|
+
model.csv_titles.map { |title| body_map[title] }
|
18
|
+
end
|
19
|
+
|
20
|
+
# private
|
21
|
+
|
22
|
+
# def csv_body_map_by_model(model, activerecord_or_activerecords)
|
23
|
+
# activerecord_or_activerecords = if activerecord_or_activerecords.is_a?(::ActiveRecord::Relation)
|
24
|
+
# activerecord_or_activerecords.to_a
|
25
|
+
# else
|
26
|
+
# activerecord_or_activerecords
|
27
|
+
# end
|
28
|
+
|
29
|
+
# model.generate_export_value(activerecord_or_activerecords).merge(
|
30
|
+
# csv_body_map_by_association(model, activerecord_or_activerecords)
|
31
|
+
# )
|
32
|
+
# end
|
33
|
+
|
34
|
+
# def csv_body_map_by_association(model, activerecord_or_activerecords)
|
35
|
+
# model.associations.inject({}) do |body_map, association_model|
|
36
|
+
# activerecords = if activerecord_or_activerecords.is_a?(::Array)
|
37
|
+
# activerecord_or_activerecords
|
38
|
+
# else
|
39
|
+
# [activerecord_or_activerecords]
|
40
|
+
# end
|
41
|
+
|
42
|
+
# body_map.merge(
|
43
|
+
# activerecords.inject({}) do |body_each_map, activerecord|
|
44
|
+
# association_value = activerecord.__send__(association_model.name)
|
45
|
+
|
46
|
+
# body_each_map.merge(
|
47
|
+
# csv_body_map_by_model(association_model, association_value)
|
48
|
+
# )
|
49
|
+
# end
|
50
|
+
# )
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -1,44 +1,3 @@
|
|
1
1
|
require 'activerecord-bixformer/version'
|
2
|
-
|
3
|
-
|
4
|
-
module Bixformer
|
5
|
-
module Attribute
|
6
|
-
autoload :Base, 'activerecord-bixformer/attribute/base'
|
7
|
-
autoload :Boolean, 'activerecord-bixformer/attribute/boolean'
|
8
|
-
autoload :Booletania, 'activerecord-bixformer/attribute/booletania'
|
9
|
-
autoload :Date, 'activerecord-bixformer/attribute/date'
|
10
|
-
autoload :Enumerize, 'activerecord-bixformer/attribute/enumerize'
|
11
|
-
autoload :Override, 'activerecord-bixformer/attribute/override'
|
12
|
-
autoload :Time, 'activerecord-bixformer/attribute/time'
|
13
|
-
end
|
14
|
-
|
15
|
-
module Generator
|
16
|
-
autoload :ActiveRecord, 'activerecord-bixformer/generator/active_record'
|
17
|
-
autoload :Base, 'activerecord-bixformer/generator/base'
|
18
|
-
autoload :CsvRow, 'activerecord-bixformer/generator/csv_row'
|
19
|
-
end
|
20
|
-
|
21
|
-
module Model
|
22
|
-
autoload :Base, 'activerecord-bixformer/model/base'
|
23
|
-
|
24
|
-
module Csv
|
25
|
-
autoload :Base, 'activerecord-bixformer/model/csv/base'
|
26
|
-
autoload :Indexed, 'activerecord-bixformer/model/csv/indexed'
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
module Modeler
|
31
|
-
autoload :Base, 'activerecord-bixformer/modeler/base'
|
32
|
-
autoload :Csv, 'activerecord-bixformer/modeler/csv'
|
33
|
-
end
|
34
|
-
|
35
|
-
module Runner
|
36
|
-
autoload :Base, 'activerecord-bixformer/runner/base'
|
37
|
-
autoload :Csv, 'activerecord-bixformer/runner/csv'
|
38
|
-
end
|
39
|
-
|
40
|
-
module Translator
|
41
|
-
autoload :I18n, 'activerecord-bixformer/translator/i18n'
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
2
|
+
require 'activerecord-bixformer/autoload'
|
3
|
+
require 'activerecord-bixformer/format/csv'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-bixformer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hiroaki Otsu
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-09-
|
11
|
+
date: 2016-09-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -222,6 +222,7 @@ files:
|
|
222
222
|
- Rakefile
|
223
223
|
- activerecord-bixformer.gemspec
|
224
224
|
- lib/activerecord-bixformer.rb
|
225
|
+
- lib/activerecord-bixformer/assignable_attributes_normalizer.rb
|
225
226
|
- lib/activerecord-bixformer/attribute/base.rb
|
226
227
|
- lib/activerecord-bixformer/attribute/boolean.rb
|
227
228
|
- lib/activerecord-bixformer/attribute/booletania.rb
|
@@ -229,16 +230,17 @@ files:
|
|
229
230
|
- lib/activerecord-bixformer/attribute/enumerize.rb
|
230
231
|
- lib/activerecord-bixformer/attribute/override.rb
|
231
232
|
- lib/activerecord-bixformer/attribute/time.rb
|
232
|
-
- lib/activerecord-bixformer/
|
233
|
-
- lib/activerecord-bixformer/
|
234
|
-
- lib/activerecord-bixformer/
|
233
|
+
- lib/activerecord-bixformer/autoload.rb
|
234
|
+
- lib/activerecord-bixformer/compiler.rb
|
235
|
+
- lib/activerecord-bixformer/format/csv.rb
|
236
|
+
- lib/activerecord-bixformer/from/csv.rb
|
237
|
+
- lib/activerecord-bixformer/import_value_validatable.rb
|
235
238
|
- lib/activerecord-bixformer/model/base.rb
|
236
239
|
- lib/activerecord-bixformer/model/csv/base.rb
|
237
240
|
- lib/activerecord-bixformer/model/csv/indexed.rb
|
238
|
-
- lib/activerecord-bixformer/
|
239
|
-
- lib/activerecord-bixformer/
|
240
|
-
- lib/activerecord-bixformer/
|
241
|
-
- lib/activerecord-bixformer/runner/csv.rb
|
241
|
+
- lib/activerecord-bixformer/plan.rb
|
242
|
+
- lib/activerecord-bixformer/plan_accessor.rb
|
243
|
+
- lib/activerecord-bixformer/to/csv.rb
|
242
244
|
- lib/activerecord-bixformer/translator/i18n.rb
|
243
245
|
- lib/activerecord-bixformer/version.rb
|
244
246
|
homepage: https://github.com/aki2o/activerecord-bixformer
|
@@ -1,170 +0,0 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Bixformer
|
3
|
-
module Generator
|
4
|
-
class ActiveRecord < ::ActiveRecord::Bixformer::Generator::Base
|
5
|
-
private
|
6
|
-
|
7
|
-
def association_generator
|
8
|
-
:new_as_association_for_import
|
9
|
-
end
|
10
|
-
|
11
|
-
def generate_model_value(model)
|
12
|
-
generate_attributes_value(model).merge(generate_association_value(model))
|
13
|
-
end
|
14
|
-
|
15
|
-
def generate_attributes_value(model)
|
16
|
-
attribute_value_map = model.generate_import_value_map
|
17
|
-
required_attributes = @modeler.config_value_for(model, :required_attributes, [])
|
18
|
-
identified_column_name = identified_column_name_of(model)
|
19
|
-
|
20
|
-
# 必須な属性が渡されていない場合には、取り込みしない
|
21
|
-
return {} if required_attributes.any? { |attribute_name| ! presence_value?(attribute_value_map[attribute_name]) }
|
22
|
-
|
23
|
-
set_required_condition(model, attribute_value_map)
|
24
|
-
set_parent_key(model, attribute_value_map, identified_column_name)
|
25
|
-
set_activerecord_id(model, attribute_value_map, identified_column_name)
|
26
|
-
|
27
|
-
# 空でない要素が無いなら、空ハッシュで返す
|
28
|
-
presence_value?(attribute_value_map) ? attribute_value_map : {}
|
29
|
-
end
|
30
|
-
|
31
|
-
def generate_association_value(parent_model)
|
32
|
-
association_value_map = {}.with_indifferent_access
|
33
|
-
|
34
|
-
parent_model.association_map.each do |association_name, model_or_models|
|
35
|
-
association_value = if model_or_models.is_a?(::Array)
|
36
|
-
model_or_models.map { |m| generate_model_value(m) }.reject { |v| ! presence_value?(v) }
|
37
|
-
else
|
38
|
-
generate_model_value(model_or_models)
|
39
|
-
end
|
40
|
-
|
41
|
-
# 取り込み時は、オプショナルな関連では、空と思われる値は取り込まない
|
42
|
-
next if ! presence_value?(association_value) &&
|
43
|
-
parent_model.optional_attributes.include?(association_name.to_s)
|
44
|
-
|
45
|
-
association_value_map["#{association_name}_attributes".to_sym] = association_value
|
46
|
-
end
|
47
|
-
|
48
|
-
association_value_map
|
49
|
-
end
|
50
|
-
|
51
|
-
def set_required_condition(model, attribute_value_map)
|
52
|
-
# 結果ハッシュが空なら、取り込みしないように追加はしない
|
53
|
-
return unless presence_value?(attribute_value_map)
|
54
|
-
|
55
|
-
# 設定するのはルートの場合のみ
|
56
|
-
return if model.parent
|
57
|
-
|
58
|
-
attribute_value_map.merge!(@modeler.required_condition)
|
59
|
-
end
|
60
|
-
|
61
|
-
def set_parent_key(model, attribute_value_map, identified_column_name)
|
62
|
-
# 結果ハッシュが空なら、取り込みしないように追加はしない
|
63
|
-
return unless presence_value?(attribute_value_map)
|
64
|
-
|
65
|
-
# 設定するのは親がいる場合のみ
|
66
|
-
return unless model.parent
|
67
|
-
|
68
|
-
parent_id = model.parent&.activerecord_id
|
69
|
-
|
70
|
-
if parent_id
|
71
|
-
# 親のレコードが見つかっているなら、それも結果ハッシュに追加する
|
72
|
-
attribute_value_map[model.parent_foreign_key] = parent_id
|
73
|
-
else
|
74
|
-
# 見つかっていないなら、間違った値が指定されている可能性があるので、キー自体を削除
|
75
|
-
attribute_value_map.delete(model.parent_foreign_key)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def set_activerecord_id(model, attribute_value_map, identified_column_name)
|
80
|
-
# 更新の場合は、インポートデータを元にデータベースから対象のレコードを検索してIDを取得
|
81
|
-
model.activerecord_id = verified_activerecord_id(model, attribute_value_map, identified_column_name)
|
82
|
-
|
83
|
-
if model.activerecord_id
|
84
|
-
# 更新なら、ID属性を改めて設定
|
85
|
-
attribute_value_map[identified_column_name] = model.activerecord_id
|
86
|
-
else
|
87
|
-
# 見つかっていないなら、間違った値が指定されている可能性があるので、キー自体を削除
|
88
|
-
attribute_value_map.delete(identified_column_name)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def verified_activerecord_id(model, attribute_value_map, identified_column_name)
|
93
|
-
# 更新対象のレコードを特定できるかチェック
|
94
|
-
identified_value = attribute_value_map[identified_column_name]
|
95
|
-
|
96
|
-
uniqueness_condition = if identified_value
|
97
|
-
{ identified_column_name => identified_value }
|
98
|
-
else
|
99
|
-
find_unique_condition(model, attribute_value_map, identified_column_name)
|
100
|
-
end
|
101
|
-
|
102
|
-
# レコードが特定できないなら、更新処理ではないので終了
|
103
|
-
return nil unless uniqueness_condition
|
104
|
-
|
105
|
-
# 更新対象のレコードを正しく特定できているか確認するための検証条件を取得
|
106
|
-
required_condition = if model.parent
|
107
|
-
key = model.parent_foreign_key
|
108
|
-
|
109
|
-
{ key => attribute_value_map[key] }
|
110
|
-
else
|
111
|
-
@modeler.required_condition
|
112
|
-
end
|
113
|
-
|
114
|
-
# 検証条件は、必ず値がなければならない
|
115
|
-
return nil if required_condition.any? { |_k, v| ! presence_value?(v) }
|
116
|
-
|
117
|
-
# インポートされてきた、レコードを特定する条件が、誤った値でないかどうかを、
|
118
|
-
# 特定されるレコードが、更新すべき正しいレコードであるかチェックするための
|
119
|
-
# 検証条件とマージして、データベースに登録されているか確認する
|
120
|
-
verified_condition = uniqueness_condition.merge(required_condition)
|
121
|
-
|
122
|
-
find_verified_activerecord_by!(model.activerecord_constant, verified_condition).__send__(identified_column_name)
|
123
|
-
rescue ::ActiveRecord::RecordNotFound => e
|
124
|
-
# ID属性が指定されているのに、データベースに見つからない場合はエラーにする
|
125
|
-
raise e if identified_value
|
126
|
-
end
|
127
|
-
|
128
|
-
def find_unique_condition(model, attribute_value_map, identified_column_name)
|
129
|
-
unique_indexes = @modeler.config_value_for(model, :unique_indexes, [])
|
130
|
-
|
131
|
-
# ユニーク条件が指定されていないなら終了
|
132
|
-
return nil if unique_indexes.empty?
|
133
|
-
|
134
|
-
unique_condition = unique_indexes.map do |key|
|
135
|
-
[key, attribute_value_map[key]]
|
136
|
-
end.to_h
|
137
|
-
|
138
|
-
# ユニーク条件は、必ず値がなければならない
|
139
|
-
return nil if unique_condition.any? { |_k, v| ! presence_value?(v) }
|
140
|
-
|
141
|
-
unique_condition
|
142
|
-
end
|
143
|
-
|
144
|
-
def find_verified_activerecord_by!(klass, verified_uniqueness_condition)
|
145
|
-
klass.find_by!(verified_uniqueness_condition)
|
146
|
-
end
|
147
|
-
|
148
|
-
def identified_column_name_of(model)
|
149
|
-
model.activerecord_constant.primary_key
|
150
|
-
end
|
151
|
-
|
152
|
-
def presence_value?(value)
|
153
|
-
# 空でない要素であるか or 空でない要素を含んでいるかどうか
|
154
|
-
case value
|
155
|
-
when ::Hash
|
156
|
-
value.values.any? { |v| presence_value?(v) }
|
157
|
-
when ::Array
|
158
|
-
value.any? { |v| presence_value?(v) }
|
159
|
-
when ::String
|
160
|
-
! value.blank?
|
161
|
-
when ::TrueClass, ::FalseClass
|
162
|
-
true
|
163
|
-
else
|
164
|
-
value ? true : false
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Bixformer
|
3
|
-
module Generator
|
4
|
-
class Base
|
5
|
-
attr_reader :data_source
|
6
|
-
|
7
|
-
def initialize(modeler, data_source)
|
8
|
-
@modeler = modeler
|
9
|
-
@data_source = data_source
|
10
|
-
end
|
11
|
-
|
12
|
-
def compile
|
13
|
-
return @model if @model
|
14
|
-
|
15
|
-
model_name = @modeler.model_name
|
16
|
-
model_type, model_options = @modeler.parse_to_type_and_options(@modeler.entry_definition[:type])
|
17
|
-
|
18
|
-
@model = @modeler.new_module_instance(:model, model_type, model_name, model_options)
|
19
|
-
|
20
|
-
@model.data_source = @data_source
|
21
|
-
|
22
|
-
compile_model(@model)
|
23
|
-
|
24
|
-
@model
|
25
|
-
end
|
26
|
-
|
27
|
-
def generate
|
28
|
-
generate_model_value(compile)
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def compile_model(model)
|
34
|
-
model.setup_with_modeler(@modeler)
|
35
|
-
|
36
|
-
compile_associations(model)
|
37
|
-
end
|
38
|
-
|
39
|
-
def compile_associations(parent_model)
|
40
|
-
association_definitions = @modeler.config_value_for(parent_model, :entry_definition, {})[:associations] || {}
|
41
|
-
|
42
|
-
association_definitions.each do |association_name, association_definition|
|
43
|
-
association_type, association_options = @modeler.parse_to_type_and_options(association_definition[:type])
|
44
|
-
association_constant = @modeler.find_module_constant(:model, association_type)
|
45
|
-
|
46
|
-
model_or_models = association_constant.__send__(
|
47
|
-
association_generator, parent_model, association_name, association_options
|
48
|
-
)
|
49
|
-
|
50
|
-
parent_model.add_association(model_or_models)
|
51
|
-
|
52
|
-
if model_or_models.is_a?(::Array)
|
53
|
-
model_or_models.each { |model| compile_model(model) }
|
54
|
-
else
|
55
|
-
compile_model(model_or_models)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def association_generator
|
61
|
-
raise ::NotImplementedError.new "You must implement #{self.class}##{__method__}"
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|