activerecord-traits 1.0.3 → 1.1.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/README.md +4 -4
- data/lib/activerecord-traits.rb +22 -18
- data/lib/traits/association/essay_shortcuts.rb +1 -1
- data/lib/traits/association/members.rb +5 -5
- data/lib/traits/association/polymorphism.rb +5 -5
- data/lib/traits/association.rb +4 -4
- data/lib/traits/attribute/essay_shortcuts.rb +1 -1
- data/lib/traits/attribute/inheritance.rb +1 -2
- data/lib/traits/attribute/key.rb +2 -2
- data/lib/traits/attribute/naming.rb +1 -1
- data/lib/traits/attribute/querying.rb +1 -1
- data/lib/traits/attribute.rb +6 -6
- data/lib/traits/descendants_listing.rb +16 -18
- data/lib/traits/list.rb +6 -0
- data/lib/traits/model/essay_shortcuts.rb +1 -1
- data/lib/traits/model/inheritance.rb +14 -20
- data/lib/traits/model/naming.rb +2 -2
- data/lib/traits/model/polymorphism.rb +2 -4
- data/lib/traits/model/querying.rb +5 -5
- data/lib/traits/model.rb +9 -12
- data/lib/traits/utilities.rb +27 -12
- data/lib/traits/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0bb790119c0be6db1ea5e9c0337b75db99a15ae3
|
4
|
+
data.tar.gz: ee1ed0dcf813732a24347107fe08ad1f5c1485ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c05ab3551ec4447387a98ffe3dbd2a5832776de6d6b7d8e767301524b8a9a5e3f8ad640401d8496576e56efc515c0380aa31b5f4a0ccb93d31afe0cbf910457
|
7
|
+
data.tar.gz: 0972d63b3d70e44d32d5d3024e9767996bee2d618f43277b6e4f83632cf2def2e98613542450839efd60f880182cef96263d0814d82ba91a0e7d9035bbad17e4
|
data/README.md
CHANGED
@@ -32,7 +32,7 @@ API design is done in good and clear manner for best understanding.
|
|
32
32
|
end
|
33
33
|
|
34
34
|
Author.traits.associations[:articles].has_many? # => true
|
35
|
-
Author.traits.associations[:articles].
|
35
|
+
Author.traits.associations[:articles].to.active_record # => Article
|
36
36
|
Author.traits.associations[:articles].paired_through_polymorphism? # => true
|
37
37
|
|
38
38
|
Photo.traits.associations[:imageable].polymorphic? # => true
|
@@ -50,9 +50,9 @@ API design is done in good and clear manner for best understanding.
|
|
50
50
|
class VideoGame < Present
|
51
51
|
end
|
52
52
|
|
53
|
-
Present.traits.
|
54
|
-
Toy.traits.
|
55
|
-
Toy.traits.
|
53
|
+
Present.traits.inheritance_base? # => true
|
54
|
+
Toy.traits.inheritance_derived? # => true
|
55
|
+
Toy.traits.inheritance_chain # => [Present, Toy]
|
56
56
|
|
57
57
|
```
|
58
58
|
|
data/lib/activerecord-traits.rb
CHANGED
@@ -18,35 +18,39 @@ require 'traits/model'
|
|
18
18
|
require 'traits/list'
|
19
19
|
|
20
20
|
class ActiveRecord::Base
|
21
|
-
|
22
|
-
|
21
|
+
class << self
|
22
|
+
def traits
|
23
|
+
@traits ||= Traits::Model.new(self)
|
24
|
+
end
|
23
25
|
end
|
24
26
|
end
|
25
27
|
|
26
28
|
module Traits
|
27
29
|
extend Enumerable
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
-
|
31
|
+
class << self
|
32
|
+
def for(obj)
|
33
|
+
retrieve_active_record!(obj).traits
|
34
|
+
end
|
32
35
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
def each
|
37
|
+
active_record_descendants.each { |ar| yield(ar.traits) }
|
38
|
+
end
|
36
39
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
+
def all
|
41
|
+
each_with_object({}) do |traits, memo|
|
42
|
+
memo[traits.name] = traits
|
43
|
+
end
|
40
44
|
end
|
41
|
-
end
|
42
45
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
+
def each_attribute(&block)
|
47
|
+
each { |traits| traits.attributes.each(&block) }
|
48
|
+
end
|
46
49
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
+
def to_hash
|
51
|
+
each_with_object({}) do |traits, memo|
|
52
|
+
memo[traits.name] = traits.to_hash
|
53
|
+
end
|
50
54
|
end
|
51
55
|
end
|
52
56
|
end
|
@@ -5,12 +5,12 @@ module Traits
|
|
5
5
|
class Association
|
6
6
|
module Members
|
7
7
|
def from
|
8
|
-
@
|
8
|
+
@from_active_record.traits
|
9
9
|
end
|
10
10
|
|
11
11
|
# Returns the actual association establisher class
|
12
|
-
def
|
13
|
-
@
|
12
|
+
def from_active_record
|
13
|
+
@from_active_record
|
14
14
|
end
|
15
15
|
|
16
16
|
# Returns the actual associated class
|
@@ -18,12 +18,12 @@ module Traits
|
|
18
18
|
reflection.klass.traits unless polymorphic?
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
21
|
+
def to_active_record
|
22
22
|
reflection.klass unless polymorphic?
|
23
23
|
end
|
24
24
|
|
25
25
|
def self_to_self?
|
26
|
-
|
26
|
+
from_active_record == to_active_record
|
27
27
|
end
|
28
28
|
|
29
29
|
def to_hash
|
@@ -52,15 +52,15 @@ module Traits
|
|
52
52
|
if polymorphic?
|
53
53
|
classes = []
|
54
54
|
attr_name = attribute_name_for_polymorphic_type
|
55
|
-
this_class =
|
55
|
+
this_class = from_active_record
|
56
56
|
|
57
|
-
Traits.active_record_descendants.each do |
|
57
|
+
Traits.active_record_descendants.each do |active_record|
|
58
58
|
# Skip current model and models which are STI derived
|
59
|
-
next if
|
59
|
+
next if active_record <= this_class # Means is or derived from current model
|
60
60
|
|
61
|
-
|
61
|
+
active_record.traits.associations.each do |assoc|
|
62
62
|
if assoc.attribute_name_for_polymorphic_type == attr_name
|
63
|
-
classes << assoc.
|
63
|
+
classes << assoc.from_active_record
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
data/lib/traits/association.rb
CHANGED
@@ -30,9 +30,9 @@ module Traits
|
|
30
30
|
|
31
31
|
attr_reader :reflection
|
32
32
|
|
33
|
-
def initialize(
|
34
|
-
@
|
35
|
-
@reflection
|
33
|
+
def initialize(active_record, reflection)
|
34
|
+
@from_active_record = active_record
|
35
|
+
@reflection = reflection
|
36
36
|
end
|
37
37
|
|
38
38
|
def inspect
|
@@ -48,7 +48,7 @@ module Traits
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def validators
|
51
|
-
|
51
|
+
from_active_record.validators_on(name)
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
@@ -7,10 +7,9 @@ module Traits
|
|
7
7
|
def inheritance_type?
|
8
8
|
(model.inheritance_base? || model.inheritance_derived?) and name == model.inheritance_attribute.name
|
9
9
|
end
|
10
|
-
alias sti_type? inheritance_type?
|
11
10
|
|
12
11
|
def to_hash
|
13
|
-
super.merge!(
|
12
|
+
super.merge!(is_inheritance_type: inheritance_type?)
|
14
13
|
end
|
15
14
|
end
|
16
15
|
end
|
data/lib/traits/attribute/key.rb
CHANGED
@@ -6,13 +6,13 @@ module Traits
|
|
6
6
|
module Key
|
7
7
|
def primary_key?
|
8
8
|
column_definition.try(:primary) ||
|
9
|
-
|
9
|
+
active_record.primary_key == column_definition.name ||
|
10
10
|
type == :primary_key
|
11
11
|
end
|
12
12
|
|
13
13
|
def foreign_key?
|
14
14
|
attr_name = name
|
15
|
-
attr_translates =
|
15
|
+
attr_translates = active_record.attribute_features[attr_name].try(:translates_with_globalize?)
|
16
16
|
|
17
17
|
model.associations.any? do |assoc|
|
18
18
|
if assoc.belongs_to?
|
data/lib/traits/attribute.rb
CHANGED
@@ -24,24 +24,24 @@ module Traits
|
|
24
24
|
include Inheritance
|
25
25
|
include EssayShortcuts
|
26
26
|
|
27
|
-
attr_reader :
|
27
|
+
attr_reader :active_record, :column_definition
|
28
28
|
|
29
|
-
def initialize(
|
30
|
-
@
|
29
|
+
def initialize(active_record, column_definition)
|
30
|
+
@active_record = active_record
|
31
31
|
@column_definition = column_definition
|
32
32
|
end
|
33
33
|
|
34
34
|
def model
|
35
|
-
|
35
|
+
active_record.traits
|
36
36
|
end
|
37
37
|
|
38
38
|
# TODO Remove this
|
39
39
|
def regular?
|
40
|
-
!(key? ||
|
40
|
+
!(key? || inheritance_type? || polymorphic_type? || active_record_timestamp?)
|
41
41
|
end
|
42
42
|
|
43
43
|
def validators
|
44
|
-
|
44
|
+
active_record.validators_on(name)
|
45
45
|
end
|
46
46
|
|
47
47
|
def value_from(model_instance)
|
@@ -4,11 +4,11 @@
|
|
4
4
|
module Traits
|
5
5
|
module DescendantsListing
|
6
6
|
def active_record_descendants_loaded?
|
7
|
-
!!@
|
7
|
+
!!@active_record_descendants_loaded
|
8
8
|
end
|
9
9
|
|
10
10
|
def load_active_record_descendants!
|
11
|
-
@
|
11
|
+
@active_record_descendants_loaded ||= begin
|
12
12
|
# Railties are not necessary here
|
13
13
|
# Source: http://stackoverflow.com/questions/6497834/differences-between-railties-and-engines-in-ruby-on-rails-3
|
14
14
|
Rails::Engine.subclasses.map(&:instance).each { |i| i.eager_load! }
|
@@ -18,23 +18,22 @@ module Traits
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def invalidate_loaded_active_record_descendants!
|
21
|
-
@
|
22
|
-
@ar_descendants_loaded = false
|
21
|
+
@active_record_descendants_loaded = false
|
23
22
|
end
|
24
23
|
|
25
|
-
def active_record_descendants
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
24
|
+
def active_record_descendants(filter = true)
|
25
|
+
load_active_record_descendants!
|
26
|
+
ary = ActiveRecord::Base.descendants
|
27
|
+
ary.reject! { |ar| filter_active_record_descendant(ar) } if filter
|
28
|
+
ary
|
30
29
|
end
|
31
30
|
|
32
|
-
def
|
33
|
-
|
34
|
-
case
|
35
|
-
when Regexp then
|
36
|
-
when String then
|
37
|
-
when Class then
|
31
|
+
def filter_active_record_descendant(active_record)
|
32
|
+
active_record_filters.any? do |filter|
|
33
|
+
case filter
|
34
|
+
when Regexp then active_record.name =~ filter
|
35
|
+
when String then active_record.name == filter
|
36
|
+
when Class then active_record == filter
|
38
37
|
else false
|
39
38
|
end
|
40
39
|
end
|
@@ -43,10 +42,9 @@ module Traits
|
|
43
42
|
|
44
43
|
extend DescendantsListing
|
45
44
|
|
46
|
-
|
47
|
-
mattr_accessor :rules_for_excluding_active_records
|
45
|
+
mattr_accessor :active_record_filters
|
48
46
|
|
49
|
-
self.
|
47
|
+
self.active_record_filters = [
|
50
48
|
'Globalize::ActiveRecord::Translation',
|
51
49
|
'ActiveRecord::SchemaMigration',
|
52
50
|
/\AHABTM/,
|
data/lib/traits/list.rb
CHANGED
@@ -7,29 +7,24 @@ module Traits
|
|
7
7
|
def uses_inheritance?
|
8
8
|
inheritance_base? || inheritance_derived?
|
9
9
|
end
|
10
|
-
alias uses_sti? uses_inheritance?
|
11
10
|
|
12
11
|
def inheritance_base?
|
13
|
-
|
14
|
-
!
|
15
|
-
|
12
|
+
active_record.descends_from_active_record? &&
|
13
|
+
!active_record.abstract_class? &&
|
14
|
+
active_record.subclasses.any? { |subclass| subclass.superclass == active_record }
|
16
15
|
end
|
17
|
-
alias sti_base? inheritance_base?
|
18
16
|
|
19
17
|
def inheritance_derived?
|
20
|
-
!
|
18
|
+
!active_record.descends_from_active_record?
|
21
19
|
end
|
22
|
-
alias sti_derived? inheritance_derived?
|
23
20
|
|
24
21
|
def inheritance_attribute
|
25
|
-
attributes[
|
22
|
+
attributes[active_record.inheritance_column]
|
26
23
|
end
|
27
|
-
alias sti_attribute inheritance_attribute
|
28
24
|
|
29
25
|
def inheritance_attribute_name
|
30
26
|
inheritance_attribute.name if uses_inheritance?
|
31
27
|
end
|
32
|
-
alias sti_attribute_name inheritance_attribute_name
|
33
28
|
|
34
29
|
# class File < ActiveRecord::Base
|
35
30
|
# end
|
@@ -49,15 +44,14 @@ module Traits
|
|
49
44
|
# Portrait.traits.inheritance_chain => [File, Photo, Portrait]
|
50
45
|
def inheritance_chain
|
51
46
|
Traits.load_active_record_descendants!
|
52
|
-
|
53
|
-
chain
|
54
|
-
until
|
55
|
-
|
56
|
-
chain.unshift(
|
47
|
+
active_record = self.active_record
|
48
|
+
chain = [active_record]
|
49
|
+
until active_record.superclass == ActiveRecord::Base do
|
50
|
+
active_record = active_record.superclass
|
51
|
+
chain.unshift(active_record)
|
57
52
|
end
|
58
53
|
chain
|
59
54
|
end
|
60
|
-
alias sti_chain inheritance_chain
|
61
55
|
|
62
56
|
def inheritance_base
|
63
57
|
inheritance_chain[0]
|
@@ -65,10 +59,10 @@ module Traits
|
|
65
59
|
|
66
60
|
def to_hash
|
67
61
|
super.merge!(
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
62
|
+
is_inheritance_base: inheritance_base?,
|
63
|
+
is_inheritance_derived: inheritance_derived?,
|
64
|
+
inheritance_attribute_name: inheritance_attribute.try(:name),
|
65
|
+
inheritance_chain: inheritance_chain.map { |active_record| active_record.traits.name }
|
72
66
|
)
|
73
67
|
end
|
74
68
|
end
|
data/lib/traits/model/naming.rb
CHANGED
@@ -34,7 +34,7 @@ module Traits
|
|
34
34
|
# 'CIHelper' => 'cihelper' - good
|
35
35
|
# 'Helpers::CIHelper' => 'helpers/cihelper' - good
|
36
36
|
#
|
37
|
-
@name ||=
|
37
|
+
@name ||= active_record.name.split('::').map(&:underscore).join('/')
|
38
38
|
if namecase == :underscore
|
39
39
|
@underscore_name ||= @name.tr('/', '_')
|
40
40
|
else
|
@@ -66,7 +66,7 @@ module Traits
|
|
66
66
|
# class_name => Assets::Photo
|
67
67
|
#
|
68
68
|
def class_name
|
69
|
-
@class_name ||=
|
69
|
+
@class_name ||= active_record.name
|
70
70
|
end
|
71
71
|
|
72
72
|
# class User
|
@@ -5,13 +5,11 @@ module Traits
|
|
5
5
|
class Model
|
6
6
|
module Polymorphism
|
7
7
|
def polymorphic_type
|
8
|
-
@polymorphic_type ||=
|
8
|
+
@polymorphic_type ||= active_record.base_class.name.to_sym
|
9
9
|
end
|
10
10
|
|
11
11
|
def to_hash
|
12
|
-
super.merge!(
|
13
|
-
polymorphic_type: polymorphic_type
|
14
|
-
)
|
12
|
+
super.merge!(polymorphic_type: polymorphic_type)
|
15
13
|
end
|
16
14
|
end
|
17
15
|
end
|
@@ -8,7 +8,7 @@ module Traits
|
|
8
8
|
# Sometimes table doesn't have primary key.
|
9
9
|
# This might be many-to-many tables (HABTM).
|
10
10
|
@pk_name ||= begin
|
11
|
-
pk =
|
11
|
+
pk = active_record.primary_key
|
12
12
|
pk.kind_of?(String) ? pk.to_sym : pk
|
13
13
|
end
|
14
14
|
end
|
@@ -18,19 +18,19 @@ module Traits
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def arel
|
21
|
-
|
21
|
+
active_record.arel_table
|
22
22
|
end
|
23
23
|
|
24
24
|
def connection
|
25
|
-
|
25
|
+
active_record.connection
|
26
26
|
end
|
27
27
|
|
28
28
|
def table_name
|
29
|
-
@table_name ||=
|
29
|
+
@table_name ||= active_record.table_name
|
30
30
|
end
|
31
31
|
|
32
32
|
def quoted_table_name
|
33
|
-
@quote_table_name ||= connection.quote_table_name(
|
33
|
+
@quote_table_name ||= connection.quote_table_name(active_record.table_name)
|
34
34
|
end
|
35
35
|
|
36
36
|
def to_hash
|
data/lib/traits/model.rb
CHANGED
@@ -22,13 +22,10 @@ module Traits
|
|
22
22
|
include EssayShortcuts
|
23
23
|
include I18n
|
24
24
|
|
25
|
-
|
25
|
+
attr_accessor :active_record
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
def initialize(model_class)
|
31
|
-
@model_class = model_class
|
27
|
+
def initialize(active_record)
|
28
|
+
@active_record = active_record
|
32
29
|
end
|
33
30
|
|
34
31
|
def attributes
|
@@ -59,10 +56,10 @@ module Traits
|
|
59
56
|
|
60
57
|
# TODO Store, Storage, Virtual attributes
|
61
58
|
def inspect_attributes
|
62
|
-
if
|
59
|
+
if active_record.abstract_class?
|
63
60
|
Traits::AttributeList.new([])
|
64
61
|
else
|
65
|
-
columns =
|
62
|
+
columns = active_record.columns_hash.values
|
66
63
|
|
67
64
|
if features.try(:translates_with_globalize?)
|
68
65
|
globalize = features.globalize
|
@@ -75,7 +72,7 @@ module Traits
|
|
75
72
|
end
|
76
73
|
|
77
74
|
list = columns.map do |column|
|
78
|
-
Traits::Attribute.new(
|
75
|
+
Traits::Attribute.new(active_record, column)
|
79
76
|
end
|
80
77
|
|
81
78
|
Traits::AttributeList.new(list)
|
@@ -83,11 +80,11 @@ module Traits
|
|
83
80
|
end
|
84
81
|
|
85
82
|
def inspect_associations
|
86
|
-
if
|
83
|
+
if active_record.abstract_class?
|
87
84
|
Traits::List.new([])
|
88
85
|
else
|
89
|
-
list =
|
90
|
-
Traits::Association.new(
|
86
|
+
list = active_record.reflections.map do |pair|
|
87
|
+
Traits::Association.new(active_record, pair.last)
|
91
88
|
end
|
92
89
|
Traits::List.new(list)
|
93
90
|
end
|
data/lib/traits/utilities.rb
CHANGED
@@ -2,39 +2,54 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module Traits
|
5
|
-
class UnidentifiedModelReference < StandardError
|
6
|
-
end
|
7
|
-
|
8
5
|
module Utilities
|
9
|
-
def
|
6
|
+
def retrieve_active_record(obj)
|
10
7
|
if active_record_descendant?(obj)
|
11
8
|
obj
|
12
9
|
|
13
10
|
elsif active_record_instance?(obj)
|
14
11
|
obj.class
|
15
12
|
|
13
|
+
elsif active_record_collection?(obj)
|
14
|
+
obj.model
|
15
|
+
|
16
16
|
else
|
17
17
|
case obj
|
18
|
-
when Symbol
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
when String, Symbol
|
19
|
+
s = obj.kind_of?(Symbol) ? obj.to_s : obj
|
20
|
+
s.camelize.safe_constantize || s.tr('_', '/').camelize.safe_constantize
|
21
|
+
|
22
|
+
when Traits::Model, Traits::Attribute
|
23
|
+
obj.active_record
|
24
|
+
|
25
|
+
when Traits::Association
|
26
|
+
obj.from_active_record
|
22
27
|
end
|
23
28
|
end
|
24
29
|
end
|
25
30
|
|
31
|
+
def retrieve_active_record!(obj)
|
32
|
+
retrieve_active_record(obj) || begin
|
33
|
+
raise ActiveRecordRetrieveError, "#{obj.inspect} is not a valid ActiveRecord reference"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
26
37
|
def active_record_descendant?(obj)
|
27
38
|
obj.kind_of?(Class) && obj < ActiveRecord::Base
|
28
39
|
end
|
29
40
|
|
30
|
-
def
|
31
|
-
obj.kind_of?(ActiveRecord::
|
41
|
+
def active_record_collection?(obj)
|
42
|
+
obj.kind_of?(ActiveRecord::Relation)
|
32
43
|
end
|
33
44
|
|
34
|
-
def
|
35
|
-
|
45
|
+
def active_record_instance?(obj)
|
46
|
+
obj.kind_of?(ActiveRecord::Base)
|
36
47
|
end
|
37
48
|
end
|
38
49
|
|
39
50
|
extend Utilities
|
51
|
+
|
52
|
+
# TODO Better name
|
53
|
+
class ActiveRecordRetrieveError < StandardError
|
54
|
+
end
|
40
55
|
end
|
data/lib/traits/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-traits
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yaroslav Konoplov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|