parascope 0.1.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 +7 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +21 -0
- data/README.md +173 -0
- data/Rakefile +6 -0
- data/bin/console +59 -0
- data/bin/setup +8 -0
- data/lib/parascope.rb +5 -0
- data/lib/parascope/query.rb +144 -0
- data/lib/parascope/query/api_block.rb +23 -0
- data/lib/parascope/query/api_methods.rb +41 -0
- data/lib/parascope/version.rb +3 -0
- data/parascope.gemspec +33 -0
- metadata +146 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 20fc5771d922f27cb3562954c138dd4d9069f01a
|
4
|
+
data.tar.gz: 2da5ec9511b1cdea10f7a7e84aaa6023c358733c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: af2fce7745657960a666ae9d160b6fced85be97a3698f8b6cd1ed0d8f5b14d694e349222c011752071501e77f86a8ca62b415c2c22c4e5d75d3fc5648460a571
|
7
|
+
data.tar.gz: ab35b12aa2b8a822dd53eb113867b63fc6cd1c00685021108273c724e4569dd78267b58b4d8da395a5c7c3db8157b951a91a6efc7d4e8b2f2636bccd5c732533
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Artem Kuzko
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
# Parascope
|
2
|
+
|
3
|
+
[](http://travis-ci.org/akuzko/parascope)
|
4
|
+
|
5
|
+
Because `periscope` is already taken.
|
6
|
+
|
7
|
+
--
|
8
|
+
|
9
|
+
This gem provides a `Parascope::Query` class with a declarative and convenient API
|
10
|
+
to build scopes (ActiveRecord relations or arbitrary objects) dynamically, based
|
11
|
+
on parameters passed to query object on initialization.
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Add this line to your application's Gemfile:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'parascope'
|
19
|
+
```
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
$ bundle
|
24
|
+
|
25
|
+
Or install it yourself as:
|
26
|
+
|
27
|
+
$ gem install parascope
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
Despite the fact `parsacope` was intended to help building ActiveRecord relations
|
32
|
+
via scopes or query methods, it's usage is not limited to ActiveRecord cases and
|
33
|
+
may be used with any arbitrary classes and objects. In fact, the only gem's dependency
|
34
|
+
is `hashie`, and for development and testing, `OpenStruct` instance is used as a
|
35
|
+
generic scope object. However, ActiveRecord examples should illustrate gem's usage
|
36
|
+
in the best way.
|
37
|
+
|
38
|
+
### API
|
39
|
+
|
40
|
+
`parascope` provides `Parascope::Query` class, descendants of which should declare
|
41
|
+
scope manipulations using `query_by`, `sift_by` and other class methods bellow.
|
42
|
+
|
43
|
+
#### Class Methods
|
44
|
+
|
45
|
+
- `query_by(*presence_fields, **value_fields, &block)` declares a scope-generation query
|
46
|
+
block that will be executed if, and only if all values of query params at the keys of
|
47
|
+
`presence_fields` are present in activesupport's definition of presence and all value
|
48
|
+
fields are present in query params as is. The block is executed in context of query
|
49
|
+
object. All values of specified params are yielded to the block. If the block
|
50
|
+
returns a non-nil value, it becomes a new scope for following processing. Of course,
|
51
|
+
there can be multiple `query_by` block definitions. Optionally, `:index` option
|
52
|
+
may be passed to control query blocks application order.
|
53
|
+
|
54
|
+
- `sift_by(*presence_fields, **value_fields, &block)` method is used to hoist sets of
|
55
|
+
query definitions that should be applied if, and only if, all specified values
|
56
|
+
match criteria in the same way as in `query_by` method. Just like `query_by` method,
|
57
|
+
values of specified fields are yielded to the block. Such `sift_by` definitions
|
58
|
+
may be nested in any depth.
|
59
|
+
|
60
|
+
- `base_scope(&block)` method is used to define a base scope as a starting point
|
61
|
+
of scope-generating process. If this method is called from `sift_by` block,
|
62
|
+
top-level base scope is yielded to the method block. Note that `base_scope` will
|
63
|
+
not be called if query is initialized with a given scope.
|
64
|
+
|
65
|
+
- `defaults(hash)` method is used to declare default query params that are reverse
|
66
|
+
merged with params passed on query initialization. When used in `sift_by` block,
|
67
|
+
hashes are merged altogether.
|
68
|
+
|
69
|
+
- `guard(&block)` defines a guard instance method block (see instance methods
|
70
|
+
bellow). All such blocks are executed before query object resolves scope via
|
71
|
+
`resolve_scope` method.
|
72
|
+
|
73
|
+
#### Instance Methods
|
74
|
+
|
75
|
+
- `initialize(params, scope: nil, **attributes)` initializes a query with `params`,
|
76
|
+
an optional scope (that if passed, is used instead of `base_scope`). All additionally
|
77
|
+
passed options are accessible via reader methods in query blocks and elsewhere.
|
78
|
+
|
79
|
+
- `params` returns a parameters passed in initialization. Is a `Hashie::Mash` instance,
|
80
|
+
thus, values can be accessible via reader methods.
|
81
|
+
|
82
|
+
- `[](key)` delegates to query `params` for slightly easier values access.
|
83
|
+
|
84
|
+
- `scope` "current" scope of query object. For an initialized query object corresponds
|
85
|
+
to base scope. Primary usage is to call this method in `query_by` blocks and return
|
86
|
+
it's mutated version corresponding to passed `query_by` arguments.
|
87
|
+
|
88
|
+
- `guard(&block)` executes a passed `block`. If this execution returns falsy value,
|
89
|
+
`UnpermittedError` is raised. You can use this method to ensure safety of param
|
90
|
+
values interpolation to a SQL string in a `query_by` block for example.
|
91
|
+
|
92
|
+
- `resolved_scope(override_params = nil)` returns a resulting scope generated by
|
93
|
+
all queries and sifted queries that fit to query params applied to base scope.
|
94
|
+
Optionally, additional params may be passed to override the ones passed on
|
95
|
+
initialization. It's the main `Query` instance method that returns the sole
|
96
|
+
purpose of it's instances.
|
97
|
+
|
98
|
+
### Usage example with ActiveRecord Relation as a scope
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
class UserQuery < Parascope::Query
|
102
|
+
defaults only_active: true
|
103
|
+
|
104
|
+
base_scope { company.users }
|
105
|
+
|
106
|
+
query_by :only_active do
|
107
|
+
scope.active
|
108
|
+
end
|
109
|
+
|
110
|
+
query_by :birthdate do |date|
|
111
|
+
scope.by_birtdate(date)
|
112
|
+
end
|
113
|
+
|
114
|
+
query_by :name do |name|
|
115
|
+
scope.where("CONCAT(first_name, ' ', last_name) LIKE ?", "%#{name}%")
|
116
|
+
end
|
117
|
+
|
118
|
+
sift_by :sort_column, :sort_direction do |scol, sdir|
|
119
|
+
guard { sdir.to_s.downcase.in?(%w(asc desc)) }
|
120
|
+
|
121
|
+
base_scope { |scope| scope.order(scol => sdir) }
|
122
|
+
|
123
|
+
query_by(:sort_direction, sort_column: 'name') do |sdir|
|
124
|
+
scope.reorder("CONCAT(first_name, ' ', last_name) #{sdir}")
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
sift_by :with_projects do
|
129
|
+
base_scope { |scope| scope.joins(:projects) }
|
130
|
+
|
131
|
+
query_by :project_name do |name|
|
132
|
+
scope.where(projects: {name: name})
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def users
|
137
|
+
@users ||= resolved_scope
|
138
|
+
end
|
139
|
+
|
140
|
+
def project_users
|
141
|
+
@project_users ||= resolved_scope(with_projects: true)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
params = {name: 'John', sort_column: 'name', sort_direction: 'DESC', project_name: 'ExampleApp'}
|
146
|
+
|
147
|
+
query = UserQuery.new(params, company: some_company)
|
148
|
+
|
149
|
+
query.project_users # => this is the same as:
|
150
|
+
# some_company.users
|
151
|
+
# .active
|
152
|
+
# .joins(:projects)
|
153
|
+
# .where("CONCAT(first_name, ' ', last_name) LIKE ?", "%John%")
|
154
|
+
# .where(projects: {name: 'ExampleApp'})
|
155
|
+
# .order("CONCAT(first_name, ' ', last_name) DESC")
|
156
|
+
```
|
157
|
+
|
158
|
+
## Development
|
159
|
+
|
160
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
161
|
+
`rake spec` to run the tests. You can also run `bin/console` for an interactive
|
162
|
+
prompt that will allow you to experiment.
|
163
|
+
|
164
|
+
## Contributing
|
165
|
+
|
166
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/akuzko/parascope.
|
167
|
+
|
168
|
+
|
169
|
+
## License
|
170
|
+
|
171
|
+
The gem is available as open source under the terms of the
|
172
|
+
[MIT License](http://opensource.org/licenses/MIT).
|
173
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "parascope"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
require 'ostruct'
|
10
|
+
|
11
|
+
class Query < Parascope::Query
|
12
|
+
defaults barbak: 'barbak'
|
13
|
+
|
14
|
+
base_scope { OpenStruct.new }
|
15
|
+
|
16
|
+
query_by :foo do |foo|
|
17
|
+
guard { foo == 'foo' }
|
18
|
+
|
19
|
+
scope.tap{ scope.foo = foo }
|
20
|
+
end
|
21
|
+
|
22
|
+
query_by bar: 'bar' do
|
23
|
+
scope.tap{ scope.bar = 'bar' }
|
24
|
+
end
|
25
|
+
|
26
|
+
sift_by baz: 'baz' do |baz|
|
27
|
+
defaults bakbar: 'bakbar'
|
28
|
+
|
29
|
+
guard { upcase(baz) == 'BAZ' }
|
30
|
+
|
31
|
+
base_scope { |scope| scope.tap{ scope.baz = 'baz' } }
|
32
|
+
|
33
|
+
query_by :bak do |bak|
|
34
|
+
scope.tap{ scope.bak = bak }
|
35
|
+
end
|
36
|
+
|
37
|
+
query_by :barbak do |barbak|
|
38
|
+
scope.tap{ scope.barbak = barbak }
|
39
|
+
end
|
40
|
+
|
41
|
+
sift_by :nested_baz do |nested_baz|
|
42
|
+
query_by :bakbar do |bakbar|
|
43
|
+
scope.tap{ scope.bakbar = [baz, nested_baz, bakbar].join('-') }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def upcase(str)
|
49
|
+
str.upcase
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
q = Query.new(foo: 'foo', bar: 'bar', baz: 'baz', bak: 'bak', nested_baz: 'nb')
|
54
|
+
|
55
|
+
require "pry"
|
56
|
+
Pry.start
|
57
|
+
|
58
|
+
# require "irb"
|
59
|
+
# IRB.start
|
data/bin/setup
ADDED
data/lib/parascope.rb
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
require "hashie/mash"
|
2
|
+
|
3
|
+
module Parascope
|
4
|
+
class Query
|
5
|
+
autoload :ApiMethods, "parascope/query/api_methods"
|
6
|
+
autoload :ApiBlock, "parascope/query/api_block"
|
7
|
+
|
8
|
+
extend Forwardable
|
9
|
+
extend ApiMethods
|
10
|
+
|
11
|
+
UndefinedScopeError = Class.new(StandardError)
|
12
|
+
UnpermittedError = Class.new(ArgumentError)
|
13
|
+
|
14
|
+
attr_reader :params
|
15
|
+
def_delegator :params, :[]
|
16
|
+
|
17
|
+
def self.inherited(subclass)
|
18
|
+
subclass.query_blocks.replace query_blocks.dup
|
19
|
+
subclass.sift_blocks.replace sift_blocks.dup
|
20
|
+
subclass.guard_blocks.replace guard_blocks.dup
|
21
|
+
subclass.base_scope(&base_scope)
|
22
|
+
subclass.defaults defaults
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(params, scope: nil, **attrs)
|
26
|
+
@params = Hashie::Mash.new(klass.defaults).merge(params || {})
|
27
|
+
@scope = scope unless scope.nil?
|
28
|
+
@attrs = attrs
|
29
|
+
define_attr_readers
|
30
|
+
end
|
31
|
+
|
32
|
+
def scope
|
33
|
+
@scope ||= base_scope
|
34
|
+
end
|
35
|
+
|
36
|
+
def base_scope
|
37
|
+
scope = klass.ancestors
|
38
|
+
.select{ |klass| klass < Query }
|
39
|
+
.reverse
|
40
|
+
.map(&:base_scope)
|
41
|
+
.compact
|
42
|
+
.reduce(nil){ |scope, block| instance_exec(scope, &block) }
|
43
|
+
|
44
|
+
if scope.nil?
|
45
|
+
fail UndefinedScopeError, "failed to build scope. Have you missed base_scope definition?"
|
46
|
+
end
|
47
|
+
|
48
|
+
scope
|
49
|
+
end
|
50
|
+
|
51
|
+
def resolved_scope(params = nil)
|
52
|
+
return sifted_instance.resolved_scope! if params.nil?
|
53
|
+
|
54
|
+
clone_with_params(params).resolved_scope
|
55
|
+
end
|
56
|
+
|
57
|
+
def klass
|
58
|
+
sifted? ? singleton_class : self.class
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
attr_writer :scope, :params
|
64
|
+
attr_accessor :block
|
65
|
+
attr_reader :attrs
|
66
|
+
|
67
|
+
def sifted_instance
|
68
|
+
block = klass.sift_blocks.find{ |block| block.fits?(params) }
|
69
|
+
|
70
|
+
block ? sifted_instance_for(block) : self
|
71
|
+
end
|
72
|
+
|
73
|
+
def resolved_scope!
|
74
|
+
guard_all
|
75
|
+
klass.query_blocks.sort{ |a, b| a.index <=> b.index }.reduce(scope) do |scope, block|
|
76
|
+
clone_with_scope(scope, block).apply_block!.scope
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def apply_block!
|
81
|
+
if block && block.fits?(params)
|
82
|
+
scope = instance_exec(*block.values_for(params), &block.block)
|
83
|
+
@scope = scope unless scope.nil?
|
84
|
+
end
|
85
|
+
self
|
86
|
+
end
|
87
|
+
|
88
|
+
def sifted!(block, query)
|
89
|
+
@attrs = query.attrs
|
90
|
+
define_attr_readers
|
91
|
+
singleton_class.query_blocks.replace query.klass.query_blocks.dup
|
92
|
+
singleton_class.guard_blocks.replace query.klass.guard_blocks.dup
|
93
|
+
singleton_class.base_scope(&query.klass.base_scope)
|
94
|
+
singleton_class.instance_exec(*block.values_for(params), &block.block)
|
95
|
+
params.replace(singleton_class.defaults.merge(params))
|
96
|
+
@sifted = true
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def guard_all
|
102
|
+
klass.guard_blocks.each{ |block| guard(&block) }
|
103
|
+
end
|
104
|
+
|
105
|
+
def guard(&block)
|
106
|
+
unless instance_exec(&block)
|
107
|
+
fail UnpermittedError, "processing is not allowed by guard block\non #{block.source_location.join(':')}"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def clone_with_scope(scope, block)
|
112
|
+
clone.tap do |query|
|
113
|
+
query.scope = scope
|
114
|
+
query.block = block
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def clone_with_params(other_params)
|
119
|
+
clone.tap do |query|
|
120
|
+
query.params = params.merge(other_params)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def clone_with_sifter(block)
|
125
|
+
dup.tap do |query|
|
126
|
+
query.sifted!(block, self)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def sifted?
|
131
|
+
!!@sifted
|
132
|
+
end
|
133
|
+
|
134
|
+
def sifted_instance_for(block)
|
135
|
+
clone_with_sifter(block).sifted_instance
|
136
|
+
end
|
137
|
+
|
138
|
+
def define_attr_readers
|
139
|
+
@attrs.each do |name, value|
|
140
|
+
define_singleton_method(name){ value }
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Parascope
|
2
|
+
class Query::ApiBlock < Struct.new(:presence_fields, :value_fields, :block, :index)
|
3
|
+
def fits?(params)
|
4
|
+
values_for(params).all?{ |value| present?(value) }
|
5
|
+
end
|
6
|
+
|
7
|
+
def values_for(params)
|
8
|
+
params.values_at(*presence_fields) + valued_values_for(params)
|
9
|
+
end
|
10
|
+
|
11
|
+
def present?(value)
|
12
|
+
value.respond_to?(:empty?) ? !value.empty? : !!value
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def valued_values_for(params)
|
18
|
+
value_fields.map do |field, required_value|
|
19
|
+
params[field] == required_value && required_value
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Parascope
|
2
|
+
module Query::ApiMethods
|
3
|
+
def base_scope(&block)
|
4
|
+
return @base_scope unless block_given?
|
5
|
+
|
6
|
+
@base_scope = block
|
7
|
+
end
|
8
|
+
|
9
|
+
def defaults(params = nil)
|
10
|
+
@defaults ||= {}
|
11
|
+
|
12
|
+
return @defaults if params.nil?
|
13
|
+
|
14
|
+
@defaults = @defaults.merge(params)
|
15
|
+
end
|
16
|
+
|
17
|
+
def sift_by(*presence_fields, **value_fields, &block)
|
18
|
+
sift_blocks.push Query::ApiBlock.new(presence_fields, value_fields, block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def query_by(*presence_fields, index: 0, **value_fields, &block)
|
22
|
+
query_blocks.push Query::ApiBlock.new(presence_fields, value_fields, block, index)
|
23
|
+
end
|
24
|
+
|
25
|
+
def guard(&block)
|
26
|
+
guard_blocks.push block
|
27
|
+
end
|
28
|
+
|
29
|
+
def sift_blocks
|
30
|
+
@sift_blocks ||= []
|
31
|
+
end
|
32
|
+
|
33
|
+
def query_blocks
|
34
|
+
@query_blocks ||= []
|
35
|
+
end
|
36
|
+
|
37
|
+
def guard_blocks
|
38
|
+
@guard_blocks ||= []
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/parascope.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'parascope/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "parascope"
|
8
|
+
spec.version = Parascope::VERSION
|
9
|
+
spec.authors = ["Artem Kuzko"]
|
10
|
+
spec.email = ["a.kuzko@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Builds a params-sifted scope}
|
13
|
+
spec.description = %q{Parascope::Query class provides a way to dynamically
|
14
|
+
apply scopes or ActiveRecord query methods based on passed params with a
|
15
|
+
declarative and convenient API}
|
16
|
+
spec.homepage = "https://github.com/akuzko/parascope"
|
17
|
+
spec.license = "MIT"
|
18
|
+
|
19
|
+
spec.required_ruby_version = '>= 2.1.0'
|
20
|
+
|
21
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
22
|
+
spec.bindir = "exe"
|
23
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
|
+
spec.require_paths = ["lib"]
|
25
|
+
|
26
|
+
spec.add_dependency "hashie"
|
27
|
+
|
28
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
29
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
30
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
31
|
+
spec.add_development_dependency "pry"
|
32
|
+
spec.add_development_dependency "pry-nav"
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: parascope
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Artem Kuzko
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-05-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: hashie
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.11'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.11'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry-nav
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: |-
|
98
|
+
Parascope::Query class provides a way to dynamically
|
99
|
+
apply scopes or ActiveRecord query methods based on passed params with a
|
100
|
+
declarative and convenient API
|
101
|
+
email:
|
102
|
+
- a.kuzko@gmail.com
|
103
|
+
executables: []
|
104
|
+
extensions: []
|
105
|
+
extra_rdoc_files: []
|
106
|
+
files:
|
107
|
+
- ".gitignore"
|
108
|
+
- ".rspec"
|
109
|
+
- ".travis.yml"
|
110
|
+
- Gemfile
|
111
|
+
- LICENSE.txt
|
112
|
+
- README.md
|
113
|
+
- Rakefile
|
114
|
+
- bin/console
|
115
|
+
- bin/setup
|
116
|
+
- lib/parascope.rb
|
117
|
+
- lib/parascope/query.rb
|
118
|
+
- lib/parascope/query/api_block.rb
|
119
|
+
- lib/parascope/query/api_methods.rb
|
120
|
+
- lib/parascope/version.rb
|
121
|
+
- parascope.gemspec
|
122
|
+
homepage: https://github.com/akuzko/parascope
|
123
|
+
licenses:
|
124
|
+
- MIT
|
125
|
+
metadata: {}
|
126
|
+
post_install_message:
|
127
|
+
rdoc_options: []
|
128
|
+
require_paths:
|
129
|
+
- lib
|
130
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: 2.1.0
|
135
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
requirements: []
|
141
|
+
rubyforge_project:
|
142
|
+
rubygems_version: 2.4.8
|
143
|
+
signing_key:
|
144
|
+
specification_version: 4
|
145
|
+
summary: Builds a params-sifted scope
|
146
|
+
test_files: []
|