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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 25c66a76b49d989ba6a6c9062d350e75a2ead10bbf4e956c5ee4ae7eff1ce5e8
4
- data.tar.gz: 3716afd6b47bc40d0ceb0f132666e5a43ea927f80d07d2c93f0c1e958aafb1e5
3
+ metadata.gz: 5f9ec59874945c8a7ee3c6abb9fb4fd58999d9fd5ade2e950957e4cdd5ceff95
4
+ data.tar.gz: d1b79735bb67d58cce0982f6e91be53599226c0b7d9835f52791f2c6140ef33f
5
5
  SHA512:
6
- metadata.gz: d71453875860516f9fe15c1be2fd55fec2c1dd7621f25be306ab2593b60475732a6d796f69bd19e0318dcb535163fd54e68415e95d08722741bd0cc259f2c607
7
- data.tar.gz: d9874d69bef44a949ba1c11fe21956c8c1107384dce2175e5a270d4488111bed08a7c6c1fa23e21231b93623083ca95e40227c8fa03cfa963a8943723ad08e98
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, :data_for_save, :base_module, :validator
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 = form_object
9
- @base_module = form_object.class.base_module
10
- @params = form_object.params
11
- @validator = Validator.new(form_object)
12
- @data_for_save = []
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 apply_parameters
16
- make_all_objects_with_attributes
17
- clear_nil_objects
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
- data_for_save
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
- def clear_nil_objects
32
- arr_ids_nil_object = []
33
- find_ids_nil_object(arr_ids_nil_object, data_for_save)
34
- delete_hash_nil_objects(arr_ids_nil_object, data_for_save)
35
- end
36
-
37
- def delete_hash_nil_objects(ids_arr, nested_array)
38
- nested_array.select!{|e| !ids_arr.include?(e.object_id)}
39
- nested_array.each do |hash|
40
- delete_hash_nil_objects(ids_arr, hash[:nested])
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 find_ids_nil_object(ids_arr, nested_array)
45
- nested_array.each do |hash|
46
- ids_arr << hash.object_id if !validator.save_if_object_is_empty?(hash[:essence][:object])
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 associate_all_nested_objects(nested_array, object=nil)
52
- nested_array.each do |hash|
53
- to_bind_models(object, hash[:essence][:object]) if object and validator.allow_to_associate_objects?(object, hash[:essence][:object])
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
- def associate_all_main_objects(data_for_save)
59
- objects = Array.new(data_for_save)
60
- while object = objects.delete( objects[0] )
61
- object_1 = object[:essence][:object]
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 make_all_objects_with_attributes
71
- params.each do |main_model_name, hash|
72
- assign_objects_attributes(main_model_name, hash, data_for_save, :main)
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 nested(model_name, nested_array, result_array)
77
- nested_array.each do |nested_object|
78
- assign_objects_attributes(model_name, nested_object, result_array, :nested)
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 is_nested?(value)
83
- return false unless value.class == Array
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
- def assign_objects_attributes(model_name, hash, result_array, type)
88
- object_hash = {}
89
- object = type == :main ? form_object.send(model_name.to_sym) : get_class_of(model_name, base_module).new
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
- # PARAMS FORMAT
105
- # {
106
- # "user"=> {
107
- # "email"=>"kjbkj@bk.ddd",
108
- # "password"=>"dsmndvvs",
109
- # "password_confirmation"=>"jvdjshvd",
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
- if options[:sfo_nested]
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
- class DateTimeSelector
91
- include HelperMethods
58
+ if const_exists?('ActionView::Helpers')
92
59
 
93
- def input_name_from_type(type)
94
- prefix = @options[:prefix] || ActionView::Helpers::DateTimeSelector::DEFAULT_PREFIX
95
- prefix += "[#{@options[:index]}]" if @options.has_key?(:index)
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
- module Tags
110
- class Base
64
+ class DateTimeSelector
111
65
  include HelperMethods
112
66
 
113
- private
114
-
115
- # TODO: Find a better way to solve this issue!
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
- def fields_for(record_name, record_object = nil, fields_options = {}, &block)
175
- fields_options, record_object = record_object, nil if record_object.is_a?(Hash) && record_object.extractable_options?
176
- fields_options[:builder] ||= options[:builder]
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
- else
187
- record_object = record_name.is_a?(Array) ? record_name.last : record_name
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
- record_name = if index
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
- module FormHelper
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, base_modulenil)
6
+ def get_class_of(snake_model_name, base_module=nil)
7
7
  pref = base_module ? (base_module.to_s + '::') : ''
8
- Object.const_get( pref + snake_model_name.to_s.split('_').map(&:capitalize).join )
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 object_2.new_record?
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, :data_for_save
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
- def init_single_models(*args)
17
- define_array_of_models(:array_of_all_models, args)
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
- self.instance_eval do
24
- define_method(:array_models_which_not_save_if_empty) { args }
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
- self.instance_eval do
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 self.send(model_name.to_sym).send(attr_name.to_sym)
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 = Assign.new(self)
102
- self.data_for_save = assign.apply_parameters
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(:array_models_which_not_save_if_empty) { [] } unless respond_to?(:array_models_which_not_save_if_empty)
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) { Proc.new { true } } unless respond_to?(:allow_to_save_object_block)
120
- define_singleton_method(:before_save_form_block) { Proc.new {} } unless respond_to?(:before_save_form_block)
121
- define_singleton_method(:after_save_form_block) { Proc.new {} } unless respond_to?(:after_save_form_block)
122
- define_singleton_method(:before_validation_form_block) { Proc.new {} } unless respond_to?(:before_validation_form_block)
123
- define_singleton_method(:after_validation_form_block) { Proc.new {} } unless respond_to?(: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, :base_module, :data_for_save
5
+ attr_reader :form_object, :params, :validator, :data_objects_arr
6
6
 
7
7
  def initialize(form_object)
8
- @form_object = form_object
9
- @base_module = form_object.class.base_module
10
- @params = form_object.params
11
- @data_for_save = form_object.data_for_save
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
- save_all
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
- save_all
26
+ _save
28
27
  end
29
28
  true
30
29
  end
31
30
 
32
31
  private
33
32
 
34
- def save_all
33
+ def _save
35
34
  ActiveRecord::Base.transaction do
36
35
  form_object.before_save_form_block.call(form_object)
37
- save_main_objects
38
- save_nested_objects
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
- def save_main_objects
44
- objects = Array.new(data_for_save)
45
- while object = objects.delete( objects[0] )
46
- object_1 = object[:essence][:object]
47
- objects.each{ |hash| save_objects(object_1, hash[:essence][:object]) }
48
- save_last_model_if_not_associations(object_1)
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 save_nested_objects
53
- data_for_save.each do |main_object|
54
- main_object[:nested].each do |object|
55
- save_object(object[:essence][:object])
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 save_objects(object_1, object_2)
61
- object_for_save = to_bind_models(object_1, object_2)
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
- object_of_model.save! if validator.allow_to_save_object?(object_of_model)
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, :array_models_which_not_save_if_empty, :base_module, :data_for_save
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
- @data_for_save = form_object.data_for_save
12
- @array_models_which_not_save_if_empty = form_object.array_models_which_not_save_if_empty
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(data_for_save)
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(nested_array)
36
- nested_array.each do |hash|
37
- set_errors( snake(hash[:essence][:object].class), hash[:essence][:object].errors ) unless hash[:essence][:object].valid?
38
- validation_objects(hash[:nested])
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)
@@ -1,3 +1,3 @@
1
1
  module SlimFormObject
2
- VERSION = "2.1.2"
2
+ VERSION = "3.0.0"
3
3
  end
@@ -4,6 +4,7 @@ require "slim_form_object/validator"
4
4
  require "slim_form_object/processing"
5
5
  require "slim_form_object/assign"
6
6
  require "slim_form_object/saver"
7
+ require "slim_form_object/data_object"
7
8
 
8
9
  module SlimFormObject
9
10
  end
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: 2.1.2
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-08 00:00:00.000000000 Z
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