eac_rails_utils 0.19.0 → 0.20.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: 3e4525483ddef206757144a407560d2b7569db1933b16935da157aef0e8645c4
4
- data.tar.gz: 163bb84353cde0a519afaba18890920cf8f04920291f8e457d81431743e61bf4
3
+ metadata.gz: 424e322548e7f55ef6044d3c7e4339cd8336b272604d40678c7016b218b69494
4
+ data.tar.gz: 28dd2d2a83760c49bbb30e0210e2c4aa096be75a77f7edf720cff7700f2cce9c
5
5
  SHA512:
6
- metadata.gz: 7313d2b4e45e6893a574df04e25ef627d0edea64820eda383a22ead2bd21243d377fb659ced3c58c84726f1f06d1c0904678510a6a60263e4aac88c45742d414
7
- data.tar.gz: 8d5b6f1ab06c37696f0dd780e4017c519c41e1a2c717e9bbe3fa066824a30766fd84641546bdabe20978cb3adbba8808b06384bc3ec8ef3a4e93bf61c378f678
6
+ metadata.gz: c7ebba5d2e7736bcefdef37c3a015130047b12ff880b2862e871b3cbd7cd1e9c9ca5bde9ab7d51def8215d4c9049bfeb2cb1a9c2ed072011dd5402e850135d59
7
+ data.tar.gz: cc57e040cca6a24be309903034e74d7ff63394efd1090191f0c90b8620404ec2f31594fa4d166b40a872aa67481486c6093713722998cb77ad5d04e1298e6cea
@@ -0,0 +1,38 @@
1
+ module ActiveModel::Associations
2
+ module ActiveRecordReflection
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ if ActiveRecord.version >= Gem::Version.new("4.1.2")
7
+ class_attribute :_reflections
8
+ self._reflections = ActiveSupport::HashWithIndifferentAccess.new
9
+ else
10
+ class_attribute :reflections
11
+ self.reflections = {}
12
+ end
13
+ end
14
+
15
+ module ClassMethods
16
+ if ActiveRecord.version < Gem::Version.new("4.1")
17
+ def create_reflection(macro, name, scope, options, active_record)
18
+ case macro
19
+ when :has_many, :belongs_to
20
+ klass = ActiveRecord::Reflection::AssociationReflection
21
+ reflection = klass.new(macro, name, scope, options, active_record)
22
+ end
23
+
24
+ self.reflections = self.reflections.merge(name => reflection)
25
+ reflection
26
+ end
27
+ end
28
+
29
+ def reflect_on_association(association)
30
+ if ActiveRecord.version >= Gem::Version.new("4.1.2")
31
+ _reflections[association.to_s]
32
+ else
33
+ reflections[association]
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,23 @@
1
+ module ActiveModel::Associations
2
+ module AssociationScopeExtension
3
+ if ActiveRecord.version >= Gem::Version.new("5.0.0.beta")
4
+ def add_constraints(scope, owner, association_klass, refl, chain_head, chain_tail)
5
+ if refl.options[:active_model]
6
+ target_ids = refl.options[:target_ids]
7
+ return scope.where(id: owner[target_ids])
8
+ end
9
+
10
+ super
11
+ end
12
+ else
13
+ def add_constraints(scope, owner, assoc_klass, refl, tracker)
14
+ if refl.options[:active_model]
15
+ target_ids = refl.options[:target_ids]
16
+ return scope.where(id: owner[target_ids])
17
+ end
18
+
19
+ super
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ module ActiveModel::Associations
2
+ module AutosaveAssociation
3
+ extend ActiveSupport::Concern
4
+
5
+ include ActiveRecord::AutosaveAssociation
6
+
7
+ included do
8
+ extend ActiveModel::Callbacks
9
+ define_model_callbacks :save, :create, :update
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ module ActiveModel::Associations
2
+ module Hooks
3
+ def self.init
4
+ ActiveSupport.on_load(:active_record) do
5
+ require 'active_model/associations/association_scope_extension'
6
+ ActiveRecord::Associations::AssociationScope.send(:prepend, ActiveModel::Associations::AssociationScopeExtension)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,16 @@
1
+ module ActiveModel::Associations
2
+ module InitializeExtension
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ prepend WithAssociationCache
7
+ end
8
+
9
+ module WithAssociationCache
10
+ def initialize(*args)
11
+ @association_cache = {}
12
+ super
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,111 @@
1
+ module ActiveModel::Associations
2
+ module OverrideMethods
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ def generated_association_methods
7
+ @generated_association_methods ||= begin
8
+ mod = const_set(:GeneratedAssociationMethods, Module.new)
9
+ include mod
10
+ mod
11
+ end
12
+ end
13
+ alias :generated_feature_methods :generated_association_methods \
14
+ if ActiveRecord.version < Gem::Version.new("4.1")
15
+
16
+ # override
17
+ def dangerous_attribute_method?(name)
18
+ false
19
+ end
20
+
21
+ # dummy table name
22
+ def pluralize_table_names
23
+ self.to_s.pluralize
24
+ end
25
+
26
+ def clear_reflections_cache
27
+ @__reflections = nil
28
+ end
29
+
30
+ def default_scopes
31
+ []
32
+ end
33
+
34
+ protected
35
+
36
+ def compute_type(type_name)
37
+ if type_name.match(/^::/)
38
+ # If the type is prefixed with a scope operator then we assume that
39
+ # the type_name is an absolute reference.
40
+ ActiveSupport::Dependencies.constantize(type_name)
41
+ else
42
+ # Build a list of candidates to search for
43
+ candidates = []
44
+ name.scan(/::|$/) { candidates.unshift "#{$`}::#{type_name}" }
45
+ candidates << type_name
46
+
47
+ candidates.each do |candidate|
48
+ begin
49
+ constant = ActiveSupport::Dependencies.constantize(candidate)
50
+ return constant if candidate == constant.to_s
51
+ # We don't want to swallow NoMethodError < NameError errors
52
+ rescue NoMethodError
53
+ raise
54
+ rescue NameError
55
+ end
56
+ end
57
+
58
+ raise NameError.new("uninitialized constant #{candidates.first}", candidates.first)
59
+ end
60
+ end
61
+ end
62
+
63
+ # use by association accessor
64
+ def association(name) #:nodoc:
65
+ association = association_instance_get(name)
66
+
67
+ if association.nil?
68
+ reflection = self.class.reflect_on_association(name)
69
+ if reflection.options[:active_model]
70
+ association = ActiveRecord::Associations::HasManyForActiveModelAssociation.new(self, reflection)
71
+ else
72
+ association = reflection.association_class.new(self, reflection)
73
+ end
74
+ association_instance_set(name, association)
75
+ end
76
+
77
+ association
78
+ end
79
+
80
+ def read_attribute(name)
81
+ send(name)
82
+ end
83
+ alias :_read_attribute :read_attribute
84
+
85
+ # dummy
86
+ def new_record?
87
+ false
88
+ end
89
+
90
+ private
91
+
92
+ # override
93
+ def validate_collection_association(reflection)
94
+ if association = association_instance_get(reflection.name)
95
+ if records = associated_records_to_validate_or_save(association, false, reflection.options[:autosave])
96
+ records.each { |record| association_valid?(reflection, record) }
97
+ end
98
+ end
99
+ end
100
+
101
+ # use in Rails internal
102
+ def association_instance_get(name)
103
+ @association_cache[name]
104
+ end
105
+
106
+ # use in Rails internal
107
+ def association_instance_set(name, association)
108
+ @association_cache[name] = association
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,7 @@
1
+ module ActiveModel::Associations
2
+ class Railtie < ::Rails::Railtie #:nodoc:
3
+ initializer 'activemodel-associations' do |_|
4
+ ActiveModel::Associations::Hooks.init
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module ActiveModel
2
+ module Associations
3
+ VERSION = "0.2.0"
4
+ end
5
+ end
@@ -0,0 +1,52 @@
1
+ require 'active_model/associations/initialize_extension'
2
+ require 'active_model/associations/active_record_reflection'
3
+ require 'active_model/associations/autosave_association'
4
+ require 'active_model/associations/override_methods'
5
+ require 'active_record/associations/builder/has_many_for_active_model'
6
+ require 'active_record/associations/has_many_for_active_model_association'
7
+ require 'active_support/core_ext/module'
8
+
9
+ module ActiveModel
10
+ module Associations
11
+ extend ActiveSupport::Concern
12
+
13
+ include InitializeExtension
14
+ include AutosaveAssociation
15
+ include ActiveRecordReflection
16
+ include OverrideMethods
17
+
18
+ included do
19
+ mattr_accessor :belongs_to_required_by_default, instance_accessor: false
20
+ end
21
+
22
+ module ClassMethods
23
+ # define association like ActiveRecord
24
+ def belongs_to(name, scope = nil, options = {})
25
+ reflection = ActiveRecord::Associations::Builder::BelongsTo.build(self, name, scope, options)
26
+ ActiveRecord::Reflection.add_reflection self, name, reflection
27
+ end
28
+
29
+ # define association like ActiveRecord
30
+ def has_many(name, scope = nil, options = {}, &extension)
31
+ options.reverse_merge!(active_model: true, target_ids: "#{name.to_s.singularize}_ids")
32
+ if scope.is_a?(Hash)
33
+ options.merge!(scope)
34
+ scope = nil
35
+ end
36
+
37
+ reflection = ActiveRecord::Associations::Builder::HasManyForActiveModel.build(self, name, scope, options, &extension)
38
+ ActiveRecord::Reflection.add_reflection self, name, reflection
39
+
40
+ mixin = generated_association_methods
41
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
42
+ def #{options[:target_ids]}=(other_ids)
43
+ @#{options[:target_ids]} = other_ids
44
+ association(:#{name}).reset
45
+ association(:#{name}).reset_scope
46
+ @#{options[:target_ids]}
47
+ end
48
+ CODE
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,21 @@
1
+ module ActiveRecord::Associations::Builder
2
+ class HasManyForActiveModel < HasMany
3
+ if ActiveRecord.version >= Gem::Version.new("5.0.0.beta")
4
+ AR_CALLBACK_METHODS = %i(define_callback before_validation after_validation before_save after_save before_update after_update)
5
+
6
+ def self.valid_options(_options)
7
+ super + [:active_model, :target_ids] - [:through, :dependent, :source, :source_type, :counter_cache, :as]
8
+ end
9
+
10
+ def self.define_callbacks(model, reflection)
11
+ if AR_CALLBACK_METHODS.all? { |meth| self.respond_to?(meth) }
12
+ super
13
+ end
14
+ end
15
+ else
16
+ def valid_options
17
+ super + [:active_model, :target_ids] - [:through, :dependent, :source, :source_type, :counter_cache, :as]
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,72 @@
1
+ module ActiveRecord::Associations
2
+ class HasManyForActiveModelAssociation < HasManyAssociation
3
+ # remove conditions: owner.new_record?, foreign_key_present?
4
+ def find_target?
5
+ !loaded? && klass
6
+ end
7
+
8
+ # no dependent action
9
+ def null_scope?
10
+ false
11
+ end
12
+
13
+ # not support counter_cache
14
+ def empty?
15
+ if loaded?
16
+ size.zero?
17
+ else
18
+ @target.blank? && !scope.exists?
19
+ end
20
+ end
21
+
22
+ # full replace simplely
23
+ def replace(other_array)
24
+ original_target = load_target.dup
25
+ other_array.each { |val| raise_on_type_mismatch!(val) }
26
+ target_ids = reflection.options[:target_ids]
27
+ owner[target_ids] = other_array.map(&:id)
28
+
29
+ old_records = original_target - other_array
30
+ old_records.each do |record|
31
+ @target.delete(record)
32
+ end
33
+
34
+ other_array.each do |record|
35
+ if index = @target.index(record)
36
+ @target[index] = record
37
+ else
38
+ @target << record
39
+ end
40
+ end
41
+ end
42
+
43
+ # no need transaction
44
+ def concat(*records)
45
+ load_target
46
+ flatten_records = records.flatten
47
+ flatten_records.each { |val| raise_on_type_mismatch!(val) }
48
+ target_ids = reflection.options[:target_ids]
49
+ owner[target_ids] ||= []
50
+ owner[target_ids].concat(flatten_records.map(&:id))
51
+
52
+ flatten_records.each do |record|
53
+ if index = @target.index(record)
54
+ @target[index] = record
55
+ else
56
+ @target << record
57
+ end
58
+ end
59
+
60
+ target
61
+ end
62
+
63
+ private
64
+
65
+ def get_records
66
+ return scope.to_a if reflection.scope_chain.any?(&:any?)
67
+
68
+ target_ids = reflection.options[:target_ids]
69
+ klass.where(id: owner[target_ids]).to_a
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,15 @@
1
+ require "active_model"
2
+ require "active_record"
3
+ require "active_support"
4
+ require "active_model/associations"
5
+ require "active_model/associations/hooks"
6
+
7
+ # Load Railtie
8
+ begin
9
+ require "rails"
10
+ rescue LoadError
11
+ end
12
+
13
+ if defined?(Rails)
14
+ require "active_model/associations/railtie"
15
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module EacRailsUtils
6
+ module Models
7
+ class Tableless
8
+ module Attributes
9
+ common_concern
10
+
11
+ def attributes=(values)
12
+ super(build_attributes(values))
13
+ end
14
+
15
+ # need hash like accessor, used internal Rails
16
+ def [](attr)
17
+ send(attr)
18
+ end
19
+
20
+ # need hash like accessor, used internal Rails
21
+ def []=(attr, value)
22
+ send("#{attr}=", value)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EacRailsUtils
4
+ module Models
5
+ class Tableless
6
+ class BuildAttributes
7
+ acts_as_instance_method
8
+ DATE_TIME_FIELDS = %i[year month day hour min sec].freeze
9
+
10
+ def initialize(model_class, values)
11
+ @model_class = model_class
12
+ @values = {}
13
+ values.each { |k, v| add(k, v) }
14
+ end
15
+
16
+ def result
17
+ @values
18
+ end
19
+
20
+ private
21
+
22
+ def add(key, value)
23
+ array_attr = parse_array_attr_key(key)
24
+ if array_attr
25
+ array_value_set(array_attr, value)
26
+ else
27
+ @values[key] = value
28
+ end
29
+ end
30
+
31
+ def parse_array_attr_key(key)
32
+ m = /\A(.+)\(([0-9]+)(.)\)\z/.match(key)
33
+ return unless m
34
+
35
+ ::OpenStruct.new(key: m[1], index: m[2].to_i - 1, converter: array_value_converter(m[3]))
36
+ end
37
+
38
+ def array_value_set(array_attr, value)
39
+ @values[array_attr.key] ||= {}
40
+ @values[array_attr.key].merge!(
41
+ DATE_TIME_FIELDS[array_attr.index] => value.send(array_attr.converter)
42
+ )
43
+ end
44
+
45
+ def array_value_converter(str_type)
46
+ case str_type
47
+ when 'i'
48
+ 'to_i'
49
+ else
50
+ raise "Unknown array type: \"#{str_type}\""
51
+ end
52
+ end
53
+
54
+ def date_time_attribute?(key)
55
+ attr = @model_class.attributes[key]
56
+ return false unless attr
57
+
58
+ raise attr.to_s
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module EacRailsUtils
6
+ module Models
7
+ class Tableless
8
+ module Columns
9
+ common_concern
10
+
11
+ class_methods do
12
+ def columns
13
+ attribute_set.each.to_a
14
+ end
15
+
16
+ def columns_names
17
+ columns.map(&:name)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -10,98 +10,15 @@ module EacRailsUtils
10
10
  include Virtus.model
11
11
  include ActiveModel::Associations
12
12
 
13
- class << self
14
- def columns
15
- attribute_set.each.to_a
16
- end
17
-
18
- def columns_names
19
- columns.map(&:name)
20
- end
21
- end
22
-
23
13
  def initialize(values = {})
24
14
  super(build_attributes(values))
25
15
  end
26
16
 
27
- def attributes=(values)
28
- super(build_attributes(values))
29
- end
30
-
31
- # need hash like accessor, used internal Rails
32
- def [](attr)
33
- send(attr)
34
- end
35
-
36
- # need hash like accessor, used internal Rails
37
- def []=(attr, value)
38
- send("#{attr}=", value)
39
- end
40
-
41
17
  def save!
42
18
  save || raise("#{self.class}.save failed: #{errors.messages}")
43
19
  end
44
20
 
45
- private
46
-
47
- def build_attributes(values)
48
- AttributesBuilder.new(self.class, values).to_attributes
49
- end
50
-
51
- class AttributesBuilder
52
- DATE_TIME_FIELDS = %i[year month day hour min sec].freeze
53
-
54
- def initialize(model_class, values)
55
- @model_class = model_class
56
- @values = {}
57
- values.each { |k, v| add(k, v) }
58
- end
59
-
60
- def to_attributes
61
- @values
62
- end
63
-
64
- private
65
-
66
- def add(key, value)
67
- array_attr = parse_array_attr_key(key)
68
- if array_attr
69
- array_value_set(array_attr, value)
70
- else
71
- @values[key] = value
72
- end
73
- end
74
-
75
- def parse_array_attr_key(key)
76
- m = /\A(.+)\(([0-9]+)(.)\)\z/.match(key)
77
- return unless m
78
-
79
- ::OpenStruct.new(key: m[1], index: m[2].to_i - 1, converter: array_value_converter(m[3]))
80
- end
81
-
82
- def array_value_set(array_attr, value)
83
- @values[array_attr.key] ||= {}
84
- @values[array_attr.key].merge!(
85
- DATE_TIME_FIELDS[array_attr.index] => value.send(array_attr.converter)
86
- )
87
- end
88
-
89
- def array_value_converter(str_type)
90
- case str_type
91
- when 'i'
92
- 'to_i'
93
- else
94
- raise "Unknown array type: \"#{str_type}\""
95
- end
96
- end
97
-
98
- def date_time_attribute?(key)
99
- attr = @model_class.attributes[key]
100
- return false unless attr
101
-
102
- raise attr.to_s
103
- end
104
- end
21
+ require_sub __FILE__, require_mode: :kernel, include_modules: :include
105
22
  end
106
23
  end
107
24
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EacRailsUtils
4
- VERSION = '0.19.0'
4
+ VERSION = '0.20.0'
5
5
  end
metadata CHANGED
@@ -1,29 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eac_rails_utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.19.0
4
+ version: 0.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - E.A.C.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-11 00:00:00.000000000 Z
11
+ date: 2023-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: activemodel-associations
14
+ name: activemodel
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0.2'
19
+ version: '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: '0.2'
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bootstrap-sass
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -50,20 +64,14 @@ dependencies:
50
64
  requirements:
51
65
  - - "~>"
52
66
  - !ruby/object:Gem::Version
53
- version: '0.117'
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- version: 0.117.1
67
+ version: '0.118'
57
68
  type: :runtime
58
69
  prerelease: false
59
70
  version_requirements: !ruby/object:Gem::Requirement
60
71
  requirements:
61
72
  - - "~>"
62
73
  - !ruby/object:Gem::Version
63
- version: '0.117'
64
- - - ">="
65
- - !ruby/object:Gem::Version
66
- version: 0.117.1
74
+ version: '0.118'
67
75
  - !ruby/object:Gem::Dependency
68
76
  name: htmlbeautifier
69
77
  requirement: !ruby/object:Gem::Requirement
@@ -212,6 +220,18 @@ files:
212
220
  - config/initializers/json.rb
213
221
  - config/locales/en.yml
214
222
  - config/locales/pt-BR.yml
223
+ - lib/active_model/associations.rb
224
+ - lib/active_model/associations/active_record_reflection.rb
225
+ - lib/active_model/associations/association_scope_extension.rb
226
+ - lib/active_model/associations/autosave_association.rb
227
+ - lib/active_model/associations/hooks.rb
228
+ - lib/active_model/associations/initialize_extension.rb
229
+ - lib/active_model/associations/override_methods.rb
230
+ - lib/active_model/associations/railtie.rb
231
+ - lib/active_model/associations/version.rb
232
+ - lib/active_record/associations/builder/has_many_for_active_model.rb
233
+ - lib/active_record/associations/has_many_for_active_model_association.rb
234
+ - lib/activemodel/associations.rb
215
235
  - lib/eac_rails_utils.rb
216
236
  - lib/eac_rails_utils/engine.rb
217
237
  - lib/eac_rails_utils/engine_helper.rb
@@ -220,6 +240,9 @@ files:
220
240
  - lib/eac_rails_utils/models/fetch_errors.rb
221
241
  - lib/eac_rails_utils/models/inequality_queries.rb
222
242
  - lib/eac_rails_utils/models/tableless.rb
243
+ - lib/eac_rails_utils/models/tableless/attributes.rb
244
+ - lib/eac_rails_utils/models/tableless/build_attributes.rb
245
+ - lib/eac_rails_utils/models/tableless/columns.rb
223
246
  - lib/eac_rails_utils/models/test_utils.rb
224
247
  - lib/eac_rails_utils/models/validations.rb
225
248
  - lib/eac_rails_utils/patches.rb