active_any 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/lib/active_any/association_relation.rb +9 -0
  4. data/lib/active_any/associations.rb +10 -0
  5. data/lib/active_any/associations/association.rb +7 -7
  6. data/lib/active_any/associations/belongs_to_association.rb +1 -14
  7. data/lib/active_any/associations/builder/association.rb +14 -8
  8. data/lib/active_any/associations/builder/has_many.rb +4 -12
  9. data/lib/active_any/associations/builder/has_one.rb +15 -0
  10. data/lib/active_any/associations/builder/singular_association.rb +9 -0
  11. data/lib/active_any/associations/collection_proxy.rb +6 -1
  12. data/lib/active_any/associations/foreign_association.rb +13 -0
  13. data/lib/active_any/associations/foreign_key_association.rb +13 -0
  14. data/lib/active_any/associations/has_many_association.rb +3 -1
  15. data/lib/active_any/associations/has_one_association.rb +9 -0
  16. data/lib/active_any/associations/preloader.rb +2 -0
  17. data/lib/active_any/associations/preloader/belongs_to.rb +1 -10
  18. data/lib/active_any/associations/preloader/has_one.rb +17 -0
  19. data/lib/active_any/associations/preloader/singular_association.rb +18 -0
  20. data/lib/active_any/associations/singular_association.rb +17 -0
  21. data/lib/active_any/attribute.rb +4 -0
  22. data/lib/active_any/core.rb +14 -0
  23. data/lib/active_any/reflection.rb +3 -0
  24. data/lib/active_any/reflection/association_reflection.rb +4 -0
  25. data/lib/active_any/reflection/belongs_to_reflection.rb +1 -1
  26. data/lib/active_any/reflection/has_many_reflection.rb +1 -1
  27. data/lib/active_any/reflection/has_one_reflection.rb +33 -0
  28. data/lib/active_any/relation.rb +0 -8
  29. data/lib/active_any/relation/delegation.rb +16 -2
  30. data/lib/active_any/version.rb +1 -1
  31. metadata +11 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 39acdd4989cf8260cd694f9c90c7e1dee0781e90
4
- data.tar.gz: 8942a09c7523b615a19bc3853141b47fdbfe9d46
3
+ metadata.gz: a75e1b79e1e6e0f79b2a8d19e730e4a47ddca996
4
+ data.tar.gz: 31cc1c7938c0649d3da04cfcaca9f2a55ff2e558
5
5
  SHA512:
6
- metadata.gz: a83b242f2d8a25fe53d78b3fe842f01a701cd8bc6a3605dbe097e337484876eafb804f0da660ab2e6cbe37efae74b6242977dff8fb6a3bad1bb0bf3df07a09bf
7
- data.tar.gz: e60bc3993222d390e5d2d0b779fe94075d6abfa43f52bd3892c5443a4147a25f475afcea7fd3e6ca30eb48f073ed47a1bc6b33c12cfaecb571f089a87f8f065a
6
+ metadata.gz: cc4a1f10b34b27e3412593e5094e09de8caab31e02e9ff4f3350a91bf16ef4a8bcaed9fcf71f467a40fb87342a21cdd0f23c241d05635d5df0033a0447a62c33
7
+ data.tar.gz: 94a64062ba15266cf0222e53170f0c187f2c3f39b5f15d7914523dfdcf1a63b77b06356317ea21d748d6c2dec57e7443b2fa36f3c6382d02df9f7c2332f2b301
@@ -16,6 +16,9 @@ Style/PredicateName:
16
16
  Style/AccessorMethodName:
17
17
  Enabled: false
18
18
 
19
+ Style/ClassAndModuleChildren:
20
+ Enabled: false
21
+
19
22
  Metrics/ClassLength:
20
23
  Max: 120
21
24
 
@@ -14,5 +14,14 @@ module ActiveAny
14
14
  def ==(other)
15
15
  other == records
16
16
  end
17
+
18
+ private
19
+
20
+ def exec_queries
21
+ super do |r|
22
+ @association.set_inverse_instance r
23
+ yield r if block_given?
24
+ end
25
+ end
17
26
  end
18
27
  end
@@ -4,10 +4,15 @@ require 'active_any/associations/preloader'
4
4
  require 'active_any/associations/collection_proxy'
5
5
  require 'active_any/associations/association_scope'
6
6
  require 'active_any/associations/builder/association'
7
+ require 'active_any/associations/builder/singular_association'
7
8
  require 'active_any/associations/builder/has_many'
9
+ require 'active_any/associations/builder/has_one'
8
10
  require 'active_any/associations/builder/belongs_to'
9
11
  require 'active_any/associations/association'
12
+ require 'active_any/associations/singular_association'
13
+ require 'active_any/associations/foreign_association'
10
14
  require 'active_any/associations/has_many_association'
15
+ require 'active_any/associations/has_one_association'
11
16
  require 'active_any/associations/belongs_to_association'
12
17
 
13
18
  module ActiveAny
@@ -34,6 +39,11 @@ module ActiveAny
34
39
  reflection = Builder::BelongsTo.build(self, name, scope, options)
35
40
  Reflection.add_reflection self, name, reflection
36
41
  end
42
+
43
+ def has_one(name, scope = nil, options = {})
44
+ reflection = Builder::HasOne.build(self, name, scope, options)
45
+ Reflection.add_reflection self, name, reflection
46
+ end
37
47
  end
38
48
 
39
49
  def initialize_dup(*)
@@ -14,11 +14,7 @@ module ActiveAny
14
14
  end
15
15
 
16
16
  def reader
17
- # TODO: implement
18
- # reload if stale_target?
19
-
20
- @proxy ||= CollectionProxy.create(owner, self)
21
- @proxy.reset_scope
17
+ raise NotImplementedError.new, 'reader is unimplemented'
22
18
  end
23
19
 
24
20
  def writer(_records)
@@ -51,7 +47,7 @@ module ActiveAny
51
47
  def load_target
52
48
  @target = find_target if find_target?
53
49
 
54
- loaded! unless loaded?
50
+ loaded!
55
51
  target
56
52
  # TODO: implement
57
53
  # rescue ActiveRecord::RecordNotFound
@@ -110,7 +106,11 @@ module ActiveAny
110
106
  end
111
107
 
112
108
  def find_target?
113
- !loaded? && klass
109
+ !loaded? && (!owner.new_record? || foreign_key_present?) && klass
110
+ end
111
+
112
+ def foreign_key_present
113
+ false
114
114
  end
115
115
 
116
116
  def inverse_reflection_for(_record)
@@ -2,20 +2,7 @@
2
2
 
3
3
  module ActiveAny
4
4
  module Associations
5
- class BelongsToAssociation < Association
6
- def reader
7
- reload unless loaded?
8
-
9
- target
10
- end
11
-
12
- def writer(_records)
13
- raise NotImplementedError.new, 'writer is unimplemented'
14
- end
15
-
16
- def find_target
17
- scope.first
18
- end
5
+ class BelongsToAssociation < SingularAssociation
19
6
  end
20
7
  end
21
8
  end
@@ -6,19 +6,18 @@ module ActiveAny
6
6
  class Association
7
7
  def self.build(klass, name, scope, options)
8
8
  reflection = create_reflection(klass, name, scope, options)
9
- define_writer_method klass, reflection.name
10
- define_reader_method klass, reflection.name
9
+ define_accessors klass, reflection
11
10
  reflection
12
11
  end
13
12
 
14
13
  VALID_OPTIONS = %i[class_name foreign_key].freeze
15
14
 
16
- def self.valid_options
15
+ def self.valid_options(_options)
17
16
  VALID_OPTIONS
18
17
  end
19
18
 
20
19
  def self.validate_options(options)
21
- options.assert_valid_keys(valid_options)
20
+ options.assert_valid_keys(valid_options(options))
22
21
  end
23
22
 
24
23
  def self.create_reflection(klass, name, scope, options)
@@ -41,16 +40,23 @@ module ActiveAny
41
40
  new_scope
42
41
  end
43
42
 
44
- def self.define_reader_method(klass, name)
45
- klass.class_eval <<-CODE, __FILE__, __LINE__ + 1
43
+ def self.define_accessors(klass, reflection)
44
+ mixin = klass.generated_association_methods
45
+ name = reflection.name
46
+ define_readers(mixin, name)
47
+ define_writers(mixin, name)
48
+ end
49
+
50
+ def self.define_readers(mixin, name)
51
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
46
52
  def #{name}(*args)
47
53
  association(:#{name}).reader(*args)
48
54
  end
49
55
  CODE
50
56
  end
51
57
 
52
- def self.define_writer_method(klass, name)
53
- klass.class_eval <<-CODE, __FILE__, __LINE__ + 1
58
+ def self.define_writers(mixin, name)
59
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
54
60
  def #{name}=(value)
55
61
  association(:#{name}).writer(value)
56
62
  end
@@ -1,17 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module ActiveAny
4
- module Associations
5
- module Builder
6
- class HasMany < Association
7
- def self.macro
8
- :has_many
9
- end
10
-
11
- def self.valid_options
12
- super + %i[primary_key]
13
- end
14
- end
3
+ module ActiveAny::Associations::Builder
4
+ class HasMany < SingularAssociation
5
+ def self.macro
6
+ :has_many
15
7
  end
16
8
  end
17
9
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAny::Associations::Builder
4
+ class HasOne < SingularAssociation
5
+ def self.macro
6
+ :has_one
7
+ end
8
+
9
+ def self.valid_options(options)
10
+ valid = super
11
+ # valid += %i[through source source_type] if options[:through]
12
+ valid
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAny::Associations::Builder
4
+ class SingularAssociation < Association
5
+ def self.valid_options(options)
6
+ super + %i[primary_key]
7
+ end
8
+ end
9
+ end
@@ -5,7 +5,7 @@ module ActiveAny
5
5
  class CollectionProxy < ActiveAny::Relation
6
6
  attr_reader :association
7
7
 
8
- delegate :target, :load_target, :load_target,
8
+ delegate :target, :load_target, :load_target, :loaded?, :find, :concat,
9
9
  :size, :empty?, :include?, to: :@association
10
10
 
11
11
  def initialize(klass, association)
@@ -13,6 +13,11 @@ module ActiveAny
13
13
  super(klass)
14
14
  end
15
15
 
16
+ def last(limit = nil)
17
+ load_target if find_from_target?
18
+ super
19
+ end
20
+
16
21
  def take(limit = nil)
17
22
  load_target if find_from_target?
18
23
  super
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAny::Associations
4
+ module ForeignAssociation
5
+ def foreign_key_present?
6
+ if reflection.klass.primary_key
7
+ owner.attribute_present?(reflection.record_class_primary_key)
8
+ else
9
+ false
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAny::Associations
4
+ module ForeignKeyAssociation
5
+ def foreign_key_present?
6
+ if reflection.klass.primary_key
7
+ owner.attribute_present?(reflection.record_class_primary_key)
8
+ else
9
+ false
10
+ end
11
+ end
12
+ end
13
+ end
@@ -3,11 +3,13 @@
3
3
  module ActiveAny
4
4
  module Associations
5
5
  class HasManyAssociation < Association
6
+ include ForeignAssociation
7
+
6
8
  def reader
7
9
  # TODO: implement
8
10
  # reload if stale_target?
9
11
 
10
- @proxy ||= CollectionProxy.create(owner, self)
12
+ @proxy ||= CollectionProxy.create(klass, self)
11
13
  @proxy.reset_scope
12
14
  end
13
15
 
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAny
4
+ module Associations
5
+ class HasOneAssociation < SingularAssociation
6
+ include ForeignAssociation
7
+ end
8
+ end
9
+ end
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_any/associations/preloader/association'
4
+ require 'active_any/associations/preloader/singular_association'
4
5
  require 'active_any/associations/preloader/has_many'
6
+ require 'active_any/associations/preloader/has_one'
5
7
  require 'active_any/associations/preloader/belongs_to'
6
8
 
7
9
  module ActiveAny
@@ -3,16 +3,7 @@
3
3
  module ActiveAny
4
4
  module Associations
5
5
  class Preloader
6
- class BelongsTo < Association
7
- def preload(preloader)
8
- associated_records_by_owner(preloader).each do |owner, associated_records|
9
- record = associated_records.first
10
-
11
- association = owner.association(reflection.name)
12
- association.target = record
13
- end
14
- end
15
-
6
+ class BelongsTo < SingularAssociation
16
7
  def association_key_name
17
8
  reflection.options[:primary_key] || klass && klass.primary_key
18
9
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAny
4
+ module Associations
5
+ class Preloader
6
+ class HasOne < SingularAssociation
7
+ def association_key_name
8
+ reflection.foreign_key
9
+ end
10
+
11
+ def owner_key_name
12
+ reflection.record_class_primary_key
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAny
4
+ module Associations
5
+ class Preloader
6
+ class SingularAssociation < Association
7
+ def preload(preloader)
8
+ associated_records_by_owner(preloader).each do |owner, associated_records|
9
+ record = associated_records.first
10
+
11
+ association = owner.association(reflection.name)
12
+ association.target = record
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAny
4
+ module Associations
5
+ class SingularAssociation < Association
6
+ def find_target
7
+ scope.first
8
+ end
9
+
10
+ def reader
11
+ reload unless loaded?
12
+
13
+ target
14
+ end
15
+ end
16
+ end
17
+ end
@@ -16,6 +16,10 @@ module ActiveAny
16
16
  attributes.fetch(name)
17
17
  end
18
18
 
19
+ def attribute_present?(name)
20
+ attributes[name].present?
21
+ end
22
+
19
23
  def attribute_for_inspect(attr_name)
20
24
  value = read_attribute(attr_name)
21
25
 
@@ -37,12 +37,26 @@ module ActiveAny
37
37
  def abstract_class?
38
38
  defined?(@abstract_class) && abstract_class == true
39
39
  end
40
+
41
+ def generated_association_methods
42
+ @generated_association_methods ||= begin
43
+ mod = const_set(:GeneratedAssociationMethods, Module.new)
44
+ private_constant :GeneratedAssociationMethods
45
+ include mod
46
+
47
+ mod
48
+ end
49
+ end
40
50
  end
41
51
 
42
52
  def initialize(*args)
43
53
  init_internals(*args)
44
54
  end
45
55
 
56
+ def new_record?
57
+ false
58
+ end
59
+
46
60
  def [](key)
47
61
  send(key)
48
62
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'active_any/reflection/association_reflection'
4
4
  require 'active_any/reflection/has_many_reflection'
5
+ require 'active_any/reflection/has_one_reflection'
5
6
  require 'active_any/reflection/belongs_to_reflection'
6
7
 
7
8
  module ActiveAny
@@ -33,6 +34,8 @@ module ActiveAny
33
34
  def self.create(macro, name, scope, options, klass)
34
35
  reflection_class =
35
36
  case macro
37
+ when :has_one
38
+ HasOneReflection
36
39
  when :belongs_to
37
40
  BelongsToReflection
38
41
  when :has_many
@@ -40,6 +40,10 @@ module ActiveAny
40
40
  false
41
41
  end
42
42
 
43
+ def has_one?
44
+ false
45
+ end
46
+
43
47
  JoinKeys = Struct.new(:key, :foreign_key)
44
48
 
45
49
  def join_keys
@@ -18,7 +18,7 @@ module ActiveAny
18
18
  private
19
19
 
20
20
  def join_pk
21
- primary_key
21
+ record_class_primary_key
22
22
  end
23
23
 
24
24
  def join_fk
@@ -22,7 +22,7 @@ module ActiveAny
22
22
  end
23
23
 
24
24
  def join_fk
25
- primary_key
25
+ record_class_primary_key
26
26
  end
27
27
  end
28
28
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAny
4
+ module Reflection
5
+ class HasOneReflection < AssociationReflection
6
+ def association_class
7
+ Associations::HasOneAssociation
8
+ end
9
+
10
+ def macro
11
+ :has_one
12
+ end
13
+
14
+ def has_one?
15
+ true
16
+ end
17
+
18
+ def collection?
19
+ false
20
+ end
21
+
22
+ private
23
+
24
+ def join_pk
25
+ foreign_key
26
+ end
27
+
28
+ def join_fk
29
+ record_class_primary_key
30
+ end
31
+ end
32
+ end
33
+ end
@@ -20,14 +20,6 @@ module ActiveAny
20
20
 
21
21
  class ImmutableRelation < StandardError; end
22
22
 
23
- def self.create(klass, *args)
24
- relation_class_for(klass).new(klass, *args)
25
- end
26
-
27
- def self.relation_class_for(klass)
28
- klass.relation_delegate_class(self)
29
- end
30
-
31
23
  def initialize(klass)
32
24
  @klass = klass
33
25
  @records = []
@@ -80,9 +80,23 @@ module ActiveAny
80
80
  end
81
81
  end
82
82
 
83
- def respond_to_missing?(name, include_private)
84
- super
83
+ def respond_to_missing?(name, _)
84
+ super || @klass.respond_to?(name)
85
+ end
86
+ end
87
+
88
+ module ClassMethods
89
+ def create(klass, *args)
90
+ relation_class_for(klass).new(klass, *args)
85
91
  end
92
+
93
+ def relation_class_for(klass)
94
+ klass.relation_delegate_class(self)
95
+ end
96
+ end
97
+
98
+ def respond_to_missing?(name, _)
99
+ super || @klass.respond_to?(name)
86
100
  end
87
101
  end
88
102
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveAny
4
- VERSION = '0.0.7'
4
+ VERSION = '0.0.8'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_any
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - yuemori
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-07-25 00:00:00.000000000 Z
11
+ date: 2017-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -209,12 +209,20 @@ files:
209
209
  - lib/active_any/associations/builder/association.rb
210
210
  - lib/active_any/associations/builder/belongs_to.rb
211
211
  - lib/active_any/associations/builder/has_many.rb
212
+ - lib/active_any/associations/builder/has_one.rb
213
+ - lib/active_any/associations/builder/singular_association.rb
212
214
  - lib/active_any/associations/collection_proxy.rb
215
+ - lib/active_any/associations/foreign_association.rb
216
+ - lib/active_any/associations/foreign_key_association.rb
213
217
  - lib/active_any/associations/has_many_association.rb
218
+ - lib/active_any/associations/has_one_association.rb
214
219
  - lib/active_any/associations/preloader.rb
215
220
  - lib/active_any/associations/preloader/association.rb
216
221
  - lib/active_any/associations/preloader/belongs_to.rb
217
222
  - lib/active_any/associations/preloader/has_many.rb
223
+ - lib/active_any/associations/preloader/has_one.rb
224
+ - lib/active_any/associations/preloader/singular_association.rb
225
+ - lib/active_any/associations/singular_association.rb
218
226
  - lib/active_any/attribute.rb
219
227
  - lib/active_any/attribute_assignment.rb
220
228
  - lib/active_any/base.rb
@@ -225,6 +233,7 @@ files:
225
233
  - lib/active_any/reflection/association_reflection.rb
226
234
  - lib/active_any/reflection/belongs_to_reflection.rb
227
235
  - lib/active_any/reflection/has_many_reflection.rb
236
+ - lib/active_any/reflection/has_one_reflection.rb
228
237
  - lib/active_any/relation.rb
229
238
  - lib/active_any/relation/delegation.rb
230
239
  - lib/active_any/relation/finder_methods.rb