queryable 1.0.1 → 2.0.0

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