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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 84c79ad24f867dd858de441a1d0bef4d74c847d2
4
- data.tar.gz: 9d312a4e8fff3e8330010e1745c687a6a072ce58
3
+ metadata.gz: 0bb790119c0be6db1ea5e9c0337b75db99a15ae3
4
+ data.tar.gz: ee1ed0dcf813732a24347107fe08ad1f5c1485ac
5
5
  SHA512:
6
- metadata.gz: 2ec766c0c8f9da4fb1b66e35fdc7e0e02d7b11dc02d71255b3363e8af2843afb6cf0645a60a63fe0cb41ce47ad893fbfe4d1ca18981d946a8078678a7d65edcd
7
- data.tar.gz: f3c97ed4ccf20b06b485b8d99b6485bca306b3bba31a6717e2e44e53096695bb3ae47597a3c8f0047ed29c247c132f8fe95ee6aa5f3a022dca217827cb3fb8cf
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].to_class # => Article
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.sti_base? # => true
54
- Toy.traits.sti_derived? # => true
55
- Toy.traits.sti_chain # => [Present, Toy]
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
 
@@ -18,35 +18,39 @@ require 'traits/model'
18
18
  require 'traits/list'
19
19
 
20
20
  class ActiveRecord::Base
21
- def self.traits
22
- @traits ||= Traits::Model.new(self)
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
- def self.for(obj)
30
- retrieve_model_class(obj).traits
31
- end
31
+ class << self
32
+ def for(obj)
33
+ retrieve_active_record!(obj).traits
34
+ end
32
35
 
33
- def self.each(&block)
34
- active_record_descendants.each { |ar| block.call(ar.traits) }
35
- end
36
+ def each
37
+ active_record_descendants.each { |ar| yield(ar.traits) }
38
+ end
36
39
 
37
- def self.all
38
- each_with_object({}) do |traits, memo|
39
- memo[traits.name] = traits
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
- def self.each_attribute(&block)
44
- each { |traits| traits.attributes.each(&block) }
45
- end
46
+ def each_attribute(&block)
47
+ each { |traits| traits.attributes.each(&block) }
48
+ end
46
49
 
47
- def self.to_hash
48
- each_with_object({}) do |traits, memo|
49
- memo[traits.name] = traits.to_hash
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,7 +5,7 @@ module Traits
5
5
  class Association
6
6
  module EssayShortcuts
7
7
  def features
8
- from_class.association_features[name]
8
+ from_active_record.association_features[name]
9
9
  end
10
10
  end
11
11
  end
@@ -5,12 +5,12 @@ module Traits
5
5
  class Association
6
6
  module Members
7
7
  def from
8
- @from_class.traits
8
+ @from_active_record.traits
9
9
  end
10
10
 
11
11
  # Returns the actual association establisher class
12
- def from_class
13
- @from_class
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 to_class
21
+ def to_active_record
22
22
  reflection.klass unless polymorphic?
23
23
  end
24
24
 
25
25
  def self_to_self?
26
- from_class == to_class
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 = from_class
55
+ this_class = from_active_record
56
56
 
57
- Traits.active_record_descendants.each do |model_class|
57
+ Traits.active_record_descendants.each do |active_record|
58
58
  # Skip current model and models which are STI derived
59
- next if model_class <= this_class # Means is or derived from current model
59
+ next if active_record <= this_class # Means is or derived from current model
60
60
 
61
- model_class.traits.associations.each do |assoc|
61
+ active_record.traits.associations.each do |assoc|
62
62
  if assoc.attribute_name_for_polymorphic_type == attr_name
63
- classes << assoc.from_class
63
+ classes << assoc.from_active_record
64
64
  end
65
65
  end
66
66
  end
@@ -30,9 +30,9 @@ module Traits
30
30
 
31
31
  attr_reader :reflection
32
32
 
33
- def initialize(model_class, reflection)
34
- @from_class = model_class
35
- @reflection = 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
- from_class.validators_on(name)
51
+ from_active_record.validators_on(name)
52
52
  end
53
53
  end
54
54
  end
@@ -5,7 +5,7 @@ module Traits
5
5
  class Attribute
6
6
  module EssayShortcuts
7
7
  def features
8
- model_class.attribute_features[name]
8
+ active_record.attribute_features[name]
9
9
  end
10
10
  end
11
11
  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!(is_sti_type: sti_type?)
12
+ super.merge!(is_inheritance_type: inheritance_type?)
14
13
  end
15
14
  end
16
15
  end
@@ -6,13 +6,13 @@ module Traits
6
6
  module Key
7
7
  def primary_key?
8
8
  column_definition.try(:primary) ||
9
- model_class.primary_key == column_definition.name ||
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 = model_class.attribute_features[attr_name].try(:translates_with_globalize?)
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?
@@ -9,7 +9,7 @@ module Traits
9
9
  end
10
10
 
11
11
  def quoted_name
12
- @quoted_name ||= model_class.connection.quote_column_name(name)
12
+ @quoted_name ||= active_record.connection.quote_column_name(name)
13
13
  end
14
14
 
15
15
  def to_hash
@@ -6,7 +6,7 @@ module Traits
6
6
  module Querying
7
7
  def arel
8
8
  table = if features.try(:translates_with_globalize?)
9
- model_class.features.globalize.translation_model_class.arel_table
9
+ active_record.features.globalize.translation_model_class.arel_table
10
10
  else
11
11
  model.arel
12
12
  end
@@ -24,24 +24,24 @@ module Traits
24
24
  include Inheritance
25
25
  include EssayShortcuts
26
26
 
27
- attr_reader :model_class, :column_definition
27
+ attr_reader :active_record, :column_definition
28
28
 
29
- def initialize(model_class, column_definition)
30
- @model_class = model_class
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
- model_class.traits
35
+ active_record.traits
36
36
  end
37
37
 
38
38
  # TODO Remove this
39
39
  def regular?
40
- !(key? || sti_type? || polymorphic_type? || active_record_timestamp?)
40
+ !(key? || inheritance_type? || polymorphic_type? || active_record_timestamp?)
41
41
  end
42
42
 
43
43
  def validators
44
- model_class.validators_on(name)
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
- !!@ar_descendants_loaded
7
+ !!@active_record_descendants_loaded
8
8
  end
9
9
 
10
10
  def load_active_record_descendants!
11
- @ar_descendants_loaded ||= begin
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
- @ar_descendants = nil
22
- @ar_descendants_loaded = false
21
+ @active_record_descendants_loaded = false
23
22
  end
24
23
 
25
- def active_record_descendants
26
- @ar_descendants ||= begin
27
- load_active_record_descendants!
28
- ActiveRecord::Base.descendants.reject! { |ar| excluded_active_record_descendant?(ar) }
29
- end
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 excluded_active_record_descendant?(model_class)
33
- rules_for_excluding_active_records.any? do |rule|
34
- case rule
35
- when Regexp then model_class.name =~ rule
36
- when String then model_class.name == rule
37
- when Class then model_class == rule
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
- # TODO Give a better name
47
- mattr_accessor :rules_for_excluding_active_records
45
+ mattr_accessor :active_record_filters
48
46
 
49
- self.rules_for_excluding_active_records = [
47
+ self.active_record_filters = [
50
48
  'Globalize::ActiveRecord::Translation',
51
49
  'ActiveRecord::SchemaMigration',
52
50
  /\AHABTM/,
data/lib/traits/list.rb CHANGED
@@ -25,6 +25,12 @@ module Traits
25
25
  by_name(arg)
26
26
  end
27
27
 
28
+ def fetch(name)
29
+ el = by_name(name)
30
+ raise StandardError, "#{name.inspect} not found" unless el
31
+ el
32
+ end
33
+
28
34
  def each(&block)
29
35
  @list.each(&block)
30
36
  end
@@ -5,7 +5,7 @@ module Traits
5
5
  class Model
6
6
  module EssayShortcuts
7
7
  def features
8
- model_class.features
8
+ active_record.features
9
9
  end
10
10
  end
11
11
  end
@@ -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
- model_class.descends_from_active_record? &&
14
- !model_class.abstract_class? &&
15
- model_class.subclasses.any? { |subclass| subclass.superclass == model_class }
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
- !model_class.descends_from_active_record?
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[model_class.inheritance_column]
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
- model_class = self.model_class
53
- chain = [model_class]
54
- until model_class.superclass == ActiveRecord::Base do
55
- model_class = model_class.superclass
56
- chain.unshift(model_class)
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
- is_sti_base: sti_base?,
69
- is_sti_derived: sti_derived?,
70
- sti_attribute_name: sti_attribute_name,
71
- sti_chain: sti_chain.map { |model_class| model_class.traits.name }
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
@@ -34,7 +34,7 @@ module Traits
34
34
  # 'CIHelper' => 'cihelper' - good
35
35
  # 'Helpers::CIHelper' => 'helpers/cihelper' - good
36
36
  #
37
- @name ||= model_class.name.split('::').map(&:underscore).join('/')
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 ||= model_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 ||= model_class.base_class.name.to_sym
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 = model_class.primary_key
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
- model_class.arel_table
21
+ active_record.arel_table
22
22
  end
23
23
 
24
24
  def connection
25
- model_class.connection
25
+ active_record.connection
26
26
  end
27
27
 
28
28
  def table_name
29
- @table_name ||= model_class.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(model_class.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
- attr_reader :model_class
25
+ attr_accessor :active_record
26
26
 
27
- alias active_record model_class
28
- alias klass model_class
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 model_class.abstract_class?
59
+ if active_record.abstract_class?
63
60
  Traits::AttributeList.new([])
64
61
  else
65
- columns = model_class.columns_hash.values
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(model_class, column)
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 model_class.abstract_class?
83
+ if active_record.abstract_class?
87
84
  Traits::List.new([])
88
85
  else
89
- list = model_class.reflections.map do |pair|
90
- Traits::Association.new(model_class, pair.last)
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
@@ -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 retrieve_model_class(obj)
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 then obj.to_s.camelize.constantize
19
- when String then obj.camelize.constantize
20
- when Model then obj.model_class
21
- else raise UnidentifiedModelReference, obj
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 active_record_instance?(obj)
31
- obj.kind_of?(ActiveRecord::Base)
41
+ def active_record_collection?(obj)
42
+ obj.kind_of?(ActiveRecord::Relation)
32
43
  end
33
44
 
34
- def valid_active_record_identifier?(id)
35
- id.kind_of?(String) || id.kind_of?(Numeric)
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
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Traits
5
- VERSION = '1.0.3'
5
+ VERSION = '1.1.0'
6
6
  end
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.3
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-22 00:00:00.000000000 Z
11
+ date: 2016-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport