baby_squeel 1.1.1 → 1.1.2

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: 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.