baby_squeel 1.1.1 → 1.1.2

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: ea748a7c86d1947f7fe48e799eb2ced9f7741a63
4
- data.tar.gz: f9196d9756b6cb9b461d654112cfc0818ced9b62
3
+ metadata.gz: 3f4792b9f869cd23c5910a52a2d95188ee75c806
4
+ data.tar.gz: c2d75c755301787ac04d5aa8220396be848f9f28
5
5
  SHA512:
6
- metadata.gz: 040230635cc12c89d661c622b6e3b43f84d0fb37fd320a0ab570560d605fa170287d594ef810d27d7cd33278c15aeba609bdb1d71cdc28cc00bd0f6b0743dff5
7
- data.tar.gz: db3975104c6c290c712fd3833e1bf469ae93e4ec262d861f1504b1f6fe9f15bada5ccebac0e43871fa61583688bf758d0d352af3bff4b7dc5e5cc9092d8c7979
6
+ metadata.gz: 6a91030415fc3afd7017e92f89440207bf7069b8f3681a549d3abba3629847e9dd589aabe6398104ff6c89d780660a7f600ddccecd3d69a07decb10fabcbc8f6
7
+ data.tar.gz: 4b1d040212307df0175af66a8e5ce59b7f398abcfae50387a857434d16b06da9b4598ffc3078a42f852272ad2981164f2fde42f3729435a44953d86b1dc17e10
@@ -97,12 +97,8 @@ module BabySqueel
97
97
 
98
98
  private
99
99
 
100
- def method_missing(meth, *args, &block)
101
- if !args.empty? && !block_given?
102
- func(meth, args)
103
- else
104
- super
105
- end
100
+ def resolver
101
+ @resolver ||= Resolver.new(self, [:function, :column, :association])
106
102
  end
107
103
  end
108
104
  end
@@ -1,7 +1,18 @@
1
1
  module BabySqueel
2
2
  class NotFoundError < StandardError # :nodoc:
3
- def initialize(model_name, name)
4
- super "There is no column or association named '#{name}' for #{model_name}."
3
+ def initialize(model_name, name, strategies)
4
+ super "There is no #{sentence(strategies)} " \
5
+ "named '#{name}' for #{model_name}."
6
+ end
7
+
8
+ private
9
+
10
+ def sentence(*words)
11
+ if words.length < 3
12
+ words.join ' or '
13
+ else
14
+ sentence words[0..-2].join(', '), words.last
15
+ end
5
16
  end
6
17
  end
7
18
 
@@ -28,7 +28,10 @@ module BabySqueel
28
28
  def find_join_association(associations)
29
29
  associations.inject(join_root) do |parent, assoc|
30
30
  parent.children.find do |join_association|
31
- join_association.reflection == assoc._reflection
31
+ reflections_equal?(
32
+ assoc._reflection,
33
+ join_association.reflection
34
+ )
32
35
  end
33
36
  end
34
37
  end
@@ -43,6 +46,18 @@ module BabySqueel
43
46
 
44
47
  private
45
48
 
49
+ # Compare two reflections and see if they're the same.
50
+ def reflections_equal?(a, b)
51
+ comparable_reflection(a) == comparable_reflection(b)
52
+ end
53
+
54
+ # Get the parent of the reflection if it has one.
55
+ # In AR4, #parent_reflection returns [name, reflection]
56
+ # In AR5, #parent_reflection returns just a reflection
57
+ def comparable_reflection(reflection)
58
+ [*reflection.parent_reflection].last || reflection
59
+ end
60
+
46
61
  # Active Record 5's AliasTracker initializes Arel tables
47
62
  # with the type_caster belonging to the wrong model.
48
63
  #
@@ -15,7 +15,7 @@ module BabySqueel
15
15
  if reflection = _scope.reflect_on_association(name)
16
16
  Association.new(self, reflection)
17
17
  else
18
- not_found_error! name, type: AssociationNotFoundError
18
+ raise AssociationNotFoundError.new(_scope.model_name, name)
19
19
  end
20
20
  end
21
21
 
@@ -30,18 +30,8 @@ module BabySqueel
30
30
 
31
31
  private
32
32
 
33
- # @override BabySqueel::Table#not_found_error!
34
- def not_found_error!(name, type: NotFoundError)
35
- raise type.new(_scope.model_name, name)
36
- end
37
-
38
- # @override BabySqueel::Table#resolve
39
- def resolve(name)
40
- if _scope.column_names.include?(name.to_s)
41
- self[name]
42
- elsif _scope.reflect_on_association(name)
43
- association(name)
44
- end
33
+ def resolver
34
+ @resolver ||= Resolver.new(self, [:column, :association])
45
35
  end
46
36
  end
47
37
  end
@@ -0,0 +1,96 @@
1
+ module BabySqueel
2
+ class Resolver
3
+ def initialize(table, strategies)
4
+ @table = table
5
+ @strategies = strategies
6
+ end
7
+
8
+ # Attempt to determine the intent of the method_missing. If this method
9
+ # returns nil, that means one of two things:
10
+ #
11
+ # 1. The argument signature is invalid.
12
+ # 2. The name of the method called is not valid (ex. invalid column name)
13
+ def resolve(name, *args, &block)
14
+ strategy = @strategies.find do |strategy|
15
+ valid?(strategy, name, *args, &block)
16
+ end
17
+
18
+ build(strategy, name, *args, &block)
19
+ end
20
+
21
+ # Try to resolve the method_missing. If we fail to resolve, there are
22
+ # two outcomes:
23
+ #
24
+ # If any of the configured strategies accept argument signature provided,
25
+ # raise an error. This means we failed to resolve the name. (ex. invalid
26
+ # column name)
27
+ #
28
+ # Otherwise, a nil return valid indicates that argument signature was not
29
+ # valid for any of the configured strategies. This case should be treated
30
+ # as a NoMethodError.
31
+ def resolve!(name, *args, &block)
32
+ if resolution = resolve(name, *args, &block)
33
+ return resolution
34
+ end
35
+
36
+ if compatible_arguments?(*args, &block)
37
+ raise NotFoundError.new(@table._scope.model_name, name, @strategies)
38
+ end
39
+
40
+ return nil
41
+ end
42
+
43
+ # Used to determine if a table can respond_to? a method.
44
+ def resolves?(name)
45
+ @strategies.any? do |strategy|
46
+ valid_name? strategy, name
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def build(strategy, name, *args)
53
+ case strategy
54
+ when :function
55
+ @table.func(name, *args)
56
+ when :association
57
+ @table.association(name)
58
+ when :column, :attribute
59
+ @table[name]
60
+ end
61
+ end
62
+
63
+ def valid?(strategy, name, *args, &block)
64
+ valid_arguments?(strategy, *args, &block) &&
65
+ valid_name?(strategy, name)
66
+ end
67
+
68
+ def valid_name?(strategy, name)
69
+ case strategy
70
+ when :column
71
+ @table._scope.column_names.include?(name.to_s)
72
+ when :association
73
+ !@table._scope.reflect_on_association(name).nil?
74
+ when :function, :attribute
75
+ true
76
+ end
77
+ end
78
+
79
+ def valid_arguments?(strategy, *args)
80
+ return false if block_given?
81
+
82
+ case strategy
83
+ when :function
84
+ !args.empty?
85
+ when :column, :attribute, :association
86
+ args.empty?
87
+ end
88
+ end
89
+
90
+ def compatible_arguments?(*args, &block)
91
+ @strategies.any? do |strategy|
92
+ valid_arguments?(strategy, *args, &block)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -1,3 +1,4 @@
1
+ require 'baby_squeel/resolver'
1
2
  require 'baby_squeel/join_expression'
2
3
  require 'baby_squeel/join_dependency/builder'
3
4
 
@@ -93,21 +94,16 @@ module BabySqueel
93
94
 
94
95
  private
95
96
 
96
- def not_found_error!
97
- raise NotImplementedError, 'BabySqueel::Table will never raise a NotFoundError'
98
- end
99
-
100
- def resolve(name)
101
- self[name]
97
+ def resolver
98
+ @resolver ||= Resolver.new(self, [:attribute])
102
99
  end
103
100
 
104
101
  def respond_to_missing?(name, *)
105
- resolve(name).present? || super
102
+ resolver.resolves?(name) || super
106
103
  end
107
104
 
108
- def method_missing(name, *args, &block)
109
- return super if !args.empty? || block_given?
110
- resolve(name) || not_found_error!(name)
105
+ def method_missing(*args, &block)
106
+ resolver.resolve!(*args, &block) || super
111
107
  end
112
108
  end
113
109
  end
@@ -1,3 +1,3 @@
1
1
  module BabySqueel
2
- VERSION = '1.1.1'.freeze
2
+ VERSION = '1.1.2'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: baby_squeel
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ray Zane
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-02-14 00:00:00.000000000 Z
11
+ date: 2017-03-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -129,6 +129,7 @@ files:
129
129
  - lib/baby_squeel/operators.rb
130
130
  - lib/baby_squeel/pluck.rb
131
131
  - lib/baby_squeel/relation.rb
132
+ - lib/baby_squeel/resolver.rb
132
133
  - lib/baby_squeel/table.rb
133
134
  - lib/baby_squeel/version.rb
134
135
  homepage: https://github.com/rzane/baby_squeel
@@ -151,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
151
152
  version: '0'
152
153
  requirements: []
153
154
  rubyforge_project:
154
- rubygems_version: 2.5.2
155
+ rubygems_version: 2.6.10
155
156
  signing_key:
156
157
  specification_version: 4
157
158
  summary: An expressive query DSL for Active Record 4 and 5.