slim_form_object 2.1.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/slim_form_object/assign.rb +78 -110
- data/lib/slim_form_object/data_object.rb +73 -0
- data/lib/slim_form_object/form_helpers/extension_actionview.rb +27 -168
- data/lib/slim_form_object/helpers.rb +7 -7
- data/lib/slim_form_object/processing.rb +53 -27
- data/lib/slim_form_object/saver.rb +46 -30
- data/lib/slim_form_object/validator.rb +9 -20
- data/lib/slim_form_object/version.rb +1 -1
- data/lib/slim_form_object.rb +1 -0
- metadata +3 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f9ec59874945c8a7ee3c6abb9fb4fd58999d9fd5ade2e950957e4cdd5ceff95
|
4
|
+
data.tar.gz: d1b79735bb67d58cce0982f6e91be53599226c0b7d9835f52791f2c6140ef33f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1889239d73747ed8812c5e10d20494cf876d434500b3576f8143035155e622cb33a6d8f39d8f12ae006e6289ae41feb2fd0006b40978ad5e2463db0f89ad705
|
7
|
+
data.tar.gz: dc5e445500ca32ef4b761d1721f9037fd258d682d0a51c6963d703615c430a08e5d2d4d46f6380a2b260ef2e3958f6e0f97f9e7cb6241009cbac5e53c6029e11
|
@@ -2,148 +2,116 @@ module SlimFormObject
|
|
2
2
|
class Assign
|
3
3
|
include ::HelperMethods
|
4
4
|
|
5
|
-
attr_reader :form_object, :params, :
|
5
|
+
attr_reader :form_object, :params, :data_for_assign
|
6
|
+
attr_accessor :data_objects_arr
|
6
7
|
|
7
8
|
def initialize(form_object)
|
8
|
-
@form_object
|
9
|
-
@
|
10
|
-
@
|
11
|
-
@
|
12
|
-
@
|
9
|
+
@form_object = form_object
|
10
|
+
@params = form_object.params
|
11
|
+
@structure = form_object.data_structure
|
12
|
+
@data_for_assign = []
|
13
|
+
@data_objects_arr = []
|
13
14
|
end
|
14
15
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
16
|
+
def apply_parameters_and_make_objects
|
17
|
+
parse_params
|
18
|
+
@data_objects_arr = make_data_objects(data_for_assign)
|
19
|
+
associate_all_objects(data_objects_arr)
|
18
20
|
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
def associate_objects
|
23
|
-
associate_all_nested_objects(data_for_save)
|
24
|
-
associate_all_main_objects(data_for_save)
|
25
|
-
|
26
|
-
data_for_save
|
21
|
+
data_objects_arr
|
27
22
|
end
|
28
23
|
|
29
24
|
private
|
30
25
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
26
|
+
# data_for_assign format
|
27
|
+
#
|
28
|
+
# [
|
29
|
+
# { :model => Product(id: integer, category_id: integer, brand_id: integer),
|
30
|
+
# :attributes => {:id=>"3871", :category_id=>"1", :brand_id=>"1"},
|
31
|
+
# :nested => [
|
32
|
+
# { :model => FiltersProduct(id: integer, product_id: integer, filter_id: integer, value_id: integer),
|
33
|
+
# :attributes => {:id=>"", :product_id=>"111", filter_id: "222", value_id: "333"},
|
34
|
+
# :nested => []
|
35
|
+
# }
|
36
|
+
# ]
|
37
|
+
# }
|
38
|
+
# ]
|
39
|
+
def make_hash_objects_and_nested_objects(key_params, value_params)
|
40
|
+
model = get_class_of(key_params)
|
41
|
+
attributes = {}
|
42
|
+
nested = []
|
43
|
+
|
44
|
+
value_params.each do |key, value|
|
45
|
+
if is_nested?(value)
|
46
|
+
if value.is_a?(Array)
|
47
|
+
value.each { |hash_params| nested << make_hash_objects_and_nested_objects(key, hash_params) }
|
48
|
+
elsif value.is_a?(ActionController::Parameters)
|
49
|
+
value.each { |index, hash_params| nested << make_hash_objects_and_nested_objects(key, hash_params) }
|
50
|
+
else
|
51
|
+
nested << make_hash_objects_and_nested_objects(key, value)
|
52
|
+
end
|
53
|
+
else
|
54
|
+
element = {key.to_sym => value}
|
55
|
+
attributes.merge!(element)
|
56
|
+
end
|
41
57
|
end
|
58
|
+
|
59
|
+
{model: model, attributes: attributes, nested: nested}
|
42
60
|
end
|
43
61
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
find_ids_nil_object(ids_arr, hash[:nested])
|
62
|
+
def parse_params
|
63
|
+
params.each do |main_model_name, attributes|
|
64
|
+
data_for_assign << make_hash_objects_and_nested_objects(main_model_name, attributes)
|
48
65
|
end
|
49
66
|
end
|
50
67
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
associate_all_nested_objects(hash[:nested], hash[:essence][:object])
|
68
|
+
def is_nested?(value)
|
69
|
+
def nested?(e)
|
70
|
+
e.class == ActionController::Parameters or e.class == Hash
|
55
71
|
end
|
56
|
-
end
|
57
72
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
objects.each do |hash|
|
63
|
-
object_2 = hash[:essence][:object]
|
64
|
-
next if !object_1.new_record? and !object_2.new_record?
|
65
|
-
to_bind_models(object_1, object_2)
|
66
|
-
end
|
73
|
+
return true if nested?(value)
|
74
|
+
|
75
|
+
if value.class == Array
|
76
|
+
value.select{ |e| nested?(e) }.size == value.size
|
67
77
|
end
|
68
78
|
end
|
69
79
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
80
|
+
def make_data_objects(data_for_assign)
|
81
|
+
data_for_assign.map do |data|
|
82
|
+
data_object = DataObject.new(name: snake(data[:model]), attributes: data[:attributes], form_object: form_object)
|
83
|
+
data_object.nested = make_data_objects(data[:nested])
|
84
|
+
data_object
|
73
85
|
end
|
74
86
|
end
|
75
87
|
|
76
|
-
def
|
77
|
-
|
78
|
-
|
88
|
+
def associate_objects(data_objects)
|
89
|
+
objects = Array.new(data_objects)
|
90
|
+
while data_object_1 = objects.delete( objects[0] )
|
91
|
+
associate_all_objects(data_object_1.nested)
|
92
|
+
objects.each do |data_object_2|
|
93
|
+
data_object_1.associate_with(data_object_2.associated_object)
|
94
|
+
end
|
79
95
|
end
|
80
96
|
end
|
81
97
|
|
82
|
-
def
|
83
|
-
|
84
|
-
value.select{ |e| e.class == ActionController::Parameters or e.class == Hash }.size == value.size
|
85
|
-
end
|
98
|
+
def associate_all_objects(objects)
|
99
|
+
associate_objects(objects)
|
86
100
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
object_hash[:nested] = []
|
91
|
-
object_attrs = {}
|
92
|
-
hash.each do |key, val|
|
93
|
-
if is_nested?(val)
|
94
|
-
nested(key, val, object_hash[:nested])
|
95
|
-
else
|
96
|
-
object_attrs.merge!({"#{key}": val})
|
101
|
+
objects.each do |data_object|
|
102
|
+
data_object.nested.each do |nested_data_object|
|
103
|
+
data_object.associate_with(nested_data_object.associated_object)
|
97
104
|
end
|
98
105
|
end
|
99
|
-
object.assign_attributes(object_attrs)
|
100
|
-
object_hash[:essence] = {model: model_name, object: object}
|
101
|
-
result_array << object_hash
|
102
106
|
end
|
103
107
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
# "address_user"=> [
|
111
|
-
# {
|
112
|
-
# "first_name"=>"dsdsd",
|
113
|
-
# "last_name"=>"kjhkjbk",
|
114
|
-
# "order"=> [
|
115
|
-
# {
|
116
|
-
# "created_at"=>"kjkjb",
|
117
|
-
# "updated_at"=>"kjbkjb"
|
118
|
-
# }
|
119
|
-
# ]
|
120
|
-
# }
|
121
|
-
# ]
|
122
|
-
# }
|
123
|
-
# }
|
108
|
+
def clean_data_objects_arr(objects)
|
109
|
+
objects.select! do |data_object|
|
110
|
+
clean_data_objects_arr(data_object.nested)
|
111
|
+
data_object.save_if_nil_or_empty?
|
112
|
+
end
|
113
|
+
end
|
124
114
|
|
125
|
-
# make_all_objects_with_attributes() EXAMPLE @data_for_save FORMAT
|
126
|
-
#
|
127
|
-
# [
|
128
|
-
# {
|
129
|
-
# essence: {model: 'user', object: WoodShop::User.new(attributes)},
|
130
|
-
# nested: [
|
131
|
-
# {
|
132
|
-
# essence: {model: 'address_user', object: WoodShop::AddressUser.new(attributes)},
|
133
|
-
# nested: [
|
134
|
-
# {
|
135
|
-
# essence: {model: 'image', object: WoodShop::Image.new(attributes)},
|
136
|
-
# nested: []
|
137
|
-
# },
|
138
|
-
# {
|
139
|
-
# essence: {model: 'image', object: WoodShop::Image.new(attributes)},
|
140
|
-
# nested: []
|
141
|
-
# }
|
142
|
-
# ]
|
143
|
-
# }
|
144
|
-
# ]
|
145
|
-
# }
|
146
|
-
# ]
|
147
115
|
end
|
148
116
|
end
|
149
117
|
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module SlimFormObject
|
2
|
+
class DataObject
|
3
|
+
include ::HelperMethods
|
4
|
+
|
5
|
+
attr_reader :name, :model, :attributes, :object, :associated_object, :form_object
|
6
|
+
attr_accessor :nested
|
7
|
+
|
8
|
+
def initialize(name: nil, attributes: {}, form_object: nil)
|
9
|
+
@name = name
|
10
|
+
@model = get_class_of(name)
|
11
|
+
@attributes = attributes
|
12
|
+
@form_object = form_object
|
13
|
+
@object = make_object
|
14
|
+
@associated_object = assign_attributes_for(make_object)
|
15
|
+
assign_attributes!
|
16
|
+
end
|
17
|
+
|
18
|
+
def associate_with(other_object, stage: nil)
|
19
|
+
case stage
|
20
|
+
when 1
|
21
|
+
obj = object
|
22
|
+
when 2
|
23
|
+
obj = object
|
24
|
+
else
|
25
|
+
obj = associated_object
|
26
|
+
end
|
27
|
+
|
28
|
+
return obj if (stage != 2 and !obj.new_record? and !other_object.new_record?)
|
29
|
+
|
30
|
+
to_bind_models(obj, other_object)
|
31
|
+
end
|
32
|
+
|
33
|
+
def save_if_nil_or_empty?
|
34
|
+
save_if_empty? and save_if_nil?
|
35
|
+
end
|
36
|
+
|
37
|
+
def save_if_empty?
|
38
|
+
!form_object.not_save_if_empty_arr.include?(model) or !empty_attributes?
|
39
|
+
end
|
40
|
+
|
41
|
+
def save_if_nil?
|
42
|
+
!form_object.not_save_if_nil_arr.include?(model) or !nil_attributes?
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def empty_attributes?
|
48
|
+
return false if nil_attributes?
|
49
|
+
attributes.each { |key, value| return false if value&.to_s&.strip != '' }
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
def nil_attributes?
|
54
|
+
attributes.empty?
|
55
|
+
end
|
56
|
+
|
57
|
+
def assign_attributes!
|
58
|
+
assign_attributes_for(object)
|
59
|
+
end
|
60
|
+
|
61
|
+
def assign_attributes_for(obj)
|
62
|
+
obj.assign_attributes(attributes)
|
63
|
+
obj
|
64
|
+
end
|
65
|
+
|
66
|
+
def make_object
|
67
|
+
attributes[:id].to_i > 0 ? model.find(attributes[:id]) : model.new
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
|
@@ -1,3 +1,9 @@
|
|
1
|
+
def const_exists?(const_name)
|
2
|
+
return true if Module.const_get(const_name)
|
3
|
+
rescue NameError
|
4
|
+
return false
|
5
|
+
end
|
6
|
+
|
1
7
|
module HelperMethods
|
2
8
|
|
3
9
|
private
|
@@ -14,51 +20,16 @@ module HelperMethods
|
|
14
20
|
/^([^-]+)-([^-]+)(\([\s\S]+\))$/
|
15
21
|
end
|
16
22
|
|
17
|
-
def sfo_collection_ads_regexp
|
18
|
-
/_ids$/
|
19
|
-
end
|
20
|
-
|
21
|
-
def sfo_form_attribute?(object)
|
22
|
-
object.class.ancestors[1] == SlimFormObject::Base if object
|
23
|
-
end
|
24
|
-
|
25
|
-
def sfo_attr?(method)
|
26
|
-
sfo_single_attr?(method)
|
27
|
-
end
|
28
|
-
|
29
|
-
def sfo_single_attr?(method)
|
30
|
-
method.to_s[sfo_single_attr_regexp] ? true : false
|
31
|
-
end
|
32
|
-
|
33
23
|
def sfo_date_attr?(tag_name)
|
34
24
|
tag_name.to_s[sfo_date_attr_regexp] ? true : false
|
35
25
|
end
|
36
26
|
|
37
|
-
def sfo_collection_ads_attr?(tag_name)
|
38
|
-
tag_name.to_s[sfo_collection_ads_regexp] ? true : false
|
39
|
-
end
|
40
|
-
|
41
|
-
def sfo_get_tag_name(object_name, method, multiple, options)
|
42
|
-
model_name, attr_name = apply_expression_text(method)
|
43
|
-
if options[:sfo_nested]
|
44
|
-
"#{object_name}[#{model_name}][][#{attr_name}]#{"[]" if multiple}"
|
45
|
-
else
|
46
|
-
"#{object_name}[#{model_name}][#{attr_name}]#{"[]" if multiple}"
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def sfo_get_method_name(method)
|
51
|
-
if sfo_single_attr?(method) and !sfo_collection_ads_attr?(method)
|
52
|
-
model_name, attr_name = apply_expression_text(method)
|
53
|
-
method = "#{model_name}_#{attr_name}"
|
54
|
-
end
|
55
|
-
|
56
|
-
method
|
57
|
-
end
|
58
|
-
|
59
27
|
def sfo_get_date_tag_name(prefix, tag_name, options)
|
60
|
-
model_name, attr_name, date_type = apply_expression_date(tag_name)
|
61
|
-
|
28
|
+
# model_name, attr_name, date_type = apply_expression_date(tag_name)
|
29
|
+
attr_name, date_type = apply_expression_text(tag_name)
|
30
|
+
model_name = options[:sfo_model]
|
31
|
+
|
32
|
+
if options[:sfo_model]
|
62
33
|
"#{prefix}[#{model_name}][][#{attr_name}#{date_type}]"
|
63
34
|
else
|
64
35
|
"#{prefix}[#{model_name}][#{attr_name}#{date_type}]"
|
@@ -83,145 +54,33 @@ module HelperMethods
|
|
83
54
|
end
|
84
55
|
end
|
85
56
|
|
86
|
-
module ActionView
|
87
|
-
module Helpers
|
88
|
-
# EXTENSIONS
|
89
57
|
|
90
|
-
|
91
|
-
include HelperMethods
|
58
|
+
if const_exists?('ActionView::Helpers')
|
92
59
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
field_name = @options[:field_name] || type
|
98
|
-
if @options[:include_position]
|
99
|
-
field_name += "(#{ActionView::Helpers::DateTimeSelector::POSITION[type]}i)"
|
100
|
-
end
|
101
|
-
options = self.instance_variable_get(:@options)
|
102
|
-
return sfo_get_date_tag_name(prefix, field_name, options) if sfo_date_attr?(field_name)
|
103
|
-
|
104
|
-
@options[:discard_type] ? prefix : "#{prefix}[#{field_name}]"
|
105
|
-
|
106
|
-
end
|
107
|
-
end
|
60
|
+
module ActionView
|
61
|
+
module Helpers
|
62
|
+
# EXTENSIONS
|
108
63
|
|
109
|
-
|
110
|
-
class Base
|
64
|
+
class DateTimeSelector
|
111
65
|
include HelperMethods
|
112
66
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
# This patch is needed since this Rails commit:
|
117
|
-
# https://github.com/rails/rails/commit/c1a118a
|
118
|
-
if defined? ::ActiveRecord
|
119
|
-
if ::ActiveRecord::VERSION::STRING < '5.2'
|
120
|
-
def value(object)
|
121
|
-
method_name = @options[:sfo_nested] ? apply_expression_text(@method_name)[1] : sfo_get_method_name(@method_name)
|
122
|
-
object.send method_name if object # use send instead of public_send
|
123
|
-
end
|
124
|
-
else # rails/rails#29791
|
125
|
-
def value
|
126
|
-
method_name = @options[:sfo_nested] ? apply_expression_text(@method_name)[1] : sfo_get_method_name(@method_name)
|
127
|
-
if @allow_method_names_outside_object
|
128
|
-
object.send method_name if object && object.respond_to?(@method_name, true)
|
129
|
-
else
|
130
|
-
object.send method_name if object
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
def tag_name(multiple = false, index = nil)
|
137
|
-
options = self.instance_variable_get(:@options)
|
138
|
-
return sfo_get_tag_name(@object_name, sanitized_method_name, multiple, options) if sfo_attr?(sanitized_method_name)
|
139
|
-
|
140
|
-
if index
|
141
|
-
"#{@object_name}[#{index}][#{sanitized_method_name}]#{"[]" if multiple}"
|
142
|
-
else
|
143
|
-
"#{@object_name}[#{sanitized_method_name}]#{"[]" if multiple}"
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
class FormBuilder
|
150
|
-
include HelperMethods
|
151
|
-
|
152
|
-
def initialize(object_name, object, template, options)
|
153
|
-
@nested_child_index = {}
|
154
|
-
@object_name, @object, @template, @options = object_name, object, template, options
|
155
|
-
@default_options = @options ? @options.slice(:index, :namespace, :skip_default_ids, :allow_method_names_outside_object) : {}
|
156
|
-
@default_options.merge!( {sfo_nested: options[:sfo_nested], sfo_main: options[:sfo_main]} )
|
157
|
-
if ::ActionView::VERSION::STRING > '5.2'
|
158
|
-
@default_html_options = @default_options.except(:skip_default_ids, :allow_method_names_outside_object)
|
159
|
-
end
|
160
|
-
convert_to_legacy_options(@options)
|
161
|
-
|
162
|
-
if @object_name.to_s.match(/\[\]$/)
|
163
|
-
if (object ||= @template.instance_variable_get("@#{Regexp.last_match.pre_match}")) && object.respond_to?(:to_param)
|
164
|
-
@auto_index = object.to_param
|
165
|
-
else
|
166
|
-
raise ArgumentError, "object[] naming but object param and @object var don't exist or don't respond to to_param: #{object.inspect}"
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
@multipart = nil
|
171
|
-
@index = options[:index] || options[:child_index]
|
172
|
-
end
|
67
|
+
def input_name_from_type(type)
|
68
|
+
prefix = @options[:prefix] || ActionView::Helpers::DateTimeSelector::DEFAULT_PREFIX
|
69
|
+
prefix += "[#{@options[:index]}]" if @options.has_key?(:index)
|
173
70
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
fields_options[:namespace] = options[:namespace]
|
178
|
-
fields_options[:parent_builder] = self
|
179
|
-
self.options[:sfo_nested] ? fields_options.merge!({sfo_main: false}) : fields_options.merge!({sfo_main: true})
|
180
|
-
|
181
|
-
case record_name
|
182
|
-
when String, Symbol
|
183
|
-
if nested_attributes_association?(record_name)
|
184
|
-
return fields_for_with_nested_attributes(record_name, record_object, fields_options, block)
|
71
|
+
field_name = @options[:field_name] || type
|
72
|
+
if @options[:include_position]
|
73
|
+
field_name += "(#{ActionView::Helpers::DateTimeSelector::POSITION[type]}i)"
|
185
74
|
end
|
186
|
-
|
187
|
-
|
188
|
-
record_name = model_name_from_record_or_class(record_object).param_key
|
189
|
-
end
|
190
|
-
|
191
|
-
object_name = @object_name
|
192
|
-
index = if options.has_key?(:index)
|
193
|
-
options[:index]
|
194
|
-
elsif defined?(@auto_index)
|
195
|
-
object_name = object_name.to_s.sub(/\[\]$/, "")
|
196
|
-
@auto_index
|
197
|
-
end
|
75
|
+
options = self.instance_variable_get(:@options)
|
76
|
+
return sfo_get_date_tag_name(prefix, field_name, options) if sfo_date_attr?(field_name)
|
198
77
|
|
199
|
-
|
200
|
-
"#{object_name}[#{index}][#{record_name}]"
|
201
|
-
elsif record_name.to_s.end_with?("[]")
|
202
|
-
record_name = record_name.to_s.sub(/(.*)\[\]$/, "[\\1][#{record_object.id}]")
|
203
|
-
"#{object_name}#{record_name}"
|
204
|
-
else
|
205
|
-
"#{object_name}[#{record_name}]"
|
206
|
-
end
|
207
|
-
fields_options[:child_index] = index
|
78
|
+
@options[:discard_type] ? prefix : "#{prefix}[#{field_name}]"
|
208
79
|
|
209
|
-
if fields_options[:sfo_nested]
|
210
|
-
record_object = object if !record_object
|
211
|
-
record_name = record_name + '[][]' unless fields_options[:sfo_main]
|
212
80
|
end
|
213
|
-
@template.fields_for(record_name, record_object, fields_options, &block)
|
214
81
|
end
|
215
|
-
end
|
216
82
|
|
217
|
-
|
218
|
-
include HelperMethods
|
219
|
-
|
220
|
-
# def fields_for(record_name, record_object = nil, options = {}, &block)
|
221
|
-
# builder = instantiate_builder(record_name, record_object, options)
|
222
|
-
# capture(builder, &block)
|
223
|
-
# end
|
83
|
+
|
224
84
|
end
|
225
|
-
|
226
85
|
end
|
227
|
-
end
|
86
|
+
end
|
@@ -3,21 +3,21 @@ module HelperMethods
|
|
3
3
|
method( snake(model.to_s).to_sym ).call
|
4
4
|
end
|
5
5
|
|
6
|
-
def get_class_of(snake_model_name,
|
6
|
+
def get_class_of(snake_model_name, base_module=nil)
|
7
7
|
pref = base_module ? (base_module.to_s + '::') : ''
|
8
|
-
|
8
|
+
Module.const_get( pref + snake_model_name.to_s.split('_').map(&:capitalize).join )
|
9
9
|
rescue
|
10
10
|
nil
|
11
11
|
end
|
12
12
|
|
13
13
|
def to_bind_models(object_1, object_2)
|
14
|
-
if
|
15
|
-
assignment_to_each_other(object_2, object_1)
|
16
|
-
else
|
14
|
+
if object_1.new_record?
|
17
15
|
assignment_to_each_other(object_1, object_2)
|
16
|
+
object_1
|
17
|
+
else
|
18
|
+
assignment_to_each_other(object_2, object_1)
|
19
|
+
object_2
|
18
20
|
end
|
19
|
-
|
20
|
-
object_1
|
21
21
|
end
|
22
22
|
|
23
23
|
def assignment_to_each_other(object_1, object_2)
|
@@ -4,7 +4,7 @@ module SlimFormObject
|
|
4
4
|
include ::HelperMethods
|
5
5
|
extend ::HelperMethods
|
6
6
|
|
7
|
-
attr_accessor :params, :
|
7
|
+
attr_accessor :params, :data_objects_arr
|
8
8
|
|
9
9
|
class << self
|
10
10
|
attr_accessor :base_module
|
@@ -13,20 +13,50 @@ module SlimFormObject
|
|
13
13
|
define_method(:model_name) { ActiveModel::Name.new(self, nil, name) }
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
# data_structure
|
17
|
+
def input_data_structure(**structure)
|
18
|
+
instance_eval do
|
19
|
+
define_method(:data_structure) { structure }
|
20
|
+
end
|
21
|
+
|
22
|
+
define_array_of_models(:array_of_all_models, get_main_models_from_structure(structure))
|
18
23
|
end
|
19
|
-
alias_method :init_models, :init_single_models
|
20
24
|
|
25
|
+
# array_models_which_not_save_if_empty
|
21
26
|
def not_save_empty_object_for(*args)
|
22
27
|
args.each { |model| raise "#{model.to_s} - type is not a Class" if model.class != Class }
|
23
|
-
|
24
|
-
define_method(:
|
28
|
+
instance_eval do
|
29
|
+
define_method(:not_save_if_empty_arr) { args }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def not_save_nil_object_for(*args)
|
34
|
+
args.each { |model| raise "#{model.to_s} - type is not a Class" if model.class != Class }
|
35
|
+
instance_eval do
|
36
|
+
define_method(:not_save_if_nil_arr) { args }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# CALLBACKS
|
41
|
+
%w(allow_to_save_object allow_to_associate_objects before_save_form after_save_form before_validation_form after_validation_form).each do |method_name|
|
42
|
+
define_method("#{method_name}".to_sym) do |&block|
|
43
|
+
instance_eval do
|
44
|
+
define_method("#{method_name}_block".to_sym) { block }
|
45
|
+
end if block
|
46
|
+
end
|
47
|
+
end
|
48
|
+
# END CALLBACKS
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def get_main_models_from_structure(structure)
|
53
|
+
structure.keys.map do |main_model_name|
|
54
|
+
get_class_of(main_model_name)
|
25
55
|
end
|
26
56
|
end
|
27
57
|
|
28
58
|
def define_array_of_models(name, args)
|
29
|
-
|
59
|
+
instance_eval do
|
30
60
|
define_method(name) { args }
|
31
61
|
end
|
32
62
|
make_methods_for_objects_of(args)
|
@@ -45,22 +75,12 @@ module SlimFormObject
|
|
45
75
|
end
|
46
76
|
end
|
47
77
|
end
|
48
|
-
|
49
|
-
# CALLBACKS
|
50
|
-
%w(allow_to_save_object allow_to_associate_objects before_save_form after_save_form before_validation_form after_validation_form).each do |method_name|
|
51
|
-
define_method("#{method_name}".to_sym) do |&block|
|
52
|
-
self.instance_eval do
|
53
|
-
define_method("#{method_name}_block".to_sym) { block }
|
54
|
-
end if block
|
55
|
-
end
|
56
|
-
end
|
57
|
-
# END CALLBACKS
|
58
78
|
end
|
59
79
|
|
60
80
|
def method_missing(name, *args, &block)
|
61
81
|
if name[/_ids$/]
|
62
82
|
model_name, attr_name = get_model_and_method_names(name)
|
63
|
-
return
|
83
|
+
return send(model_name.to_sym).send(attr_name.to_sym)
|
64
84
|
end
|
65
85
|
super(name, args, block)
|
66
86
|
end
|
@@ -91,6 +111,11 @@ module SlimFormObject
|
|
91
111
|
Validator.new(self).validate_form_object
|
92
112
|
end
|
93
113
|
|
114
|
+
def permit_params(params)
|
115
|
+
return {} if params.empty?
|
116
|
+
params.require(snake(model_name.name).gsub(/_+/, '_')).permit(data_structure)
|
117
|
+
end
|
118
|
+
|
94
119
|
private
|
95
120
|
|
96
121
|
def require_extensions
|
@@ -98,9 +123,8 @@ module SlimFormObject
|
|
98
123
|
end
|
99
124
|
|
100
125
|
def apply
|
101
|
-
assign
|
102
|
-
self.
|
103
|
-
self.data_for_save = assign.associate_objects
|
126
|
+
assign = Assign.new(self)
|
127
|
+
self.data_objects_arr = assign.apply_parameters_and_make_objects
|
104
128
|
end
|
105
129
|
|
106
130
|
def get_or_add_default_objects
|
@@ -114,14 +138,16 @@ module SlimFormObject
|
|
114
138
|
end
|
115
139
|
|
116
140
|
def default_settings
|
117
|
-
define_singleton_method(:
|
141
|
+
define_singleton_method(:not_save_if_empty_arr) { [] } unless respond_to?(:not_save_if_empty_arr)
|
142
|
+
define_singleton_method(:not_save_if_nil_arr) { [] } unless respond_to?(:not_save_if_nil_arr)
|
118
143
|
define_singleton_method(:allow_to_associate_objects_block) { Proc.new { true } } unless respond_to?(:allow_to_associate_objects_block)
|
119
|
-
define_singleton_method(:allow_to_save_object_block)
|
120
|
-
define_singleton_method(:before_save_form_block)
|
121
|
-
define_singleton_method(:after_save_form_block)
|
122
|
-
define_singleton_method(:before_validation_form_block)
|
123
|
-
define_singleton_method(:after_validation_form_block)
|
144
|
+
define_singleton_method(:allow_to_save_object_block) { Proc.new { true } } unless respond_to?(:allow_to_save_object_block)
|
145
|
+
define_singleton_method(:before_save_form_block) { Proc.new {} } unless respond_to?(:before_save_form_block)
|
146
|
+
define_singleton_method(:after_save_form_block) { Proc.new {} } unless respond_to?(:after_save_form_block)
|
147
|
+
define_singleton_method(:before_validation_form_block) { Proc.new {} } unless respond_to?(:before_validation_form_block)
|
148
|
+
define_singleton_method(:after_validation_form_block) { Proc.new {} } unless respond_to?(:after_validation_form_block)
|
124
149
|
end
|
150
|
+
|
125
151
|
end
|
126
152
|
end
|
127
153
|
|
@@ -2,19 +2,18 @@ module SlimFormObject
|
|
2
2
|
class Saver
|
3
3
|
include ::HelperMethods
|
4
4
|
|
5
|
-
attr_reader :form_object, :params, :validator, :
|
5
|
+
attr_reader :form_object, :params, :validator, :data_objects_arr
|
6
6
|
|
7
7
|
def initialize(form_object)
|
8
|
-
@form_object
|
9
|
-
@
|
10
|
-
@
|
11
|
-
@
|
12
|
-
@validator = Validator.new(form_object)
|
8
|
+
@form_object = form_object
|
9
|
+
@params = form_object.params
|
10
|
+
@data_objects_arr = form_object.data_objects_arr
|
11
|
+
@validator = Validator.new(form_object)
|
13
12
|
end
|
14
13
|
|
15
14
|
def save
|
16
15
|
if form_object.valid?
|
17
|
-
|
16
|
+
_save
|
18
17
|
return true
|
19
18
|
end
|
20
19
|
false
|
@@ -24,52 +23,69 @@ module SlimFormObject
|
|
24
23
|
|
25
24
|
def save!
|
26
25
|
if form_object.valid?
|
27
|
-
|
26
|
+
_save
|
28
27
|
end
|
29
28
|
true
|
30
29
|
end
|
31
30
|
|
32
31
|
private
|
33
32
|
|
34
|
-
def
|
33
|
+
def _save
|
35
34
|
ActiveRecord::Base.transaction do
|
36
35
|
form_object.before_save_form_block.call(form_object)
|
37
|
-
|
38
|
-
|
36
|
+
stage_1(data_objects_arr)
|
37
|
+
stage_2(data_objects_arr)
|
38
|
+
stage_3(data_objects_arr)
|
39
39
|
form_object.after_save_form_block.call(form_object)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
43
|
+
# association per parent with all nested objects
|
44
|
+
def stage_1(objects)
|
45
|
+
objects.each do |data_object|
|
46
|
+
data_object.nested.each do |nested_data_object|
|
47
|
+
data_object.associate_with(nested_data_object.object, stage: 1)
|
48
|
+
end
|
49
|
+
stage_1(data_object.nested)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# save all objects
|
54
|
+
def stage_2(objects)
|
55
|
+
objects.each do |data_object|
|
56
|
+
stage_2(data_object.nested)
|
57
|
+
save_object(data_object.object)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# associate and save between a nested objects
|
62
|
+
def stage_3(objects)
|
63
|
+
associate_and_save_objects(objects)
|
64
|
+
|
65
|
+
objects.each do |data_object|
|
66
|
+
stage_3(data_object.nested)
|
49
67
|
end
|
50
68
|
end
|
51
69
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
|
70
|
+
def associate_and_save_objects(data_objects)
|
71
|
+
objects = Array.new(data_objects)
|
72
|
+
while data_object_1 = objects.delete( objects[0] )
|
73
|
+
objects.each do |data_object_2|
|
74
|
+
obj = data_object_1.associate_with(data_object_2.object, stage: 2)
|
75
|
+
save_object(obj)
|
56
76
|
end
|
57
77
|
end
|
58
78
|
end
|
59
79
|
|
60
|
-
def
|
61
|
-
|
62
|
-
save_object(object_for_save)
|
80
|
+
def allow_to_save(object_of_model)
|
81
|
+
object_of_model.valid? and object_of_model.changed? and validator.allow_to_save_object?(object_of_model)
|
63
82
|
end
|
64
83
|
|
65
84
|
def save_object(object_of_model)
|
66
|
-
|
85
|
+
if allow_to_save(object_of_model)
|
86
|
+
object_of_model.save!
|
87
|
+
end
|
67
88
|
end
|
68
89
|
|
69
|
-
def save_last_model_if_not_associations(object_1)
|
70
|
-
association_trigger = false
|
71
|
-
data_for_save.each { |hash| association_trigger = true if get_reflection(object_1.class, hash[:essence][:object].class) }
|
72
|
-
save_object(object_1) unless association_trigger
|
73
|
-
end
|
74
90
|
end
|
75
91
|
end
|
@@ -2,26 +2,22 @@ module SlimFormObject
|
|
2
2
|
class Validator
|
3
3
|
include ::HelperMethods
|
4
4
|
|
5
|
-
attr_reader :form_object, :params, :
|
5
|
+
attr_reader :form_object, :params, :not_save_if_empty_arr, :not_save_if_nil_arr, :data_objects_arr
|
6
6
|
|
7
7
|
def initialize(form_object)
|
8
8
|
@form_object = form_object
|
9
|
-
@base_module = form_object.class.base_module
|
10
9
|
@params = form_object.params
|
11
|
-
@
|
12
|
-
@
|
10
|
+
@data_objects_arr = form_object.data_objects_arr
|
11
|
+
@not_save_if_empty_arr = form_object.not_save_if_empty_arr
|
12
|
+
@not_save_if_nil_arr = form_object.not_save_if_nil_arr
|
13
13
|
end
|
14
14
|
|
15
15
|
def validate_form_object
|
16
16
|
form_object.before_validation_form_block.call(form_object)
|
17
|
-
validation_objects(
|
17
|
+
validation_objects(data_objects_arr)
|
18
18
|
form_object.after_validation_form_block.call(form_object)
|
19
19
|
end
|
20
20
|
|
21
|
-
def save_if_object_is_empty?(object)
|
22
|
-
!(all_attributes_is_nil?(object) and array_models_which_not_save_if_empty.include?(object.class))
|
23
|
-
end
|
24
|
-
|
25
21
|
def allow_to_save_object?(object)
|
26
22
|
form_object.allow_to_save_object_block.call(object)
|
27
23
|
end
|
@@ -32,18 +28,11 @@ module SlimFormObject
|
|
32
28
|
|
33
29
|
private
|
34
30
|
|
35
|
-
def validation_objects(
|
36
|
-
|
37
|
-
set_errors( snake(
|
38
|
-
validation_objects(
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def all_attributes_is_nil?(object)
|
43
|
-
object.class.column_names.each do |attr_name|
|
44
|
-
return false if object.send(attr_name.to_sym) != nil
|
31
|
+
def validation_objects(objects)
|
32
|
+
objects.each do |data_object|
|
33
|
+
set_errors( snake(data_object.model), data_object.associated_object.errors ) unless data_object.associated_object.valid?
|
34
|
+
validation_objects(data_object.nested)
|
45
35
|
end
|
46
|
-
true
|
47
36
|
end
|
48
37
|
|
49
38
|
def set_errors(object_name, object_errors)
|
data/lib/slim_form_object.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: slim_form_object
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- woodcrust
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-01-
|
11
|
+
date: 2019-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -24,20 +24,6 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 4.0.0
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: actionview
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 4.0.0
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: 4.0.0
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: bundler
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -162,6 +148,7 @@ files:
|
|
162
148
|
- bin/slim_form_object
|
163
149
|
- lib/slim_form_object.rb
|
164
150
|
- lib/slim_form_object/assign.rb
|
151
|
+
- lib/slim_form_object/data_object.rb
|
165
152
|
- lib/slim_form_object/form_helpers/extension_actionview.rb
|
166
153
|
- lib/slim_form_object/helpers.rb
|
167
154
|
- lib/slim_form_object/processing.rb
|