active_form_objects 0.1.2 → 1.0.0.beta

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: daff81f1e757efcd09b602052b01108e5975ec4afdbc23eb990d9fd4fad28067
4
- data.tar.gz: bd751ee1875ac9ff54e70d107106cbc041e499dedd9bb8b44147c0f902ea44eb
3
+ metadata.gz: '03871811ee607637a50a7c85d85985dea846a563709f4d1b803aa681589e5517'
4
+ data.tar.gz: d6fb754563a486d09e99cb09dc183dc276d83f0d1ab9b8a11c83003a8920340e
5
5
  SHA512:
6
- metadata.gz: 23909b529fe45a1de257f237698b6be281d1ef4d8ec8d7f09a588783ced45552e4373ca185e6787a23f3be2552a3a8c3b08477b14daef69dc8082ebd1e026a60
7
- data.tar.gz: 3ed88b54b54be83db842ebb37565eecfe194bc12c970b01b26871ef0d95c0364705ea6b01e376ea6d584fb6877025c34ad6143e23902dc3cb6fb8c9c63ae80e7
6
+ metadata.gz: f041ee7728861ab7112f9202284bb1d133c877fe42def63e9ba437efb2ebc87efb8ffab77f5a7d519001eba7639c51b03b87371e5c35d5586bde821dc7a18ce4
7
+ data.tar.gz: 362e0149393a0fd88f129e4169e16c3f037ec506610de8469fe6d33a5478f540c7fda66da8aafebe8be0981f17a200c58a011c94f0d695925ec1a5ff565bf194
@@ -1,97 +1,36 @@
1
- require 'active_support'
2
1
  require 'active_model'
3
- require 'active_support/core_ext/object/instance_variables'
4
- require 'active_support/core_ext/hash/indifferent_access'
5
- require_relative 'concerns/relations'
6
- require_relative 'concerns/savings'
2
+
3
+ require_relative 'dsl/relations'
4
+ require_relative 'dsl/attributes'
5
+ require_relative 'dsl/delegates'
6
+ require_relative 'dsl/savings'
7
+ require_relative 'dsl/resource'
8
+ require_relative 'dsl/polymorphs'
9
+
10
+ require_relative 'handlers/initializer'
11
+ require_relative 'handlers/relations'
12
+ require_relative 'handlers/resource'
13
+ require_relative 'handlers/attributes'
7
14
 
8
15
  module ActiveFormObjects
9
16
  class Base
10
17
  include ActiveModel::Model
11
- include Relations
12
- include Savings
13
-
14
- @@authorized_params = {}
15
- @@overrided_params = {}
16
- @@default_params = {}
17
- @@preparers = {}
18
- @@resource = {}
19
-
20
- attr_reader :resource
21
-
22
- def self.resource(resource = nil, &block)
23
- bloc_to_call = block || proc { resource }
24
- @@resource[name] = bloc_to_call
25
- end
26
-
27
- def self.prepare(*params)
28
- method_to_call = params.last[:with]
29
- @@preparers[name] = (@@preparers[name] || []) + [{
30
- key: params.first,
31
- method_to_call: method_to_call
32
- }]
33
- end
34
-
35
- def self.attributes(*params)
36
- @@authorized_params[name] = (@@authorized_params[name] || []) + params
37
- send(:attr_accessor, *params)
38
- end
39
-
40
- def self.delegate(*params)
41
- delegator = params.last
42
- params.pop
43
- send(:attributes, *params)
44
- define_method("#{delegator[:to]}_params") do
45
- attrs_only(params)
46
- end
47
- end
48
18
 
49
- def self.set_default(params)
50
- [params[:to]].flatten.each do |param|
51
- @@default_params[name] ||= {}
52
- @@default_params[name][param] = params[:value]
53
- end
54
- send(:attributes, *params[:to])
55
- end
56
-
57
- def self.ensure_value(param, value)
58
- @@overrided_params[name] ||= {}
59
- @@overrided_params[name][param] = value
60
-
61
- send(:attributes, param)
62
- end
19
+ include Dsl::Resource
20
+ include Dsl::Attributes
21
+ include Dsl::Relations
22
+ include Dsl::Polymorphs
23
+ include Dsl::Delegates
24
+ include Dsl::Savings
63
25
 
64
26
  def initialize(params, resource = nil)
65
- @resource = resource || @@resource[self.class.name].try(:call, params).try(:new)
66
- set_associated_forms
67
- params = affect_relation_values(params)
68
- resource_params(params || {})
69
-
70
- params_with_resource_attrs = @resource.respond_to?(:attributes) ? @resource.attributes.symbolize_keys.slice(*@authorized_params).merge(@params) : @params
71
- params_with_preprared_value = affect_prepared_values(params_with_resource_attrs)
72
- super(params_with_preprared_value)
73
- end
74
-
75
- def affect_prepared_values(params)
76
- (@@preparers[self.class.name] || []).each do |preparer|
77
- params[preparer[:key]] = params[preparer[:key]].try(preparer[:method_to_call])
78
- end
79
- params
80
- end
81
-
82
- def resource_params(params)
83
- @default_params = @@default_params[self.class.name] || {}
84
- @overrided_params = @@overrided_params[self.class.name] || {}
85
- @authorized_params = @@authorized_params[self.class.name] || {}
86
- @params = @default_params.merge(params.to_h.symbolize_keys).merge(@overrided_params).slice(*@authorized_params)
87
- end
88
-
89
- def attrs_only(params)
90
- attributes.slice(*params)
91
- end
27
+ @params = params
28
+ @resource = resource
92
29
 
93
- def attributes
94
- instance_values.with_indifferent_access.symbolize_keys
30
+ Handlers::Initializer.handle(self)
31
+ Handlers::Resource.handle(self)
32
+ Handlers::Attributes.handle(self)
33
+ super(@params)
95
34
  end
96
35
  end
97
36
  end
@@ -0,0 +1,44 @@
1
+ require 'active_support'
2
+
3
+ module Dsl
4
+ module Attributes
5
+ extend ActiveSupport::Concern
6
+
7
+ @@attributes = {}
8
+ @@overrided_params = {}
9
+ @@default_params = {}
10
+ @@preparers = {}
11
+
12
+ included do
13
+ attr_accessor :params
14
+
15
+ def self.attributes(*params)
16
+ @@attributes[name] = (@@attributes[name] || []) + params
17
+ attr_accessor(*params)
18
+ end
19
+
20
+ def self.set_default(params)
21
+ [params[:to]].flatten.each do |param|
22
+ @@default_params[name] ||= {}
23
+ @@default_params[name][param] = params[:value]
24
+ end
25
+ send(:attributes, *params[:to])
26
+ end
27
+
28
+ def self.ensure_value(param, value)
29
+ @@overrided_params[name] ||= {}
30
+ @@overrided_params[name][param] = value
31
+
32
+ send(:attributes, param)
33
+ end
34
+
35
+ def self.prepare(*params)
36
+ method_to_call = params.last[:with]
37
+ @@preparers[name] = (@@preparers[name] || []) + [{
38
+ key: params.first,
39
+ method_to_call: method_to_call
40
+ }]
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,18 @@
1
+ require 'active_support'
2
+
3
+ module Dsl
4
+ module Delegates
5
+ extend ActiveSupport::Concern
6
+
7
+ @@delegators = {}
8
+
9
+ included do
10
+ def self.delegate(*params)
11
+ delegator = params.last[:to].merge(attributes: params)
12
+ params.pop
13
+
14
+ @@delegators[name] = (@@delegators[name] || []) << delegator
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,35 @@
1
+ require 'active_support'
2
+ require 'active_model'
3
+
4
+ module Dsl
5
+ module Polymorphs
6
+ extend ActiveSupport::Concern
7
+
8
+ @@polymorphic_keys = {}
9
+
10
+ class_methods do
11
+ # Allows to declare a polymorphic relationship
12
+ #
13
+ # Params:
14
+ # +key+:: the corresponding key in the params hash
15
+ # +possible_types+:: A hash that follows the below format
16
+ #
17
+ # polymorph(:content, :program_id, {
18
+ # foo: Bar
19
+ # })
20
+ #
21
+ # Int the above example the possible_types hash :
22
+ # scannable => key
23
+ # Scannable => model class
24
+ #
25
+ def polymorph(key, possible_types)
26
+ @@polymorphic_keys[name] ||= []
27
+ @@polymorphic_keys[name] << {
28
+ key: key,
29
+ types: possible_types
30
+ }
31
+ send(:attributes, key)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,39 @@
1
+ require 'active_support'
2
+ require 'active_model'
3
+
4
+ module Dsl
5
+ module Relations
6
+ extend ActiveSupport::Concern
7
+
8
+ @@relation_keys = {}
9
+
10
+ class RelationValidator < ActiveModel::EachValidator
11
+ def validate_each(record, attribute, _)
12
+ record.errors.add(attribute, "#{attribute} or #{attribute}_id is required") unless record.try(attribute).present? || record.try("#{attribute}_id".to_sym).present?
13
+ end
14
+ end
15
+
16
+ class_methods do
17
+ # Allows to receive a relation as an input params.
18
+ # Relation can then be received either as :
19
+ # - relation_id => The key to the corresponding relation
20
+ # - relation => An instance of the object
21
+ #
22
+ # Params:
23
+ # +params+:: the list of relations to declare
24
+ #
25
+ # Example :
26
+ # relations(:entity, :user)
27
+ #
28
+ def relations(*params)
29
+ validates(*params, relation: true)
30
+
31
+ params.each do |param|
32
+ relation_key = "#{param}_id".to_sym
33
+ send(:attributes, param, relation_key)
34
+ @@relation_keys[name] = (@@relation_keys[name] || []) + [param]
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,18 @@
1
+ require 'active_support'
2
+
3
+ module Dsl
4
+ module Resource
5
+ extend ActiveSupport::Concern
6
+
7
+ @@resource = {}
8
+
9
+ included do
10
+ attr_reader :resource
11
+
12
+ def self.resource(resource = nil, &block)
13
+ bloc_to_call = block || proc { resource }
14
+ @@resource[name] = bloc_to_call
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ require 'active_support'
2
+ require 'active_record'
3
+ require_relative '../handlers/savings'
4
+
5
+ module Dsl
6
+ module Savings
7
+ extend ActiveSupport::Concern
8
+
9
+ class_methods do
10
+ def save(&block)
11
+ define_method(:save!) do
12
+ Handlers::Savings.new(self).save!(&block)
13
+ end
14
+ end
15
+ end
16
+
17
+ def save!
18
+ Handlers::Savings.new(self).save!
19
+ end
20
+
21
+ def save
22
+ save!
23
+ rescue
24
+ false
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,52 @@
1
+ require 'active_support/core_ext/hash/reverse_merge'
2
+ require_relative 'base'
3
+ require_relative 'relations'
4
+ require_relative 'delegates'
5
+
6
+ module Handlers
7
+ class Attributes < Base
8
+ def handle
9
+ start_with_default_params!
10
+ affect_prepared_values!
11
+ merge_with_resource_attributes!
12
+ affect_relation_values!
13
+ merge_overrided_params!
14
+ slice_unauthorized_attributes!
15
+ end
16
+
17
+ # DSL method : set_default
18
+ def start_with_default_params!
19
+ default_params = upper(:@@default_params) || {}
20
+ @params.reverse_merge!(default_params)
21
+ end
22
+
23
+ # DSL method : prepare
24
+ def affect_prepared_values!
25
+ (upper(:@@preparers) || []).each do |preparer|
26
+ @params[preparer[:key]] = @params[preparer[:key]].try(preparer[:method_to_call])
27
+ end
28
+ end
29
+
30
+ def merge_with_resource_attributes!
31
+ return unless @resource.respond_to?(:attributes)
32
+ @params.reverse_merge!(@resource.attributes.symbolize_keys)
33
+ end
34
+
35
+ # DSL method : ensure_value
36
+ def merge_overrided_params!
37
+ overrided_params = upper(:@@overrided_params) || {}
38
+ @params.merge!(overrided_params)
39
+ end
40
+
41
+ # DSL method : relation
42
+ def affect_relation_values!
43
+ Relations.new(@klass).affect_relation_values!
44
+ end
45
+
46
+ # DSL method : attributes
47
+ def slice_unauthorized_attributes!
48
+ authorized_attributes = upper(:@@attributes) || {}
49
+ @params.slice!(*authorized_attributes)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,18 @@
1
+ module Handlers
2
+ class Base
3
+ def initialize(klass)
4
+ @klass = klass
5
+ @raw_params = @klass.instance_variable_get(:@raw_params)
6
+ @params = @klass.instance_variable_get(:@params)
7
+ @resource = @klass.instance_variable_get(:@resource)
8
+ end
9
+
10
+ def self.handle(klass)
11
+ new(klass).handle
12
+ end
13
+
14
+ def upper(var)
15
+ @klass.class.class_variable_get(var)[@klass.class.name]
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,33 @@
1
+ require_relative 'base'
2
+
3
+ module Handlers
4
+ class Delegates < Base
5
+ def handle
6
+ delegates = upper :@@delegators
7
+ (delegates || []).each do |delegate|
8
+ Delegate.new(@klass, delegate).handle
9
+ end
10
+ end
11
+ end
12
+
13
+ class Delegate < Base
14
+ def initialize(klass, delegate)
15
+ @delegate = delegate
16
+
17
+ @form = @delegate[:form]
18
+ @foreign_key = @delegate[:foreign_key]
19
+ @relation = @delegate[:relation]
20
+ @attributes = @delegate[:attributes]
21
+
22
+ super(klass)
23
+ end
24
+
25
+ def handle
26
+ @attributes = @raw_params.slice(*@attributes).merge({
27
+ @foreign_key => @resource.id
28
+ })
29
+
30
+ @form.new(@attributes, @resource.send(@relation)).save!
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,8 @@
1
+ module Handlers
2
+ class Initializer
3
+ def self.handle(klass)
4
+ params = klass.instance_variable_get(:@params)
5
+ klass.instance_variable_set('@raw_params', {}.merge(params).freeze)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,53 @@
1
+ require_relative 'base'
2
+
3
+ module Handlers
4
+ class Polymorphs < Base
5
+ def handle
6
+ polymorphs = upper :@@polymorphic_keys
7
+ (polymorphs || []).each do |polymorph|
8
+ Polymorph.new(@klass, polymorph).handle
9
+ end
10
+ end
11
+ end
12
+
13
+ class Polymorph < Base
14
+ # Handle either the retrieving of the associated relation
15
+ # or
16
+ # the creation of the resource based on this possible input and the params
17
+ #
18
+ # Params:
19
+ # +klass+:: ActiveFormObject::Base instance
20
+ # +polymorph+:: The param specified in the dsl, example :
21
+ # {
22
+ # key: :content,
23
+ # foreign_key: :program_id,
24
+ # types: {
25
+ # polymorph: Dsl::PolymorphsTest::PolymorphForeignForm
26
+ # }
27
+ # }
28
+ #
29
+ def initialize(klass, polymorph)
30
+ @polymorph = polymorph
31
+ super(klass)
32
+ end
33
+
34
+ def handle
35
+ @params_to_send = @params[@polymorph[:key]] || {}
36
+ polymorph_instance = form_class.new(@params_to_send, @resource.try(@polymorph[:key])).save!
37
+
38
+ @params["#{@polymorph[:key]}_id".to_sym] = polymorph_instance.id
39
+ @params["#{@polymorph[:key]}_type".to_sym] = polymorph_instance.class.name
40
+ @params.delete(@polymorph[:key])
41
+ end
42
+
43
+ def form_class
44
+ @polymorph[:types][
45
+ @resource.try("#{@polymorph[:key]}_type".to_sym) || clean_params.try(:to_sym)
46
+ ]
47
+ end
48
+
49
+ def clean_params
50
+ @params_to_send.delete(:type)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,12 @@
1
+ require_relative 'base'
2
+
3
+ module Handlers
4
+ class Relations < Base
5
+ def affect_relation_values!
6
+ relation_keys = upper(:@@relation_keys) || {}
7
+ {}.merge(@params).each_key do |key|
8
+ @params["#{key}_id".to_sym] = @params[key.to_sym].id if relation_keys.include?(key)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require_relative 'base'
2
+
3
+ module Handlers
4
+ class Resource < Base
5
+ def handle
6
+ class_resource = upper(:@@resource)
7
+ @resource ||= class_resource.try(:call, @params).try(:new)
8
+
9
+ @klass.instance_variable_set(:@resource, @resource)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,42 @@
1
+ require 'active_support'
2
+ require 'active_record'
3
+
4
+ require_relative 'base'
5
+ require_relative 'polymorphs'
6
+ require_relative 'delegates'
7
+
8
+ module Handlers
9
+ class Savings < Base
10
+ def save!(&block)
11
+ # ActiveRecord::Base.transaction do
12
+ @klass.validate!
13
+
14
+ before_save_hooks!
15
+ block ? save_with_block!(block) : save_without_block!
16
+ after_save_hooks!
17
+
18
+ @resource
19
+ # end
20
+ rescue ActiveRecord::RecordInvalid => e
21
+ e.record.errors.add(e.record.class.name, '')
22
+ raise ActiveRecord::RecordInvalid.new(e.record)
23
+ end
24
+
25
+ def after_save_hooks!
26
+ Delegates.handle(@klass)
27
+ end
28
+
29
+ def save_with_block!(block)
30
+ @klass.instance_eval(&block)
31
+ @resource.try(:save!)
32
+ end
33
+
34
+ def save_without_block!
35
+ @resource.update!(@params)
36
+ end
37
+
38
+ def before_save_hooks!
39
+ Polymorphs.handle(@klass)
40
+ end
41
+ end
42
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_form_objects
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 1.0.0.beta
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michaël Villeneuve
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '4.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '4.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '4.2'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: activemodel
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -45,8 +59,20 @@ extensions: []
45
59
  extra_rdoc_files: []
46
60
  files:
47
61
  - lib/active_form_objects.rb
48
- - lib/concerns/relations.rb
49
- - lib/concerns/savings.rb
62
+ - lib/dsl/attributes.rb
63
+ - lib/dsl/delegates.rb
64
+ - lib/dsl/polymorphs.rb
65
+ - lib/dsl/relations.rb
66
+ - lib/dsl/resource.rb
67
+ - lib/dsl/savings.rb
68
+ - lib/handlers/attributes.rb
69
+ - lib/handlers/base.rb
70
+ - lib/handlers/delegates.rb
71
+ - lib/handlers/initializer.rb
72
+ - lib/handlers/polymorphs.rb
73
+ - lib/handlers/relations.rb
74
+ - lib/handlers/resource.rb
75
+ - lib/handlers/savings.rb
50
76
  homepage: https://github.com/fidme/active_form_objects
51
77
  licenses:
52
78
  - MIT
@@ -62,9 +88,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
62
88
  version: '0'
63
89
  required_rubygems_version: !ruby/object:Gem::Requirement
64
90
  requirements:
65
- - - ">="
91
+ - - ">"
66
92
  - !ruby/object:Gem::Version
67
- version: '0'
93
+ version: 1.3.1
68
94
  requirements: []
69
95
  rubyforge_project:
70
96
  rubygems_version: 2.7.3
@@ -1,35 +0,0 @@
1
- require 'active_support'
2
- require 'active_model'
3
-
4
- module Relations
5
- extend ActiveSupport::Concern
6
-
7
- @@relation_keys = {}
8
-
9
- class RelationValidator < ActiveModel::EachValidator
10
- def validate_each(record, attribute, value)
11
- record.errors.add(attribute, "#{attribute} or #{attribute}_id is required") unless record.try(attribute).present? || record.try("#{attribute}_id".to_sym).present?
12
- end
13
- end
14
-
15
- def affect_relation_values(params)
16
- @relation_keys = @@relation_keys[self.class.name] || []
17
- params.keys.each do |key|
18
- params["#{key}_id".to_sym] = params[key.to_sym].id if @relation_keys.include?(key)
19
- end
20
-
21
- params
22
- end
23
-
24
- class_methods do
25
- def relations(*params)
26
- validates *params, relation: true
27
-
28
- params.each do |param|
29
- relation_key = "#{param}_id".to_sym
30
- send(:attributes, param, relation_key)
31
- @@relation_keys[name] = (@@relation_keys[name] || []) + [param]
32
- end
33
- end
34
- end
35
- end
@@ -1,71 +0,0 @@
1
- require 'active_support'
2
-
3
- module Savings
4
- extend ActiveSupport::Concern
5
-
6
- @@associated_forms = {}
7
-
8
- class_methods do
9
- def associated(key, form, params = nil)
10
- @@associated_forms[name] ||= []
11
- @@associated_forms[name] << { name: key, form: form, params: params }
12
-
13
- set_default value: {}, to: key
14
- end
15
-
16
- def save(&block)
17
- define_method(:save!) do
18
- with_rescue do
19
- ActiveRecord::Base.transaction do
20
- validate!
21
- instance_eval(&block)
22
- @resource.try(:save!)
23
- end
24
- @resource
25
- end
26
- end
27
- end
28
- end
29
-
30
- def save!
31
- with_rescue do
32
- if @@associated_forms[self.class.name].nil?
33
- validate!
34
- @resource.update!(@params)
35
- @resource
36
- else
37
- save_associated_forms!
38
- end
39
- end
40
- end
41
-
42
- def save
43
- save!
44
- rescue
45
- false
46
- end
47
-
48
- def save_associated_forms!
49
- (@@associated_forms[self.class.name] || []).each do |associated|
50
- params = associated[:params].nil? ? @params[associated[:name]] : send(associated[:params])
51
- resource_to_save = send("#{associated[:name]}_to_update") rescue nil
52
- @TheForm = associated[:form]
53
-
54
- saved_form = @TheForm.new(params, resource_to_save).save!
55
- instance_variable_set("@#{associated[:name]}", saved_form)
56
- end
57
- end
58
-
59
- def set_associated_forms
60
- (@@associated_forms[self.class.name] || []).each do |form|
61
- instance_variable_set("@#{form[:name]}_form", form[:form])
62
- end
63
- end
64
-
65
- def with_rescue
66
- yield
67
- rescue ActiveRecord::RecordInvalid => e
68
- e.record.errors.add(e.record.class.name, '')
69
- raise ActiveRecord::RecordInvalid.new(e.record)
70
- end
71
- end