queryable 1.0.1 → 2.0.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: d01fa7b43b3b44643d009f15e6438ef3fd4a665f
4
- data.tar.gz: 75164b6c8f28fb3db7e6b182a3f18bf50aa386f8
3
+ metadata.gz: 28570cfafe1680583b92ea618a85cbca197f5c4b
4
+ data.tar.gz: 981e0042933205c1bf4c10daa8db4dcecec540f0
5
5
  SHA512:
6
- metadata.gz: 994927851ef85e8a225f3cb8c21cac6eb21d9d97ac336ca7992d0b4594d8aafab58130e3d60e590b044f331fd7214b99b14fa00b5d56995b3bf0594d001c1b67
7
- data.tar.gz: 4f0c6d2d977f9d5ba763c414f2fe434da06c089a8ca628e6358fba8899396fbd3c6a3fd0bfb80a597e44117a163b0e9870a417f6eb1ec5aef22080f76e8a77ea
6
+ metadata.gz: ecfd3bb32c31a300bd768cbf82d5f42628e1012259de2df4c174d68ad2ba368d2db4a0666dfb482ff7a94391dedbef9c6e658c3fba19a62c14ee2ff9fd2119ae
7
+ data.tar.gz: 318dea62093ecd3e8defe4e3b87bbf0b0a5169980164d5597e1ed51bfe06193a731d577bcf05a029b96fecd3939c518ac910e970e0606258ea44c31627831d91
data/README.md CHANGED
@@ -3,6 +3,7 @@ Queryable
3
3
  [![Gem Version](https://badge.fury.io/rb/queryable.svg)](http://badge.fury.io/rb/queryable)
4
4
  [![Build Status](https://travis-ci.org/ElMassimo/queryable.svg)](https://travis-ci.org/ElMassimo/queryable)
5
5
  [![Coverage Status](https://coveralls.io/repos/ElMassimo/queryable/badge.png)](https://coveralls.io/r/ElMassimo/queryable)
6
+ [![Inline docs](http://inch-ci.org/github/ElMassimo/queryable.svg)](http://inch-ci.org/github/ElMassimo/queryable)
6
7
  <!-- [![Code Climate](https://codeclimate.com/github/ElMassimo/queryable.png)](https://codeclimate.com/github/ElMassimo/queryable) -->
7
8
 
8
9
  Queryable is a mixin that allows you to easily define query objects with chainable scopes.
@@ -9,19 +9,19 @@
9
9
  # include Queryable
10
10
  # scope(:too_damn_high) { where(:level.gt => 9000) }
11
11
  # end
12
- #
12
+ #'
13
13
  module Queryable
14
14
 
15
15
  # Internal: Adds class methods, a query accessor, and method delegation.
16
16
  def self.included(base)
17
- base.extend ClassMethods
18
17
  base.extend Forwardable
18
+ base.extend ClassMethods
19
19
  base.class_eval do
20
-
21
20
  # Public: Gets/Sets the internal query.
22
21
  attr_accessor :query
23
22
 
24
- def_delegators :query, *delegated_methods
23
+ # Internal: Delegates Array and Criteria methods to the internal query.
24
+ delegate *Queryable.default_delegated_methods
25
25
  end
26
26
  end
27
27
 
@@ -32,47 +32,15 @@ module Queryable
32
32
  @query = query.all
33
33
  end
34
34
 
35
- # Public: Convenience setter for the internal query that returns self. The
36
- # query is set to the value returned by the block. Useful when you need to
37
- # access the context of the Queryable in addition to the query.
38
- #
39
- # block - A block that returns the new value of the internal query.
40
- #
41
- # Yields the internal query, which can be used to build upon.
42
- # def search(query)
43
- #
44
- # Examples
45
- #
46
- # # Accessing a constant in the Queryable object context.
47
- # LATEST_COUNT = 10
48
- # def latest
49
- # define_query {|query| query.limit(LATEST_COUNT) }
50
- # end
51
- #
52
- # # We use it because the last method we chain does not return self.
53
- # def recent_by_name
54
- # define_query { recent.order(:name) }
55
- # end
56
- #
57
- # # Extracted from a scope for clarity.
58
- # def search(field_values)
59
- # define_query do |users|
60
- # field_values.inject(users) { |users, (field, value)|
61
- # users.where(field => /#{value}/i)
62
- # }
63
- # end
64
- # end
65
- #
66
- # Returns the Queryable object itself (self).
67
- def define_query
68
- @query = yield(query)
69
- self
70
- end
71
-
72
35
  # Internal: Contains the Queryable class methods.
73
36
  module ClassMethods
74
- # Public: Defines a new method that executes the passed proc or block in
75
- # the context of the internal query object, and returns self.
37
+
38
+ # Public: Delegates the specified methods to the internal query.
39
+ def delegate(*methods)
40
+ methods.last.is_a?(Hash) ? super : def_delegators(:query, *methods)
41
+ end
42
+
43
+ # Public: Defines a new scope method, or makes an existing method chainable.
76
44
  #
77
45
  # name - Name of the scope to define for this Queryable.
78
46
  #
@@ -94,22 +62,59 @@ module Queryable
94
62
  # where(_type: "#{brand}ExtremelyFastRacingCar")
95
63
  # end
96
64
  #
65
+ # scope def search(field_values)
66
+ # field_values.inject(query) { |query, (field, value)|
67
+ # query.where(field => /#{value}/i)
68
+ # }
69
+ # end
70
+ #
97
71
  # Returns nothing.
98
72
  def scope(name, proc=nil, &block)
73
+ if method_defined?(name)
74
+ scope_method(name)
75
+ else
76
+ define_scope(name, proc || block)
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ # Internal: Defines a new method that executes the passed proc or block in
83
+ # the context of the internal query object, and returns self.
84
+ def define_scope(name, proc)
99
85
  define_method(name) do |*args|
100
- @query = query.instance_exec *args, &(proc || block)
86
+ @query = query.instance_exec *args, &proc
101
87
  self
102
88
  end
103
89
  end
104
90
 
105
- # Internal: Methods to be delegated to the internal query. Method
106
- # can be safely overriden to add or remove methods to delegate.
107
- #
108
- # Returns an Array with the name of the methods to delegate.
109
- def delegated_methods
110
- Array.instance_methods - Object.instance_methods +
111
- [:all, :where, :distinct, :group, :having, :includes, :joins, :limit, :offset, :order, :reverse_order] +
112
- [:==, :as_json, :cache_key, :decorate]
91
+ # Public: Makes an existing method chainable by intercepting the call, and
92
+ # storing the result as the internal query, and returning self.
93
+ def scope_method(name)
94
+ prepend Module.new.tap { |s| s.module_eval Queryable.scope_method(name) }
113
95
  end
114
96
  end
97
+
98
+ # Internal: Generates the scope interceptor method.
99
+ #
100
+ # name - Name of the method to convert to a scope.
101
+ #
102
+ # Returns a String with the code of the scope method.
103
+ def self.scope_method(name)
104
+ <<-SCOPE
105
+ def #{name}(*args)
106
+ @query = super
107
+ self
108
+ end
109
+ SCOPE
110
+ end
111
+
112
+ # Internal: Default methods to be delegated to the internal query.
113
+ #
114
+ # Returns an Array with the name of the methods to delegate.
115
+ def self.default_delegated_methods
116
+ Array.instance_methods - Object.instance_methods +
117
+ [:all, :where, :distinct, :group, :having, :includes, :joins, :limit, :offset, :order, :reverse_order] +
118
+ [:==, :as_json, :cache_key, :decorate]
119
+ end
115
120
  end
@@ -0,0 +1,40 @@
1
+ # Public: Provides default initialization for query objects, most objects are
2
+ # mapped to a collection or table, the default query takes all of them.
3
+ module Queryable
4
+ module DefaultQuery
5
+
6
+ # Internal: Adds class methods, and default initialization.
7
+ def self.included(base)
8
+ base.extend ClassMethods
9
+ end
10
+
11
+ def initialize(query=self.class.default_query)
12
+ super
13
+ end
14
+
15
+ module ClassMethods
16
+
17
+ # Public: Sets the default table or collection for this query object.
18
+ #
19
+ # collection - A model or static query.
20
+ def queryable(collection)
21
+ @queryable_class = collection
22
+ end
23
+
24
+ # Internal: Default query for the object, can be overriden by subclasses.
25
+ #
26
+ # Returns a criteriable or chainable query of some sort.
27
+ def default_query
28
+ queryable_class.all
29
+ end
30
+
31
+ # Internal: The default table or collection for this query object.
32
+ # Provides a default based on a convention of the query object name.
33
+ def queryable_class
34
+ @queryable_class ||= if superclass.respond_to?(:queryable_class)
35
+ superclass.queryable_class || Object.const_get(name.gsub('sQuery', ''))
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,53 @@
1
+ # Public: Allows to define default scopes in query objects, and inherit them in
2
+ # query object subclasses.
3
+ module Queryable
4
+ module DefaultScope
5
+
6
+ # Internal: Adds class methods, and default initialization.
7
+ def self.included(base)
8
+ base.extend ClassMethods
9
+ end
10
+
11
+ def initialize(*args)
12
+ super
13
+ apply_default_scopes
14
+ end
15
+
16
+ private
17
+
18
+ # Internal: Applies all the default scopes to this query object.
19
+ def apply_default_scopes
20
+ self.class.default_scopes.each { |scope| apply_default_scope(scope) }
21
+ end
22
+
23
+ # Internal: Applies a default scope to this query object.
24
+ #
25
+ # scope - A method name Symbol, or a Proc.
26
+ #
27
+ def apply_default_scope(scope)
28
+ scope.is_a?(Proc) ? instance_exec(&scope) : send(scope)
29
+ end
30
+
31
+ module ClassMethods
32
+
33
+ # Public: Allows a class to set a default scope. Default scopes are
34
+ # chainable with inheritance, so a subclass also picks up the default
35
+ # scopes of the parent class.
36
+ #
37
+ # scope - A method name Symbol, or a Proc.
38
+ def default_scope(scope)
39
+ @default_scope = scope
40
+ end
41
+
42
+ # Internal: Returns the default scopes of the parent query objects.
43
+ def parent_scopes
44
+ superclass.respond_to?(:default_scopes) ? superclass.default_scopes : []
45
+ end
46
+
47
+ # Internal: Returns the default scopes that should be applied.
48
+ def default_scopes
49
+ @default_scopes ||= (parent_scopes + [@default_scope]).compact
50
+ end
51
+ end
52
+ end
53
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: queryable
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Máximo Mussini
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-12 00:00:00.000000000 Z
11
+ date: 2014-08-12 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Queryable is a module that encapsulates query building so you don't have
14
14
  to tuck scopes inside your models.
@@ -21,6 +21,8 @@ extra_rdoc_files:
21
21
  files:
22
22
  - README.md
23
23
  - lib/queryable.rb
24
+ - lib/queryable/default_query.rb
25
+ - lib/queryable/default_scope.rb
24
26
  homepage: https://github.com/ElMassimo/queryable
25
27
  licenses:
26
28
  - MIT
@@ -47,4 +49,3 @@ signing_key:
47
49
  specification_version: 4
48
50
  summary: Keep your scopes and queries flexible by using Ruby
49
51
  test_files: []
50
- has_rdoc: