eac_rails_utils 0.18.0 → 0.20.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/app/helpers/eac_rails_utils/data_table_helper/column.rb +26 -23
- data/app/helpers/eac_rails_utils/data_table_helper/column_node.rb +32 -0
- data/app/helpers/eac_rails_utils/data_table_helper/data_table/value_cell.rb +30 -0
- data/app/helpers/eac_rails_utils/data_table_helper/data_table.rb +24 -16
- data/app/helpers/eac_rails_utils/data_table_helper/setup.rb +5 -2
- data/lib/active_model/associations/active_record_reflection.rb +38 -0
- data/lib/active_model/associations/association_scope_extension.rb +23 -0
- data/lib/active_model/associations/autosave_association.rb +12 -0
- data/lib/active_model/associations/hooks.rb +10 -0
- data/lib/active_model/associations/initialize_extension.rb +16 -0
- data/lib/active_model/associations/override_methods.rb +111 -0
- data/lib/active_model/associations/railtie.rb +7 -0
- data/lib/active_model/associations/version.rb +5 -0
- data/lib/active_model/associations.rb +52 -0
- 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.rb +1 -84
- data/lib/eac_rails_utils/version.rb +1 -1
- metadata +40 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 424e322548e7f55ef6044d3c7e4339cd8336b272604d40678c7016b218b69494
|
4
|
+
data.tar.gz: 28dd2d2a83760c49bbb30e0210e2c4aa096be75a77f7edf720cff7700f2cce9c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c7ebba5d2e7736bcefdef37c3a015130047b12ff880b2862e871b3cbd7cd1e9c9ca5bde9ab7d51def8215d4c9049bfeb2cb1a9c2ed072011dd5402e850135d59
|
7
|
+
data.tar.gz: cc57e040cca6a24be309903034e74d7ff63394efd1090191f0c90b8620404ec2f31594fa4d166b40a872aa67481486c6093713722998cb77ad5d04e1298e6cea
|
@@ -1,48 +1,51 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'eac_ruby_utils/core_ext'
|
4
|
+
|
3
5
|
module EacRailsUtils
|
4
6
|
module DataTableHelper
|
5
7
|
class Column
|
6
8
|
EMPTY_VALUE = '-'
|
7
9
|
|
8
|
-
|
10
|
+
common_constructor :args, :block
|
11
|
+
|
12
|
+
# @return [String]
|
13
|
+
def label
|
14
|
+
args[0]
|
15
|
+
end
|
9
16
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
@block = block
|
17
|
+
# @return [String]
|
18
|
+
def path
|
19
|
+
args[1].to_s.split('.')
|
14
20
|
end
|
15
21
|
|
16
22
|
def record_value(record)
|
17
|
-
v =
|
23
|
+
v = ::EacRailsUtils::DataTableHelper::ColumnNode.new(record, path).value
|
18
24
|
if v.present?
|
19
|
-
|
25
|
+
block ? block.call(v) : v
|
20
26
|
else
|
21
27
|
EMPTY_VALUE
|
22
28
|
end
|
23
29
|
end
|
24
30
|
|
25
|
-
|
31
|
+
# @param attribute [Symbol]
|
32
|
+
# @param value [Proc, Object]
|
33
|
+
# @return [self]
|
34
|
+
def value_cell(attribute, value = nil, &block)
|
35
|
+
value_cell_attributes[attribute.to_sym] = block.if_present(value)
|
26
36
|
|
27
|
-
|
28
|
-
return node if subpath.empty?
|
37
|
+
self
|
29
38
|
end
|
30
39
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
def value
|
38
|
-
return @node if @node.nil? || @path.empty?
|
40
|
+
# @return [Hash]
|
41
|
+
def value_cell_attributes
|
42
|
+
@value_cell_attributes ||= {}
|
43
|
+
end
|
39
44
|
|
40
|
-
|
41
|
-
n = subpath.shift
|
42
|
-
return Node.new(@node.send(n), subpath).value if @node.respond_to?(n)
|
45
|
+
private
|
43
46
|
|
44
|
-
|
45
|
-
|
47
|
+
def node_value(node, subpath)
|
48
|
+
return node if subpath.empty?
|
46
49
|
end
|
47
50
|
end
|
48
51
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'eac_ruby_utils/core_ext'
|
4
|
+
|
5
|
+
module EacRailsUtils
|
6
|
+
module DataTableHelper
|
7
|
+
class ColumnNode
|
8
|
+
common_constructor :node, :path
|
9
|
+
|
10
|
+
# @return [Boolean]
|
11
|
+
def ended?
|
12
|
+
node.nil? || path.empty?
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [Object]
|
16
|
+
def value
|
17
|
+
ended? ? node : child_value
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# @return [Object]
|
23
|
+
def child_value
|
24
|
+
subpath = path.dup
|
25
|
+
n = subpath.shift
|
26
|
+
return self.class.new(node.send(n), subpath).value if node.respond_to?(n)
|
27
|
+
|
28
|
+
raise "Instance of #{node.class} does not respond to #{n}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'eac_ruby_utils/core_ext'
|
4
|
+
|
5
|
+
module EacRailsUtils
|
6
|
+
module DataTableHelper
|
7
|
+
class DataTable
|
8
|
+
class ValueCell
|
9
|
+
enable_method_class
|
10
|
+
common_constructor :data_table, :column, :record
|
11
|
+
delegate :view, to: :data_table
|
12
|
+
|
13
|
+
# @return [ActiveSupport::SafeBuffer]
|
14
|
+
def result
|
15
|
+
view.content_tag('td', column.record_value(record), tag_attributes)
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [Object]
|
19
|
+
def tag_attribute_value(value)
|
20
|
+
value.is_a?(::Proc) ? value.call(record) : value
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Hash]
|
24
|
+
def tag_attributes
|
25
|
+
column.value_cell_attributes.map { |k, v| [k, tag_attribute_value(v)] }.to_h
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,17 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'eac_ruby_utils/core_ext'
|
4
|
+
|
3
5
|
module EacRailsUtils
|
4
6
|
module DataTableHelper
|
5
7
|
class DataTable
|
6
|
-
|
7
|
-
@view = view
|
8
|
-
@dataset = dataset
|
9
|
-
@setup = ::EacRailsUtils::DataTableHelper::Setup.new
|
10
|
-
yield(@setup)
|
11
|
-
end
|
8
|
+
common_constructor :view, :dataset, :setup_block, block_arg: true
|
12
9
|
|
13
10
|
def output
|
14
|
-
|
11
|
+
view.content_tag(:table, id: id) do
|
15
12
|
head << body
|
16
13
|
end << script
|
17
14
|
end
|
@@ -19,29 +16,29 @@ module EacRailsUtils
|
|
19
16
|
private
|
20
17
|
|
21
18
|
def head
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
view.content_tag(:thead) do
|
20
|
+
view.content_tag(:tr) do
|
21
|
+
view.safe_join(setup.columns.map { |c| view.content_tag('th', c.label) })
|
25
22
|
end
|
26
23
|
end
|
27
24
|
end
|
28
25
|
|
29
26
|
def body
|
30
|
-
|
31
|
-
|
27
|
+
view.content_tag(:tbody) do
|
28
|
+
view.safe_join(dataset.map { |r| row(r) })
|
32
29
|
end
|
33
30
|
end
|
34
31
|
|
35
32
|
def row(record)
|
36
|
-
|
37
|
-
|
38
|
-
|
33
|
+
view.content_tag(:tr) do
|
34
|
+
view.safe_join(
|
35
|
+
setup.columns.map { |c| value_cell(c, record) << "\n" }
|
39
36
|
)
|
40
37
|
end << "\n"
|
41
38
|
end
|
42
39
|
|
43
40
|
def script
|
44
|
-
|
41
|
+
view.javascript_tag <<~JS_CODE
|
45
42
|
$(document).ready(function () {
|
46
43
|
$('##{id}').DataTable({
|
47
44
|
paging: #{@setup.paging ? 'true' : 'false'}
|
@@ -53,6 +50,17 @@ module EacRailsUtils
|
|
53
50
|
def id
|
54
51
|
@id ||= SecureRandom.hex(32)
|
55
52
|
end
|
53
|
+
|
54
|
+
# @return [EacRailsUtils::DataTableHelper::Setup]
|
55
|
+
def setup
|
56
|
+
@setup ||= begin
|
57
|
+
r = ::EacRailsUtils::DataTableHelper::Setup.new
|
58
|
+
setup_block.call(r)
|
59
|
+
r
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
require_sub __FILE__, require_mode: :kernel
|
56
64
|
end
|
57
65
|
end
|
58
66
|
end
|
@@ -11,8 +11,11 @@ module EacRailsUtils
|
|
11
11
|
@paging = true
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
# @return [EacRailsUtils::DataTableHelper::Column]
|
15
|
+
def column(*args, &block)
|
16
|
+
column = ::EacRailsUtils::DataTableHelper::Column.new(args, block)
|
17
|
+
@columns << column
|
18
|
+
column
|
16
19
|
end
|
17
20
|
end
|
18
21
|
end
|
@@ -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,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
|
-
|
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
|
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.
|
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-
|
11
|
+
date: 2023-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name: activemodel
|
14
|
+
name: activemodel
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0
|
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
|
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.
|
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.
|
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
|
@@ -193,7 +201,9 @@ files:
|
|
193
201
|
- app/helpers/eac_rails_utils/common_form_helper/form_builder/year_month_field.rb
|
194
202
|
- app/helpers/eac_rails_utils/data_table_helper.rb
|
195
203
|
- app/helpers/eac_rails_utils/data_table_helper/column.rb
|
204
|
+
- app/helpers/eac_rails_utils/data_table_helper/column_node.rb
|
196
205
|
- app/helpers/eac_rails_utils/data_table_helper/data_table.rb
|
206
|
+
- app/helpers/eac_rails_utils/data_table_helper/data_table/value_cell.rb
|
197
207
|
- app/helpers/eac_rails_utils/data_table_helper/setup.rb
|
198
208
|
- app/helpers/eac_rails_utils/formatter_helper.rb
|
199
209
|
- app/helpers/eac_rails_utils/links_helper.rb
|
@@ -210,6 +220,18 @@ files:
|
|
210
220
|
- config/initializers/json.rb
|
211
221
|
- config/locales/en.yml
|
212
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
|
213
235
|
- lib/eac_rails_utils.rb
|
214
236
|
- lib/eac_rails_utils/engine.rb
|
215
237
|
- lib/eac_rails_utils/engine_helper.rb
|
@@ -218,6 +240,9 @@ files:
|
|
218
240
|
- lib/eac_rails_utils/models/fetch_errors.rb
|
219
241
|
- lib/eac_rails_utils/models/inequality_queries.rb
|
220
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
|
221
246
|
- lib/eac_rails_utils/models/test_utils.rb
|
222
247
|
- lib/eac_rails_utils/models/validations.rb
|
223
248
|
- lib/eac_rails_utils/patches.rb
|