slim_form_object 0.5.23 → 1.0.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c790c09a7f14bba8e6919633cf1e42b329b28e09
4
- data.tar.gz: 9a56d7be9abf5a89d75a0e1528e3f5379d1e7f93
3
+ metadata.gz: eead85525874b4ad6ac4fea0f9bdace9f2cc5f90
4
+ data.tar.gz: e382a9c9eabfcdf5744647916a6f9d68dc1e06bd
5
5
  SHA512:
6
- metadata.gz: 41588b2e3ee7615fa00c64d8bf6358f28c7ba77775247a02af54e0ce87fee09f943bbce12832677b18a3d80b87a1f2c59bb95d0c18726df11e8b3dfac82824ca
7
- data.tar.gz: 0b2adebf258a068570ab894e0e27babe9888ce33389db897b4704a98801dee89c3fac6a5dfdcff80fd7e3908fcac6b253dd4fc839f43d72e25dd89b18b68502d
6
+ metadata.gz: 65fc388efca69511b521c7c4589fdf0828f3f8ef5a6e4f4693b8bb78fc53370752e1563f1ef2692066c38b34b15d5cce7bc184d28fb7b1c4fbd9a5c356908346
7
+ data.tar.gz: c97e749fe60e6cf20a813aa9ff77ff24f68352122d863592c71d4a1cc96b06eb6eeb4146aa92353e9a7b8bb7801a7d66d50cbb4e9a8498ef7c2a8a96d9ec0203
@@ -1,7 +1,10 @@
1
1
  require "slim_form_object/version"
2
+ require "slim_form_object/form_helpers/extension_actionview"
2
3
  require "slim_form_object/helpers"
4
+ require "slim_form_object/validator"
3
5
  require "slim_form_object/processing"
6
+ require "slim_form_object/assign"
7
+ require "slim_form_object/saver"
4
8
 
5
9
  module SlimFormObject
6
-
7
10
  end
@@ -0,0 +1,89 @@
1
+ module SlimFormObject
2
+ class Assign
3
+ include ::HelperMethods
4
+
5
+ attr_reader :form_object, :params, :array_all_objects_for_save, :not_save_this_model, :result_hash_updated_objects
6
+
7
+ def initialize(form_object)
8
+ @form_object = form_object
9
+ @params = form_object.params
10
+ @array_all_objects_for_save = form_object.array_all_objects_for_save
11
+ @not_save_this_model = form_object.not_save_this_model
12
+ @result_hash_updated_objects = {objects: [], nested_objects: {}}
13
+ end
14
+
15
+ def apply_parameters
16
+ filter_not_save_objects
17
+ update_objects_attributes
18
+ make_nested_objects
19
+
20
+ result_hash_updated_objects
21
+ end
22
+
23
+ def filter_not_save_objects
24
+ array_all_objects_for_save.reject do |object|
25
+ not_save_this_model.include?(object.class)
26
+ end
27
+ end
28
+
29
+ # STANDART OBJECTS
30
+
31
+ def update_objects_attributes
32
+ array_all_objects_for_save.each do |object|
33
+ object.assign_attributes(hash_params_of_object(object))
34
+ end
35
+
36
+ result_hash_updated_objects[:objects] = array_all_objects_for_save
37
+ end
38
+
39
+
40
+ def hash_params_of_object(object)
41
+ if force_permit(params[snake(object.class.to_s)])
42
+ params[snake(object.class.to_s)]
43
+ else
44
+ {}
45
+ end
46
+ end
47
+
48
+ def force_permit(params)
49
+ return nil if params.class != ActionController::Parameters
50
+ params.instance_variable_set(:@permitted, true)
51
+ params
52
+ end
53
+
54
+ # NESTED OBJECTS
55
+ # example params
56
+ #
57
+ # "sfo-multiple"=>{
58
+ # snake_model_name "category_vacancy"=>{
59
+ # snake_object_name "specialty_vacancy"=>[
60
+ # parameters {"name"=>"4", "category_vacancy_id"=>"12"}, {"name"=>"6", "category_vacancy_id"=>"14"} ]}}
61
+ #
62
+ def make_nested_objects
63
+ params.keys.each do |key|
64
+ if key == 'sfo-multiple'
65
+ params[key].keys.each do |snake_model_name|
66
+ result_hash_updated_objects[:nested_objects][snake_model_name.to_sym] ||= []
67
+
68
+ params[key][snake_model_name].keys.each do |snake_object_name|
69
+ params[key][snake_model_name][snake_object_name].each do |parameters|
70
+ object = get_class_of_snake_model_name(snake_object_name).new
71
+ object.assign_attributes(force_permit(parameters))
72
+ result_hash_updated_objects[:nested_objects][snake_model_name.to_sym] << object
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ end
81
+ end
82
+
83
+
84
+
85
+
86
+
87
+
88
+
89
+
@@ -0,0 +1,161 @@
1
+ module ActionView
2
+ module Helpers
3
+ module HelperMethods
4
+ def sfo_fields_for(name, object = nil, form_options: {}, options: {}, &block)
5
+ object = get_class_of_snake_model_name(name.to_s).new unless object
6
+
7
+ if options[:sfo_form]
8
+ form_object_class = get_class_of_snake_model_name(name.to_s)
9
+ name = "slim_form_object_#{name}"
10
+ object = form_object_class.new(form_options)
11
+ end
12
+
13
+ fields_for(name, object, options, &block)
14
+ end
15
+
16
+ private
17
+
18
+ def get_class_of_snake_model_name(snake_model_name)
19
+ Object.const_get( snake_model_name.split('_').map(&:capitalize).join )
20
+ end
21
+
22
+ def sfo_single_attr_regexp
23
+ /^([^-]+)-([^-]+)$/
24
+ end
25
+
26
+ def sfo_multiple_attr_regexp
27
+ /sfo-multiple/
28
+ end
29
+
30
+ def sfo_date_attr_regexp
31
+ /^([^-]+)-([^-]+)(\([\s\S]+\))$/
32
+ end
33
+
34
+ def sfo_form_attribute?(object)
35
+ object.class.ancestors[1] == SlimFormObject::Base if object
36
+ end
37
+
38
+ def sfo_attr?(method)
39
+ sfo_single_attr?(method) or sfo_multiple_attr?(method)
40
+ end
41
+
42
+ def sfo_single_attr?(method)
43
+ method.to_s[sfo_single_attr_regexp] ? true : false
44
+ end
45
+
46
+ def sfo_multiple_attr?(string)
47
+ string.to_s[sfo_multiple_attr_regexp] ? true : false
48
+ end
49
+
50
+ def sfo_date_attr?(tag_name)
51
+ tag_name.to_s[sfo_date_attr_regexp] ? true : false
52
+ end
53
+
54
+ def sfo_get_tag_name(object_name, method, multiple)
55
+ if sfo_multiple_attr?(object_name)
56
+ method.to_s[sfo_single_attr_regexp]
57
+ model_name = $1
58
+ attr_name = $2
59
+ tag_name = "#{object_name}[#{model_name}][][#{attr_name}]#{"[]" if multiple}"
60
+ elsif sfo_single_attr?(method)
61
+ method.to_s[sfo_single_attr_regexp]
62
+ model_name = $1
63
+ attr_name = $2
64
+ tag_name = "#{object_name}[#{model_name}][#{attr_name}]#{"[]" if multiple}"
65
+ end
66
+
67
+ tag_name
68
+ end
69
+
70
+ def sfo_get_method_name(method)
71
+ if sfo_single_attr?(method)
72
+ method.to_s[sfo_single_attr_regexp]
73
+ model_name = $1
74
+ attr_name = $2
75
+ method = "#{model_name}_#{attr_name}"
76
+ end
77
+
78
+ method
79
+ end
80
+
81
+ def sfo_get_date_tag_name(prefix, tag_name)
82
+ if sfo_multiple_attr?(prefix)
83
+ tag_name[sfo_date_attr_regexp]
84
+ model_name = $1
85
+ attr_name = $2
86
+ date_type = $3
87
+ tag_name = "#{prefix}[#{model_name}][][#{attr_name}#{date_type}]"
88
+ elsif tag_name[sfo_date_attr_regexp]
89
+ model_name = $1
90
+ attr_name = $2
91
+ date_type = $3
92
+ tag_name = "#{prefix}[#{model_name}][#{attr_name}#{date_type}]"
93
+ end
94
+
95
+ tag_name
96
+ end
97
+ end
98
+
99
+ class DateTimeSelector
100
+ include HelperMethods
101
+
102
+ def input_name_from_type(type)
103
+ prefix = @options[:prefix] || ActionView::Helpers::DateTimeSelector::DEFAULT_PREFIX
104
+ prefix += "[#{@options[:index]}]" if @options.has_key?(:index)
105
+
106
+ field_name = @options[:field_name] || type
107
+ if @options[:include_position]
108
+ field_name += "(#{ActionView::Helpers::DateTimeSelector::POSITION[type]}i)"
109
+ end
110
+
111
+ return sfo_get_date_tag_name(prefix, field_name) if sfo_date_attr?(field_name)
112
+
113
+ @options[:discard_type] ? prefix : "#{prefix}[#{field_name}]"
114
+
115
+ end
116
+ end
117
+
118
+ module Tags
119
+ class Base
120
+ include HelperMethods
121
+
122
+ private
123
+
124
+ def value(object)
125
+ method_name = sfo_get_method_name(@method_name)
126
+ object.public_send method_name if object
127
+ end
128
+
129
+ def tag_name(multiple = false, index = nil)
130
+ return sfo_get_tag_name(@object_name, sanitized_method_name, multiple) if sfo_attr?(sanitized_method_name)
131
+
132
+ if index
133
+ "#{@object_name}[#{index}][#{sanitized_method_name}]#{"[]" if multiple}"
134
+ else
135
+ "#{@object_name}[#{sanitized_method_name}]#{"[]" if multiple}"
136
+ end
137
+ end
138
+ end
139
+ end
140
+
141
+ class FormBuilder
142
+ include HelperMethods
143
+ end
144
+
145
+ module FormHelper
146
+ include HelperMethods
147
+
148
+ def fields_for(record_name, record_object = nil, options = {}, &block)
149
+ if options[:sfo_multiple]
150
+ record_name[/^([\s\S]+)(\[[\s\S]+\])/]
151
+ part_1 = $1
152
+ part_2 = $2
153
+ record_name = "#{part_1}[sfo-multiple]#{part_2}"
154
+ end
155
+ builder = instantiate_builder(record_name, record_object, options)
156
+ capture(builder, &block)
157
+ end
158
+ end
159
+
160
+ end
161
+ end
@@ -1,5 +1,6 @@
1
1
  module HelperMethods
2
2
  def snake(string)
3
+ string = string.to_s
3
4
  string.gsub!(/((\w)([A-Z]))/,'\2_\3')
4
5
  class_name_if_module(string.downcase)
5
6
  end
@@ -8,4 +9,12 @@ module HelperMethods
8
9
  return $1 if string =~ /^.+::(.+)$/
9
10
  string
10
11
  end
12
+
13
+ def get_self_object(model)
14
+ method( snake(model.to_s).to_sym ).call
15
+ end
16
+
17
+ def get_class_of_snake_model_name(snake_model_name)
18
+ Object.const_get( snake_model_name.to_s.split('_').map(&:capitalize).join )
19
+ end
11
20
  end
@@ -1,163 +1,117 @@
1
+ require 'byebug'
2
+
1
3
  module SlimFormObject
4
+ class Base
5
+ include ActiveModel::Model
6
+ include ::HelperMethods
7
+ extend ::HelperMethods
2
8
 
3
- def self.included(base)
4
- base.include ActiveModel::Model
5
- base.include HelperMethods
6
- base.extend ClassMethods
7
- base.extend HelperMethods
8
- end
9
+ attr_accessor :params, :array_objects_for_save, :hash_objects_for_save
9
10
 
10
- module ClassMethods
11
+ class << self
11
12
 
12
- def init_models(*args)
13
- self.instance_eval do
14
- define_method(:array_of_models) { args }
13
+ def set_model_name(name)
14
+ define_method(:model_name) { ActiveModel::Name.new(self, nil, name) }
15
15
  end
16
- add_attributes(args)
17
- end
18
16
 
19
- def add_attributes(models)
20
- #attr_accessor for models and env params
21
- attr_accessor :params
22
- models.each{ |model| attr_accessor snake(model.to_s).to_sym }
23
-
24
- #delegate attributes of models
25
- models.each do |model|
26
- model.column_names.each do |attr|
27
- delegate attr.to_sym, "#{attr}=".to_sym,
28
- to: snake(model.to_s).to_sym,
29
- prefix: snake(model.to_s).to_sym
17
+ def init_single_models(*args)
18
+ define_array_of_models(:array_of_all_models, args)
19
+ end
20
+ alias_method :init_models, :init_single_models
21
+
22
+ def not_save_this_model(*args)
23
+ self.instance_eval do
24
+ define_method(:not_validate_this_models) { args }
30
25
  end
31
26
  end
32
- end
33
27
 
34
- def set_model_name(name)
35
- define_method(:model_name) { ActiveModel::Name.new(self, nil, name) }
36
- end
37
- end
28
+ def force_save_if_all_attr_is_nil(*args)
29
+ self.instance_eval do
30
+ define_method(:force_save_if_all_attr_is_nil) { args }
31
+ end
32
+ end
38
33
 
39
- def submit
40
- @array_of_models ||= array_of_models.reject do |model|
41
- array_of_models_without_validates.include?(model) if self.respond_to?(:array_of_models_without_validates)
42
- end
43
- update_attributes
44
- update_attributes_for_collection
45
- self
46
- end
34
+ def define_array_of_models(name, args)
35
+ self.instance_eval do
36
+ define_method(name) { args }
37
+ end
38
+ make_methods_for_objects_of(args)
39
+ end
47
40
 
48
- alias_method :apply_parameters, :submit
41
+ def make_methods_for_objects_of(models)
42
+ models.each{ |model| attr_accessor snake(model.to_s).to_sym }
43
+
44
+ delegate_models_attributes(models)
45
+ end
49
46
 
50
- def save
51
- if valid?
52
- models = Array.new(@array_of_models)
53
- while model1 = models.delete( models[0] )
54
- models.each{ |model2| save_models(model1, model2) }
47
+ def delegate_models_attributes(models)
48
+ models.each do |model|
49
+ model.column_names.each do |attr|
50
+ delegate attr.to_sym, "#{attr}=".to_sym, to: snake(model.to_s).to_sym, prefix: true
51
+ end
52
+ end
55
53
  end
56
- return true
57
54
  end
58
- false
59
- end
60
55
 
61
- def not_validate(*args)
62
- define_singleton_method(:array_of_models_without_validates) { args }
63
- end
56
+ def initialize(params: {})
57
+ self.params = params
58
+ get_or_add_default_objects
59
+ end
60
+
61
+ def get_or_add_default_objects
62
+ array_of_all_models.map do |model|
63
+ if get_self_object(model) == nil
64
+ method( "#{snake(model.to_s)}=" ).call(model.new)
65
+ else
66
+ get_self_object(model)
67
+ end
68
+ end
69
+ end
70
+ # INIT END
64
71
 
65
- private
66
72
 
67
- def save_models(model1, model2)
68
- self_object_of_model1 = method( snake(model1.to_s) ).call
69
- self_object_of_model2 = method( snake(model2.to_s) ).call
70
- association = get_association(model1, model2)
73
+ def apply_parameters
74
+ check_array_settings_with_settings
75
+ apply
76
+ end
77
+ alias_method :submit, :apply_parameters
71
78
 
72
- if association == :belongs_to or association == :has_one
73
- self_object_of_model1.send( "#{snake(model2.to_s)}=", self_object_of_model2 )
74
- self_object_of_model1.save!
75
- elsif association == :has_many or association == :has_and_belongs_to_many
76
- self_object_of_model1.method("#{model2.table_name}").call << self_object_of_model2
77
- self_object_of_model1.save!
79
+ def save
80
+ Saver.new(self).save
78
81
  end
79
- end
80
82
 
81
- def validation_models
82
- @array_of_models.each do |model|
83
- set_errors( method(snake(model.to_s)).call.errors ) unless method( snake(model.to_s) ).call.valid?
83
+ def validation_models
84
+ Validator.new(self).validate_form_object
84
85
  end
85
- end
86
86
 
87
- def set_errors(model_errors)
88
- model_errors.each do |attribute, message|
89
- errors.add(attribute, message)
87
+ # POMOGAY
88
+
89
+ def apply
90
+ assign = Assign.new(self)
91
+ @hash_objects_for_save = assign.apply_parameters
92
+ end
93
+
94
+ def check_array_settings_with_settings
95
+ define_singleton_method(:not_save_this_model) { [] } unless respond_to?(:not_validate_this_model)
96
+ define_singleton_method(:force_save_if_all_attr_is_nil) { [] } unless respond_to?(:force_save_if_all_attr_is_nil)
90
97
  end
91
- end
92
98
 
93
- def update_attributes
94
- @array_of_models.each do |model|
95
- model_attributes = make_attributes_of_model(model)
96
- method( snake(model.to_s) ).call.assign_attributes( get_attributes_for_update(model_attributes, model) )
99
+ def set_errors(object_errors)
100
+ object_errors.each do |attribute, message|
101
+ errors.add(attribute, message)
102
+ end
97
103
  end
98
- end
99
104
 
100
- def update_attributes_for_collection
101
- @array_of_models.each do |model|
102
- assign_attributes_for_collection(model)
105
+ def array_all_objects_for_save
106
+ array_objects_for_save ||= get_or_add_default_objects
103
107
  end
104
- end
105
108
 
106
- def keys_of_collections
107
- @keys ||= []
108
- params.keys.each do |key|
109
- @array_of_models.each do |model|
110
- self_object_of_model = method( snake(model.to_s) ).call
111
- method_name = key.to_s[/#{snake(model.to_s)}_(.*)/, 1]
112
- @keys << method_name if self_object_of_model.respond_to? method_name.to_s
113
- end if key[/^.+_ids$/]
114
- end if @keys.empty?
115
- @keys
116
109
  end
110
+ end
117
111
 
118
- def exist_any_errors_without_collections?
119
- keys_of_collections.each do |method_name|
120
- @array_of_models.each do |model|
121
- name_of_model = method_name.to_s[/^(.+)_ids$/, 1]
122
- name_of_constant_model = name_of_model.split('_').map(&:capitalize).join
123
- name_of_key_error = Object.const_get(name_of_constant_model).table_name
124
- errors.messages.delete(name_of_key_error.to_sym)
125
- end
126
- end unless valid?
127
- errors.messages.empty?
128
- end
129
112
 
130
- def assign_attributes_for_collection(model)
131
- self_object_of_model = method( snake(model.to_s) ).call
132
113
 
133
- keys_of_collections.each do |method_name|
134
- if self_object_of_model.respond_to? method_name
135
- old_attribute = self_object_of_model.method( method_name ).call
136
- unless self_object_of_model.update_attributes( {method_name.to_s => params["#{snake(model.to_s)}_#{method_name}".to_sym]} )
137
- set_errors(self_object_of_model.errors)
138
- self_object_of_model.update_attributes( {method_name.to_s => old_attribute} )
139
- end if exist_any_errors_without_collections?
140
- end
141
- end
142
- end
143
114
 
144
- def make_attributes_of_model(model)
145
- model_attributes = []
146
- model.column_names.each do |name|
147
- model_attributes << "#{snake(model.to_s)}_#{name}"
148
- end
149
- model_attributes
150
- end
151
115
 
152
- def get_attributes_for_update(model_attributes, model)
153
- update_attributes = {}
154
- hash_attributes = params.slice(*model_attributes)
155
- hash_attributes.each{ |attr, val| update_attributes[attr.gsub(/#{snake(model.to_s)}_(.*)/, '\1')] = val }
156
- update_attributes
157
- end
158
116
 
159
- def get_association(class1, class2)
160
- class1.reflections.slice(snake(class2.to_s), class2.table_name).values.first&.macro
161
- end
162
117
 
163
- end
@@ -0,0 +1,81 @@
1
+ module SlimFormObject
2
+ class Saver
3
+ include ::HelperMethods
4
+
5
+ attr_reader :form_object, :params, :validator, :hash_objects_for_save
6
+
7
+ def initialize(form_object)
8
+ @form_object = form_object
9
+ @params = form_object.params
10
+ @hash_objects_for_save = form_object.hash_objects_for_save
11
+ @validator = Validator.new(form_object)
12
+ end
13
+
14
+ def save
15
+ if form_object.valid?
16
+ ActiveRecord::Base.transaction do
17
+ save_main_objects
18
+ save_nested_objects
19
+ end
20
+ return true
21
+ end
22
+ false
23
+ rescue
24
+ # p "ERROR"
25
+ false
26
+ end
27
+
28
+ def save_main_objects
29
+ objects = Array.new(hash_objects_for_save[:objects])
30
+ while object_1 = objects.delete( objects[0] )
31
+ objects.each{ |object_2| save_objects(object_1, object_2) }
32
+ save_last_model_if_not_associations(object_1)
33
+ end
34
+ end
35
+
36
+ def save_nested_objects
37
+ hash_objects_for_save[:objects].each do |object_1|
38
+ next unless hash_objects_for_save[:nested_objects].include?( snake(object_1.class).to_sym )
39
+ hash_objects_for_save[:nested_objects][snake(object_1.class).to_sym].each do |object_2|
40
+ save_objects(object_1, object_2)
41
+ end
42
+ end
43
+ end
44
+
45
+ def save_objects(object_1, object_2)
46
+ object_for_save = to_bind_models(object_1, object_2)
47
+ save_object(object_for_save)
48
+ end
49
+
50
+ def to_bind_models(object_1, object_2)
51
+ association = get_association(object_1.class, object_2.class)
52
+
53
+ if association == :belongs_to or association == :has_one
54
+ object_1.send( "#{snake(object_2.class.to_s)}=", object_2 )
55
+ elsif association == :has_many or association == :has_and_belongs_to_many
56
+ object_1.method("#{object_2.class.table_name}").call << object_2
57
+ end
58
+
59
+ object_1
60
+ end
61
+
62
+ def save_object(object_of_model)
63
+ if validator.valid_model_for_save?(object_of_model.class)
64
+ object_of_model.save!
65
+ end
66
+ end
67
+
68
+ def save_last_model_if_not_associations(object_1)
69
+ association_trigger = false
70
+ hash_objects_for_save[:objects].each { |object_2| association_trigger = true if get_association(object_1.class, object_2.class) }
71
+ object_1.save unless association_trigger
72
+ rescue
73
+ object_1.class.find(object_1.id).update!(object_1.attributes)
74
+ end
75
+
76
+ def get_association(class1, class2)
77
+ class1.reflections.slice(snake(class2.to_s), class2.table_name).values.first&.macro
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,297 @@
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+ # require 'byebug'
10
+
11
+ # module SlimFormObject
12
+ # class Base
13
+ # attr_accessor :params
14
+
15
+ # def self.init_models(*args)
16
+ # self.instance_eval do
17
+ # define_method(:array_of_single_models) { args }
18
+ # end
19
+ # add_attributes(args)
20
+ # end
21
+
22
+ # alias_method :init_single_models, :init_models
23
+
24
+ # def self.init_multiple_models(*args)
25
+ # self.instance_eval do
26
+ # define_method(:array_multiple_models) { args }
27
+ # end
28
+ # add_attributes(args)
29
+ # end
30
+
31
+ # def self.add_attributes(models)
32
+ # #acessors for model objects
33
+ # models.each{ |model| attr_accessor snake(model.to_s).to_sym }
34
+
35
+ # #delegate attributes of models
36
+ # models.each do |model|
37
+ # model.column_names.each do |attr|
38
+ # delegate attr.to_sym, "#{attr}=".to_sym, to: snake(model.to_s).to_sym,
39
+ # prefix: true
40
+ # end
41
+ # end
42
+ # end
43
+
44
+ # def self.set_model_name(name)
45
+ # define_method(:model_name) { ActiveModel::Name.new(self, nil, name) }
46
+ # end
47
+ # # def initializer
48
+
49
+ # # end
50
+ # end
51
+
52
+ # def self.included(base)
53
+ # # define_properties(base)
54
+
55
+ # base.include ActiveModel::Model
56
+ # base.include HelperMethods
57
+ # base.extend ClassMethods
58
+ # base.extend HelperMethods
59
+ # end
60
+
61
+ # # def self.define_properties(form_object_klass)
62
+ # # class << form_object_klass
63
+ # # #attr_accessor for models and env params
64
+ # # # attr_accessor :params
65
+
66
+ # # # byebug
67
+
68
+ # # # def params=(val)
69
+ # # # @params = val
70
+ # # # end
71
+
72
+ # # # def params
73
+ # # # @params
74
+ # # # end
75
+ # # end
76
+ # # end
77
+
78
+ # # module ClassMethods
79
+
80
+ # # def init_models(*args)
81
+ # # self.instance_eval do
82
+ # # define_method(:array_of_single_models) { args }
83
+ # # end
84
+ # # add_attributes(args)
85
+ # # end
86
+
87
+ # # alias_method :init_single_models, :init_models
88
+
89
+ # # def init_multiple_models(*args)
90
+ # # self.instance_eval do
91
+ # # define_method(:array_multiple_models) { args }
92
+ # # end
93
+ # # add_attributes(args)
94
+ # # end
95
+
96
+ # # def add_attributes(models)
97
+ # # #acessors for model objects
98
+ # # models.each{ |model| attr_accessor snake(model.to_s).to_sym }
99
+
100
+ # # #delegate attributes of models
101
+ # # models.each do |model|
102
+ # # model.column_names.each do |attr|
103
+ # # delegate attr.to_sym, "#{attr}=".to_sym, to: snake(model.to_s).to_sym,
104
+ # # prefix: true
105
+ # # end
106
+ # # end
107
+ # # end
108
+
109
+ # # def set_model_name(name)
110
+ # # define_method(:model_name) { ActiveModel::Name.new(self, nil, name) }
111
+ # # end
112
+ # # end
113
+
114
+ # def submit
115
+ # @array_of_single_models ||= array_of_single_models.reject do |model|
116
+ # array_of_single_models_without_validates.include?(model) if self.respond_to?(:array_of_single_models_without_validates)
117
+ # end
118
+ # update_attributes
119
+ # update_attributes_for_collection
120
+ # self
121
+ # end
122
+
123
+ # alias_method :apply_parameters, :submit
124
+
125
+ # def save
126
+ # if valid?
127
+ # models = Array.new(@array_of_single_models)
128
+ # while model1 = models.delete( models[0] )
129
+ # models.each{ |model2| save_models(model1, model2) }
130
+ # save_last_model_if_not_associations(model1) if models.empty?
131
+ # end
132
+ # return true
133
+ # end
134
+ # false
135
+ # end
136
+
137
+ # def not_validate(*args)
138
+ # define_singleton_method(:array_of_single_models_without_validates) { args }
139
+ # end
140
+
141
+ # private
142
+
143
+ # def save_models(model_1, model_2)
144
+ # self_object_of_model_for_save = nil
145
+ # byebug
146
+ # if both_model_attributes_exist?(model_1, model_2)
147
+ # # byebug
148
+ # self_object_of_model_for_save = to_bind_models(model_1, model_2)
149
+ # save_model(self_object_of_model_for_save)
150
+ # else
151
+ # get_self_objects_of_model(model_1, model_2).each do |object|
152
+ # save_model(object)
153
+ # end
154
+ # end
155
+ # end
156
+
157
+ # def to_bind_models(model_1, model_2)
158
+ # self_object_of_model_1, self_object_of_model_2 = get_self_objects_of_model(model_1, model_2)
159
+ # association = get_association(model_1, model_2)
160
+
161
+ # if association == :belongs_to or association == :has_one
162
+ # self_object_of_model_1.send( "#{snake(model_2.to_s)}=", self_object_of_model_2 )
163
+ # elsif association == :has_many or association == :has_and_belongs_to_many
164
+ # self_object_of_model_1.method("#{model_2.table_name}").call << self_object_of_model_2
165
+ # end
166
+
167
+ # self_object_of_model_1
168
+ # end
169
+
170
+ # def valid_model_for_save?(model)
171
+ # ( (attributes_is_present?(model) and method( snake(model.to_s) ).call.id != nil) or (method( snake(model.to_s) ).call.id == nil and !all_attributes_is_empty?(model)) )
172
+ # end
173
+
174
+ # def attributes_is_present?(model)
175
+ # (make_attributes_of_model(model) & params.keys).present?
176
+ # end
177
+
178
+ # def both_model_attributes_exist?(model_1, model_2)
179
+ # valid_model_for_save?(model_1) and valid_model_for_save?(model_2)
180
+ # end
181
+
182
+ # def save_model(self_object_of_model)
183
+ # if valid_model_for_save?(self_object_of_model.class)
184
+ # self_object_of_model.save!
185
+ # end
186
+ # end
187
+
188
+ # def all_attributes_is_empty?(model)
189
+ # is_empty = true
190
+ # array_symbols_of_attributes = (make_attributes_of_model(model) & params.keys).map { |attr| attr.to_sym }
191
+ # params.slice(*array_symbols_of_attributes).values.each do |value|
192
+ # is_empty = false unless value == ""
193
+ # end
194
+ # is_empty
195
+ # end
196
+
197
+ # def get_self_objects_of_model(model_1, model_2)
198
+ # [ method( snake(model_1.to_s) ).call, method( snake(model_2.to_s) ).call ]
199
+ # end
200
+
201
+ # def save_last_model_if_not_associations(model)
202
+ # association_trigger = false
203
+ # self_object_of_model = method( snake(model.to_s) ).call
204
+ # @array_of_single_models.each { |model2| association_trigger = true if get_association(model, model2) }
205
+ # self_object_of_model.save unless association_trigger
206
+ # rescue
207
+ # self_object_of_model.class.find(self_object_of_model.id).update!(self_object_of_model.attributes)
208
+ # end
209
+
210
+ # def validation_models
211
+ # @array_of_single_models.each do |model|
212
+ # next unless valid_model_for_save?(model)
213
+ # set_errors( method(snake(model.to_s)).call.errors ) unless method( snake(model.to_s) ).call.valid?
214
+ # end
215
+ # end
216
+
217
+ # def set_errors(model_errors)
218
+ # model_errors.each do |attribute, message|
219
+ # errors.add(attribute, message)
220
+ # end
221
+ # end
222
+
223
+ # def update_attributes
224
+ # @array_of_single_models.each do |model|
225
+ # model_attributes = make_attributes_of_model(model)
226
+ # method( snake(model.to_s) ).call.assign_attributes( get_attributes_for_update(model_attributes, model) )
227
+ # end
228
+ # end
229
+
230
+ # def update_attributes_for_collection
231
+ # @array_of_single_models.each do |model|
232
+ # assign_attributes_for_collection(model)
233
+ # end
234
+ # end
235
+
236
+ # def keys_of_collections
237
+ # @keys ||= []
238
+ # params.keys.each do |key|
239
+ # @array_of_single_models.each do |model|
240
+ # self_object_of_model = method( snake(model.to_s) ).call
241
+ # method_name = key.to_s[/#{snake(model.to_s)}_(.*)/, 1]
242
+ # @keys << method_name if self_object_of_model.respond_to? method_name.to_s
243
+ # end if key[/^.+_ids$/]
244
+ # end if @keys.empty?
245
+ # @keys
246
+ # end
247
+
248
+ # def exist_any_errors_without_collections?
249
+ # keys_of_collections.each do |method_name|
250
+ # @array_of_single_models.each do |model|
251
+ # name_of_model = method_name.to_s[/^(.+)_ids$/, 1]
252
+ # name_of_constant_model = name_of_model.split('_').map(&:capitalize).join
253
+ # name_of_key_error = Object.const_get(name_of_constant_model).table_name
254
+ # errors.messages.delete(name_of_key_error.to_sym)
255
+ # end
256
+ # end unless valid?
257
+ # errors.messages.empty?
258
+ # end
259
+
260
+ # def assign_attributes_for_collection(model)
261
+ # self_object_of_model = method( snake(model.to_s) ).call
262
+
263
+ # keys_of_collections.each do |method_name|
264
+ # if self_object_of_model.respond_to? method_name
265
+ # old_attribute = self_object_of_model.method( method_name ).call
266
+ # unless self_object_of_model.update_attributes( {method_name.to_s => params["#{snake(model.to_s)}_#{method_name}".to_sym]} )
267
+ # set_errors(self_object_of_model.errors)
268
+ # self_object_of_model.update_attributes( {method_name.to_s => old_attribute} )
269
+ # end if exist_any_errors_without_collections?
270
+ # end
271
+ # end
272
+ # end
273
+
274
+ # def make_attributes_of_model(model)
275
+ # model_attributes = []
276
+ # model.column_names.each do |name|
277
+ # model_attributes << "#{snake(model.to_s)}_#{name}"
278
+ # end
279
+ # model_attributes
280
+ # end
281
+
282
+ # def get_attributes_for_update(model_attributes, model)
283
+ # attributes_for_update = {}
284
+ # hash_attributes = params.slice(*model_attributes)
285
+ # hash_attributes.each{ |attr, val| attributes_for_update[attr.gsub(/#{snake(model.to_s)}_(.*)/, '\1')] = val }
286
+ # attributes_for_update
287
+ # end
288
+
289
+ # def get_association(class1, class2)
290
+ # class1.reflections.slice(snake(class2.to_s), class2.table_name).values.first&.macro
291
+ # end
292
+
293
+
294
+ # # get attributes
295
+ # # .gsub(/^\[|\]$|"/, '').split(', ')
296
+
297
+ # end
@@ -0,0 +1,55 @@
1
+ module SlimFormObject
2
+ class Validator
3
+ include ::HelperMethods
4
+
5
+ attr_reader :form_object, :params, :hash_objects_for_save
6
+
7
+ def initialize(form_object)
8
+ @form_object = form_object
9
+ @params = form_object.params
10
+ @hash_objects_for_save = form_object.hash_objects_for_save
11
+ end
12
+
13
+ def validate_form_object
14
+ filter_nil_objects
15
+
16
+ hash_objects_for_save[:objects].each do |object|
17
+ next if all_attributes_is_nil?(object)
18
+ form_object.set_errors( object.errors ) unless object.valid?
19
+ end
20
+
21
+ hash_objects_for_save[:nested_objects].keys.each do |snake_model_name|
22
+ hash_objects_for_save[:nested_objects][snake_model_name].each do |object|
23
+ form_object.set_errors( object.errors ) unless object.valid?
24
+ end
25
+ end
26
+ end
27
+
28
+ def filter_nil_objects
29
+ hash_objects_for_save[:objects].reject! do |object|
30
+ all_attributes_is_nil?(object)
31
+ end
32
+ end
33
+
34
+ def valid_model_for_save?(object)
35
+ # ( (attributes_is_present?(object) and object.id != nil) or (object.id == nil and !all_attributes_is_empty?(object)) )
36
+ true
37
+ end
38
+
39
+ def both_model_attributes_exist?(object_1, object_2)
40
+ # valid_model_for_save?(object_1) and valid_model_for_save?(object_2)
41
+ !(all_attributes_is_nil?(object_1) and all_attributes_is_nil?(object_2))
42
+ end
43
+
44
+ def all_attributes_is_nil?(object)
45
+ object.class.column_names.each do |attr_name|
46
+ return false if object.send(attr_name.to_sym) != nil
47
+ end
48
+ true
49
+ end
50
+
51
+ end
52
+ end
53
+
54
+
55
+
@@ -1,3 +1,3 @@
1
1
  module SlimFormObject
2
- VERSION = "0.5.23"
2
+ VERSION = "1.0.1"
3
3
  end
@@ -1,5 +1,5 @@
1
1
 
2
- class CreateModelOne < ActiveRecord::Migration
2
+ class CreateModelOne < ActiveRecord::Migration[5.0]
3
3
  def self.up
4
4
  create_table :test_one_models do |t|
5
5
  t.string :title
@@ -1,5 +1,5 @@
1
1
 
2
- class CreateModelTwo < ActiveRecord::Migration
2
+ class CreateModelTwo < ActiveRecord::Migration[5.0]
3
3
  def self.up
4
4
  create_table :test_two_models do |t|
5
5
  t.string :title
@@ -1,5 +1,5 @@
1
1
 
2
- class CreateModelThree < ActiveRecord::Migration
2
+ class CreateModelThree < ActiveRecord::Migration[5.0]
3
3
  def self.up
4
4
  create_table :test_three_models do |t|
5
5
  t.string :title
@@ -1,5 +1,5 @@
1
1
 
2
- class CreateModelFour < ActiveRecord::Migration
2
+ class CreateModelFour < ActiveRecord::Migration[5.0]
3
3
  def self.up
4
4
  create_table :test_four_models do |t|
5
5
  t.string :title
@@ -1,5 +1,5 @@
1
1
 
2
- class CreateModelOneFour < ActiveRecord::Migration
2
+ class CreateModelOneFour < ActiveRecord::Migration[5.0]
3
3
  def self.up
4
4
  create_table :test_one_four_models do |t|
5
5
  t.integer :test_one_model_id
@@ -1,5 +1,5 @@
1
1
 
2
- class CreateModelTwoThree < ActiveRecord::Migration
2
+ class CreateModelTwoThree < ActiveRecord::Migration[5.0]
3
3
  def self.up
4
4
  create_table :test_three_model_test_two_models do |t|
5
5
  t.integer :test_three_model_id
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: 0.5.23
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - woodcrust
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-23 00:00:00.000000000 Z
11
+ date: 2017-06-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -16,14 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 4.0.0
19
+ version: 5.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 4.0.0
26
+ version: 5.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: 5.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: 5.0.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -147,8 +161,13 @@ extra_rdoc_files: []
147
161
  files:
148
162
  - bin/slim_form_object
149
163
  - lib/slim_form_object.rb
164
+ - lib/slim_form_object/assign.rb
165
+ - lib/slim_form_object/form_helpers/extension_actionview.rb
150
166
  - lib/slim_form_object/helpers.rb
151
167
  - lib/slim_form_object/processing.rb
168
+ - lib/slim_form_object/saver.rb
169
+ - lib/slim_form_object/tmp.rb
170
+ - lib/slim_form_object/validator.rb
152
171
  - lib/slim_form_object/version.rb
153
172
  - spec/db/database.yml
154
173
  - spec/db/database.yml.travis