eac_rails_utils 0.19.0 → 0.21.0
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 +4 -4
- data/lib/active_record/associations/builder/has_many_for_active_model.rb +21 -0
- data/lib/active_record/associations/has_many_for_active_model_association.rb +72 -0
- data/lib/activemodel/associations.rb +15 -0
- data/lib/eac_rails_utils/models/tableless/attributes.rb +27 -0
- data/lib/eac_rails_utils/models/tableless/build_attributes.rb +63 -0
- data/lib/eac_rails_utils/models/tableless/columns.rb +23 -0
- data/lib/eac_rails_utils/models/tableless/strict_loading.rb +25 -0
- data/lib/eac_rails_utils/models/tableless.rb +2 -85
- data/lib/eac_rails_utils/models/tableless_associations/active_record_reflection.rb +38 -0
- data/lib/eac_rails_utils/models/tableless_associations/association_scope_extension.rb +23 -0
- data/lib/eac_rails_utils/models/tableless_associations/autosave_association.rb +12 -0
- data/lib/eac_rails_utils/models/tableless_associations/hooks.rb +10 -0
- data/lib/eac_rails_utils/models/tableless_associations/initialize_extension.rb +16 -0
- data/lib/eac_rails_utils/models/tableless_associations/override_methods.rb +111 -0
- data/lib/eac_rails_utils/models/tableless_associations/railtie.rb +7 -0
- data/lib/eac_rails_utils/models/tableless_associations/version.rb +5 -0
- data/lib/eac_rails_utils/models/tableless_associations.rb +54 -0
- data/lib/eac_rails_utils/patches/active_model_associations.rb +22 -20
- data/lib/eac_rails_utils/patches/rails_4.rb +1 -1
- data/lib/eac_rails_utils/patches/rails_5_2/active_model_association_method_fix.rb +1 -1
- data/lib/eac_rails_utils/patches/rails_5_2.rb +1 -1
- data/lib/eac_rails_utils/version.rb +1 -1
- metadata +22 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3aedeca11ee83d3ba78b7ed6e4018ec11ec5358279ee8aa60aeee9a704b67bc7
|
4
|
+
data.tar.gz: cf7618ee67289bbcfae473c46816562d43ed1054febf31982250b1f4c1db4184
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba22996dcb260db19cfc7ea31adf12da8f530220c2426178a50b8fbd50094040aa8bb140d83d7f81b9a1ea987f6c278f0f29c8e3d9793f52e29688e0020801c6
|
7
|
+
data.tar.gz: 538843dd71b2511945bede0711f03390c0620482643b7dd0beb5bbf39fae8a79dc31c723c0a3f318379dca0734d8433b1db3462dbb5f381e6b84a49c5c4a7bfd
|
@@ -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 "eac_rails_utils/models/tableless_associations"
|
5
|
+
require "eac_rails_utils/models/tableless_associations/hooks"
|
6
|
+
|
7
|
+
# Load Railtie
|
8
|
+
begin
|
9
|
+
require "rails"
|
10
|
+
rescue LoadError
|
11
|
+
end
|
12
|
+
|
13
|
+
if defined?(Rails)
|
14
|
+
require "eac_rails_utils/models/tableless_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
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'eac_ruby_utils/core_ext'
|
4
|
+
|
5
|
+
module EacRailsUtils
|
6
|
+
module Models
|
7
|
+
class Tableless
|
8
|
+
# For Rails >= '6.1'.
|
9
|
+
module StrictLoading
|
10
|
+
common_concern
|
11
|
+
|
12
|
+
class_methods do
|
13
|
+
def strict_loading?
|
14
|
+
false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [Boolean]
|
19
|
+
def strict_loading?
|
20
|
+
self.class.strict_loading?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -8,100 +8,17 @@ module EacRailsUtils
|
|
8
8
|
class Tableless
|
9
9
|
include ActiveModel::Model
|
10
10
|
include Virtus.model
|
11
|
-
include
|
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
|
11
|
+
include EacRailsUtils::Models::TablelessAssociations
|
22
12
|
|
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
|
-
|
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
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module EacRailsUtils::Models::TablelessAssociations
|
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 EacRailsUtils::Models::TablelessAssociations
|
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 EacRailsUtils::Models::TablelessAssociations
|
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 EacRailsUtils::Models::TablelessAssociations
|
2
|
+
module Hooks
|
3
|
+
def self.init
|
4
|
+
ActiveSupport.on_load(:active_record) do
|
5
|
+
require 'eac_rails_utils/models/tableless_associations/association_scope_extension'
|
6
|
+
ActiveRecord::Associations::AssociationScope.send(:prepend, EacRailsUtils::Models::TablelessAssociations::AssociationScopeExtension)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module EacRailsUtils::Models::TablelessAssociations
|
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 EacRailsUtils::Models::TablelessAssociations
|
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,54 @@
|
|
1
|
+
require 'eac_rails_utils/models/tableless_associations/initialize_extension'
|
2
|
+
require 'eac_rails_utils/models/tableless_associations/active_record_reflection'
|
3
|
+
require 'eac_rails_utils/models/tableless_associations/autosave_association'
|
4
|
+
require 'eac_rails_utils/models/tableless_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 EacRailsUtils
|
10
|
+
module Models
|
11
|
+
module TablelessAssociations
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
|
14
|
+
include InitializeExtension
|
15
|
+
include AutosaveAssociation
|
16
|
+
include ActiveRecordReflection
|
17
|
+
include OverrideMethods
|
18
|
+
|
19
|
+
included do
|
20
|
+
mattr_accessor :belongs_to_required_by_default, instance_accessor: false
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
# define association like ActiveRecord
|
25
|
+
def belongs_to(name, scope = nil, options = {})
|
26
|
+
reflection = ActiveRecord::Associations::Builder::BelongsTo.build(self, name, scope, options)
|
27
|
+
ActiveRecord::Reflection.add_reflection self, name, reflection
|
28
|
+
end
|
29
|
+
|
30
|
+
# define association like ActiveRecord
|
31
|
+
def has_many(name, scope = nil, options = {}, &extension)
|
32
|
+
options.reverse_merge!(active_model: true, target_ids: "#{name.to_s.singularize}_ids")
|
33
|
+
if scope.is_a?(Hash)
|
34
|
+
options.merge!(scope)
|
35
|
+
scope = nil
|
36
|
+
end
|
37
|
+
|
38
|
+
reflection = ActiveRecord::Associations::Builder::HasManyForActiveModel.build(self, name, scope, options, &extension)
|
39
|
+
ActiveRecord::Reflection.add_reflection self, name, reflection
|
40
|
+
|
41
|
+
mixin = generated_association_methods
|
42
|
+
mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
43
|
+
def #{options[:target_ids]}=(other_ids)
|
44
|
+
@#{options[:target_ids]} = other_ids
|
45
|
+
association(:#{name}).reset
|
46
|
+
association(:#{name}).reset_scope
|
47
|
+
@#{options[:target_ids]}
|
48
|
+
end
|
49
|
+
CODE
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -4,30 +4,32 @@ require 'activemodel/associations'
|
|
4
4
|
require 'eac_rails_utils/patches/rails_4'
|
5
5
|
require 'eac_rails_utils/patches/rails_5_2'
|
6
6
|
|
7
|
-
module
|
8
|
-
module
|
9
|
-
module
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
7
|
+
module EacRailsUtils
|
8
|
+
module Models
|
9
|
+
module TablelessAssociations
|
10
|
+
module Hooks
|
11
|
+
class << self
|
12
|
+
def init
|
13
|
+
init_rails_4 if ::EacRailsUtils::Patches::Rails4.enabled?
|
14
|
+
init_rails_5_2 if ::EacRailsUtils::Patches::Rails52.enabled?
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
def init_rails_4
|
18
|
+
ActiveSupport.on_load(:active_record) do
|
19
|
+
ActiveRecord::Associations::AssociationScope.prepend(
|
20
|
+
::EacRailsUtils::Patches::Rails4::ActiveRecordAssociationsAssociationScope
|
21
|
+
)
|
22
|
+
end
|
21
23
|
end
|
22
|
-
end
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
def init_rails_5_2
|
26
|
+
rails_5_2_fix_activemodel_associations_methods
|
27
|
+
end
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
def rails_5_2_fix_activemodel_associations_methods
|
30
|
+
%i[belongs_to has_many].each do |method|
|
31
|
+
::EacRailsUtils::Patches::Rails52::ActiveModelAssociationMethodFix.new(method)
|
32
|
+
end
|
31
33
|
end
|
32
34
|
end
|
33
35
|
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eac_rails_utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.21.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-
|
11
|
+
date: 2023-07-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: activemodel-associations
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0.2'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0.2'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: bootstrap-sass
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,20 +36,20 @@ dependencies:
|
|
50
36
|
requirements:
|
51
37
|
- - "~>"
|
52
38
|
- !ruby/object:Gem::Version
|
53
|
-
version: '0.
|
39
|
+
version: '0.118'
|
54
40
|
- - ">="
|
55
41
|
- !ruby/object:Gem::Version
|
56
|
-
version: 0.
|
42
|
+
version: 0.118.1
|
57
43
|
type: :runtime
|
58
44
|
prerelease: false
|
59
45
|
version_requirements: !ruby/object:Gem::Requirement
|
60
46
|
requirements:
|
61
47
|
- - "~>"
|
62
48
|
- !ruby/object:Gem::Version
|
63
|
-
version: '0.
|
49
|
+
version: '0.118'
|
64
50
|
- - ">="
|
65
51
|
- !ruby/object:Gem::Version
|
66
|
-
version: 0.
|
52
|
+
version: 0.118.1
|
67
53
|
- !ruby/object:Gem::Dependency
|
68
54
|
name: htmlbeautifier
|
69
55
|
requirement: !ruby/object:Gem::Requirement
|
@@ -212,6 +198,9 @@ files:
|
|
212
198
|
- config/initializers/json.rb
|
213
199
|
- config/locales/en.yml
|
214
200
|
- config/locales/pt-BR.yml
|
201
|
+
- lib/active_record/associations/builder/has_many_for_active_model.rb
|
202
|
+
- lib/active_record/associations/has_many_for_active_model_association.rb
|
203
|
+
- lib/activemodel/associations.rb
|
215
204
|
- lib/eac_rails_utils.rb
|
216
205
|
- lib/eac_rails_utils/engine.rb
|
217
206
|
- lib/eac_rails_utils/engine_helper.rb
|
@@ -220,6 +209,19 @@ files:
|
|
220
209
|
- lib/eac_rails_utils/models/fetch_errors.rb
|
221
210
|
- lib/eac_rails_utils/models/inequality_queries.rb
|
222
211
|
- lib/eac_rails_utils/models/tableless.rb
|
212
|
+
- lib/eac_rails_utils/models/tableless/attributes.rb
|
213
|
+
- lib/eac_rails_utils/models/tableless/build_attributes.rb
|
214
|
+
- lib/eac_rails_utils/models/tableless/columns.rb
|
215
|
+
- lib/eac_rails_utils/models/tableless/strict_loading.rb
|
216
|
+
- lib/eac_rails_utils/models/tableless_associations.rb
|
217
|
+
- lib/eac_rails_utils/models/tableless_associations/active_record_reflection.rb
|
218
|
+
- lib/eac_rails_utils/models/tableless_associations/association_scope_extension.rb
|
219
|
+
- lib/eac_rails_utils/models/tableless_associations/autosave_association.rb
|
220
|
+
- lib/eac_rails_utils/models/tableless_associations/hooks.rb
|
221
|
+
- lib/eac_rails_utils/models/tableless_associations/initialize_extension.rb
|
222
|
+
- lib/eac_rails_utils/models/tableless_associations/override_methods.rb
|
223
|
+
- lib/eac_rails_utils/models/tableless_associations/railtie.rb
|
224
|
+
- lib/eac_rails_utils/models/tableless_associations/version.rb
|
223
225
|
- lib/eac_rails_utils/models/test_utils.rb
|
224
226
|
- lib/eac_rails_utils/models/validations.rb
|
225
227
|
- lib/eac_rails_utils/patches.rb
|