activerecord-traits 1.0.3 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  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