flex-scopes 1.0.1
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.
- data/LICENSE +20 -0
- data/README.md +25 -0
- data/VERSION +1 -0
- data/flex-scopes.gemspec +19 -0
- data/lib/flex-scopes.rb +12 -0
- data/lib/flex/result/scope.rb +12 -0
- data/lib/flex/scope.rb +42 -0
- data/lib/flex/scope/filter_methods.rb +81 -0
- data/lib/flex/scope/queries.yml +52 -0
- data/lib/flex/scope/query_methods.rb +89 -0
- data/lib/flex/scope/utils.rb +13 -0
- data/lib/flex/scope/vars_methods.rb +81 -0
- data/lib/flex/scopes.rb +89 -0
- metadata +76 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012-2013 by Domizio Demichelis
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# flex-scopes
|
2
|
+
|
3
|
+
Provides an easy to use ruby API to search elasticsearch with ActiveRecord-like chainable and mergeables scopes.
|
4
|
+
|
5
|
+
|
6
|
+
## Links
|
7
|
+
|
8
|
+
* [Flex Repository](https://github.com/ddnexus/flex)
|
9
|
+
* [Flex Project (Global Documentation)](http://ddnexus.github.io/flex/doc/)
|
10
|
+
* [flex-scopes Gem (Specific Documentation)](http://ddnexus.github.io/flex/doc/3-flex-scopes)
|
11
|
+
* [Issues](https://github.com/ddnexus/flex-scopes/issues)
|
12
|
+
* [Pull Requests](https://github.com/ddnexus/flex-scopes/pulls)
|
13
|
+
|
14
|
+
## Branches
|
15
|
+
|
16
|
+
The master branch reflects the last published gem. Then you may find a next-version branch (named after the version string), with the commits that will be merged in master just before publishing the next gem version. The next-version branch may get rebased or force pushed.
|
17
|
+
|
18
|
+
## Credits
|
19
|
+
|
20
|
+
Special thanks for their sponsorship to [Escalate Media](http://www.escalatemedia.com) and [Barquin International](http://www.barquin.com).
|
21
|
+
|
22
|
+
## Copyright
|
23
|
+
|
24
|
+
Copyright (c) 2012-2013 by [Domizio Demichelis](mailto://dd.nexus@gmail.com)<br>
|
25
|
+
See [LICENSE](https://github.com/ddnexus/flex-scopes/blob/master/LICENSE) for details.
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.1
|
data/flex-scopes.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'date'
|
2
|
+
version = File.read(File.expand_path('../VERSION', __FILE__)).strip
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'flex-scopes'
|
6
|
+
s.summary = 'ActiveRecord-like chainable scopes and finders for Flex.'
|
7
|
+
s.description = 'Provides an easy to use ruby API to search elasticsearch with ActiveRecord-like chainable and mergeables scopes.'
|
8
|
+
s.homepage = 'http://github.com/ddnexus/flex-scopes'
|
9
|
+
s.authors = ["Domizio Demichelis"]
|
10
|
+
s.email = 'dd.nexus@gmail.com'
|
11
|
+
s.extra_rdoc_files = %w[README.md]
|
12
|
+
s.files = `git ls-files -z`.split("\0")
|
13
|
+
s.version = version
|
14
|
+
s.date = Date.today.to_s
|
15
|
+
s.required_rubygems_version = ">= 1.3.6"
|
16
|
+
s.rdoc_options = %w[--charset=UTF-8]
|
17
|
+
|
18
|
+
s.add_runtime_dependency 'flex', version
|
19
|
+
end
|
data/lib/flex-scopes.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'flex'
|
2
|
+
require 'flex/scope/utils'
|
3
|
+
require 'flex/scope/filter_methods'
|
4
|
+
require 'flex/scope/vars_methods'
|
5
|
+
require 'flex/scope/query_methods'
|
6
|
+
require 'flex/scope'
|
7
|
+
require 'flex/scopes'
|
8
|
+
require 'flex/result/scope'
|
9
|
+
|
10
|
+
Flex::LIB_PATHS << File.dirname(__FILE__)
|
11
|
+
|
12
|
+
Flex::Conf.result_extenders |= [Flex::Result::Scope]
|
data/lib/flex/scope.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module Flex
|
2
|
+
# never instantiate this class directly: it is automatically done by the scoped method
|
3
|
+
class Scope < Vars
|
4
|
+
|
5
|
+
class Error < StandardError; end
|
6
|
+
|
7
|
+
include FilterMethods
|
8
|
+
include VarsMethods
|
9
|
+
include QueryMethods
|
10
|
+
|
11
|
+
SCOPED_METHODS = FilterMethods.instance_methods + VarsMethods.instance_methods + QueryMethods.instance_methods
|
12
|
+
|
13
|
+
def inspect
|
14
|
+
"#<#{self.class.name} #{self}>"
|
15
|
+
end
|
16
|
+
|
17
|
+
def respond_to?(meth, private=false)
|
18
|
+
super || is_template?(meth) || is_scope?(meth)
|
19
|
+
end
|
20
|
+
|
21
|
+
def method_missing(meth, *args, &block)
|
22
|
+
super unless respond_to?(meth)
|
23
|
+
case
|
24
|
+
when is_scope?(meth)
|
25
|
+
deep_merge self[:context].send(meth, *args, &block)
|
26
|
+
when is_template?(meth)
|
27
|
+
self[:context].send(meth, deep_merge(*args), &block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def is_template?(name)
|
34
|
+
self[:context].respond_to?(:template_methods) && self[:context].template_methods.include?(name.to_sym)
|
35
|
+
end
|
36
|
+
|
37
|
+
def is_scope?(name)
|
38
|
+
self[:context].scope_methods.include?(name.to_sym)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Flex
|
2
|
+
class Scope
|
3
|
+
module FilterMethods
|
4
|
+
|
5
|
+
include Scope::Utils
|
6
|
+
|
7
|
+
# accepts also :any_term => nil for missing values
|
8
|
+
def terms(value)
|
9
|
+
terms, missing_list = {}, []
|
10
|
+
value.each { |f, v| v.nil? ? missing_list.push({ :missing => f }) : (terms[f] = v) }
|
11
|
+
terms, term = terms.partition{|k,v| v.is_a?(Array)}
|
12
|
+
term_list = []
|
13
|
+
term.each do |term, value|
|
14
|
+
term_list.push(:term => {term => value})
|
15
|
+
end
|
16
|
+
deep_merge boolean_wrapper( :terms_list => Hash[terms],
|
17
|
+
:term_list => term_list,
|
18
|
+
:_missing_list => missing_list )
|
19
|
+
end
|
20
|
+
|
21
|
+
# accepts one or an array or a list of filter structures
|
22
|
+
def filters(*value)
|
23
|
+
deep_merge boolean_wrapper( :filters => array_value(value) )
|
24
|
+
end
|
25
|
+
|
26
|
+
def missing(*fields)
|
27
|
+
missing_list = []
|
28
|
+
for field in fields
|
29
|
+
missing_list.push(:missing => field)
|
30
|
+
end
|
31
|
+
deep_merge :_missing_list => missing_list
|
32
|
+
end
|
33
|
+
|
34
|
+
# accepts a single key hash or a multiple keys hash, that will be translated in a array of single key hashes
|
35
|
+
def term(term_or_terms_hash)
|
36
|
+
term_list = []
|
37
|
+
term_or_terms_hash.each do |term, value|
|
38
|
+
term_list.push(:term => {term => value})
|
39
|
+
end
|
40
|
+
deep_merge boolean_wrapper(:term_list => term_list)
|
41
|
+
end
|
42
|
+
|
43
|
+
# accepts one hash of ranges documented at
|
44
|
+
# http://www.elasticsearch.org/guide/reference/query-dsl/range-filter/
|
45
|
+
def range(value)
|
46
|
+
deep_merge boolean_wrapper(:range => value)
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
%w[and or].each do |m|
|
51
|
+
class_eval <<-ruby, __FILE__, __LINE__
|
52
|
+
def #{m}(&block)
|
53
|
+
vars = {:_#{m} => Hash[Flex::Scope.new.instance_eval(&block).to_a]}
|
54
|
+
vars.merge!(:_boolean_wrapper => :_#{m}) if context_scope?
|
55
|
+
deep_merge vars
|
56
|
+
end
|
57
|
+
ruby
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def context_scope?
|
63
|
+
has_key?(:context)
|
64
|
+
end
|
65
|
+
|
66
|
+
def boolean_wrapper(value)
|
67
|
+
if context_scope?
|
68
|
+
if has_key?(:_boolean_wrapper) && self[:_boolean_wrapper] != :_and
|
69
|
+
current_wrapper = {self[:_boolean_wrapper] => delete(self[:_boolean_wrapper])}
|
70
|
+
self.and{ current_wrapper }.and{ value }
|
71
|
+
else
|
72
|
+
self.and{value}
|
73
|
+
end
|
74
|
+
else
|
75
|
+
value
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
ANCHORS:
|
2
|
+
- &filters
|
3
|
+
- <<filters= ~ >>
|
4
|
+
- <<term_list= ~ >>
|
5
|
+
- terms: <<terms_list= ~ >>
|
6
|
+
- <<_missing_list= ~ >>
|
7
|
+
- <<_and= ~ >>
|
8
|
+
- <<_or= ~ >>
|
9
|
+
- range: <<range= ~ >>
|
10
|
+
|
11
|
+
- &scope
|
12
|
+
query:
|
13
|
+
query_string:
|
14
|
+
"<<cleanable_query= {query: '*'} >>"
|
15
|
+
script_fields:
|
16
|
+
<<script_fields= ~ >>
|
17
|
+
sort: <<sort= ~ >>
|
18
|
+
facets: <<facets= ~ >>
|
19
|
+
highlight: <<highlight= ~ >>
|
20
|
+
filter: <<_boolean_wrapper= :_and >>
|
21
|
+
|
22
|
+
_and:
|
23
|
+
and: *filters
|
24
|
+
|
25
|
+
_or:
|
26
|
+
or: *filters
|
27
|
+
|
28
|
+
_missing_fields:
|
29
|
+
missing:
|
30
|
+
field: <<missing>>
|
31
|
+
|
32
|
+
get:
|
33
|
+
- GET
|
34
|
+
- /<<index>>/<<type>>/_search
|
35
|
+
- *scope
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
delete:
|
40
|
+
- DELETE
|
41
|
+
- /<<index>>/<<type>>/_query
|
42
|
+
- filtered:
|
43
|
+
<<: *scope
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
ids:
|
48
|
+
- GET
|
49
|
+
- /<<index>>/<<type>>/_search
|
50
|
+
- query:
|
51
|
+
terms:
|
52
|
+
_id: <<ids>>
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Flex
|
2
|
+
class Scope
|
3
|
+
|
4
|
+
module Query
|
5
|
+
|
6
|
+
include Templates
|
7
|
+
flex.load_source File.expand_path('../queries.yml', __FILE__)
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
module QueryMethods
|
12
|
+
|
13
|
+
# MyModel.find(ids, *vars)
|
14
|
+
# - ids can be a single id or an array of ids
|
15
|
+
#
|
16
|
+
# MyModel.find '1Momf4s0QViv-yc7wjaDCA'
|
17
|
+
# #=> #<MyModel ... color: "red", size: "small">
|
18
|
+
#
|
19
|
+
# MyModel.find ['1Momf4s0QViv-yc7wjaDCA', 'BFdIETdNQv-CuCxG_y2r8g']
|
20
|
+
# #=> [#<MyModel ... color: "red", size: "small">, #<MyModel ... color: "bue", size: "small">]
|
21
|
+
#
|
22
|
+
def find(ids, *vars)
|
23
|
+
raise ArgumentError, "Empty argument passed (got #{ids.inspect})" \
|
24
|
+
if ids.nil? || ids.respond_to?(:empty?) && ids.empty?
|
25
|
+
wrapped = ids.is_a?(::Array) ? ids : [ids]
|
26
|
+
result = Query.ids self, *vars, :ids => wrapped
|
27
|
+
docs = result.get_docs
|
28
|
+
ids.is_a?(::Array) ? docs : docs.first
|
29
|
+
end
|
30
|
+
|
31
|
+
# it limits the size of the query to the first document and returns it as a single document object
|
32
|
+
def first(*vars)
|
33
|
+
result = Query.get params(:size => 1), *vars
|
34
|
+
docs = result.get_docs
|
35
|
+
docs.is_a?(Array) ? docs.first : docs
|
36
|
+
end
|
37
|
+
|
38
|
+
# it limits the size of the query to the last document and returns it as a single document object
|
39
|
+
def last(*vars)
|
40
|
+
result = Query.get params(:from => count-1, :size => 1), *vars
|
41
|
+
docs = result.get_docs
|
42
|
+
docs.is_a?(Array) ? docs.first : docs
|
43
|
+
end
|
44
|
+
|
45
|
+
# will retrieve all documents, the results will be limited by the default :size param
|
46
|
+
# use #scan_all if you want to really retrieve all documents (in batches)
|
47
|
+
def all(*vars)
|
48
|
+
result = Query.get self, *vars
|
49
|
+
result.get_docs
|
50
|
+
end
|
51
|
+
|
52
|
+
def each(*vars, &block)
|
53
|
+
all(*vars).each &block
|
54
|
+
end
|
55
|
+
|
56
|
+
# scan_search: the block will be yielded many times with an array of batched results.
|
57
|
+
# You can pass :scroll and :size as params in order to control the action.
|
58
|
+
# See http://www.elasticsearch.org/guide/reference/api/search/scroll.html
|
59
|
+
def scan_all(*vars, &block)
|
60
|
+
Query.flex.scan_search(:get, self, *vars) do |result|
|
61
|
+
block.call result.get_docs
|
62
|
+
end
|
63
|
+
end
|
64
|
+
alias_method :each_batch, :scan_all
|
65
|
+
alias_method :find_in_batches, :scan_all
|
66
|
+
|
67
|
+
def delete(*vars)
|
68
|
+
Query.delete self, *vars
|
69
|
+
end
|
70
|
+
|
71
|
+
# performs a count search on the scope
|
72
|
+
# you can pass a template name as the first arg and
|
73
|
+
# it will be used to compute the count. For example:
|
74
|
+
# SearchClass.scoped.count(:search_template, vars)
|
75
|
+
#
|
76
|
+
def count(*vars)
|
77
|
+
result = if vars.first.is_a?(Symbol)
|
78
|
+
template = vars.shift
|
79
|
+
# preserves an eventual wrapper by calling the template method
|
80
|
+
self[:context].send(template, params(:search_type => 'count'), *vars)
|
81
|
+
else
|
82
|
+
Query.flex.count_search(:get, self, *vars)
|
83
|
+
end
|
84
|
+
result['hits']['total']
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Flex
|
2
|
+
class Scope
|
3
|
+
module VarsMethods
|
4
|
+
|
5
|
+
include Scope::Utils
|
6
|
+
|
7
|
+
def query_string(q)
|
8
|
+
hash = q.is_a?(Hash) ? q : {:query => q}
|
9
|
+
deep_merge :cleanable_query => hash
|
10
|
+
end
|
11
|
+
alias_method :query, :query_string
|
12
|
+
|
13
|
+
# accepts one or an array or a list of sort structures documented at
|
14
|
+
# http://www.elasticsearch.org/guide/reference/api/search/sort.html
|
15
|
+
# doesn't probably support the multiple hash form, but you can pass an hash as single argument
|
16
|
+
# or an array or list of hashes
|
17
|
+
def sort(*value)
|
18
|
+
deep_merge :sort => array_value(value)
|
19
|
+
end
|
20
|
+
|
21
|
+
# the fields that you want to retrieve (limiting the size of the response)
|
22
|
+
# the returned records will be frozen (for Flex::ActiveModel objects), and the missing fields will be nil
|
23
|
+
# pass an array eg fields.([:field_one, :field_two]) or a list of fields e.g. fields(:field_one, :field_two)
|
24
|
+
def fields(*value)
|
25
|
+
deep_merge :params => {:fields => array_value(value)}
|
26
|
+
end
|
27
|
+
|
28
|
+
# limits the size of the retrieved hits
|
29
|
+
def size(value)
|
30
|
+
deep_merge :params => {:size => value}
|
31
|
+
end
|
32
|
+
|
33
|
+
# sets the :from param so it will return the nth page of size :size
|
34
|
+
def page(value)
|
35
|
+
deep_merge :page => value || 1
|
36
|
+
end
|
37
|
+
|
38
|
+
# the standard :params variable
|
39
|
+
def params(value)
|
40
|
+
deep_merge :params => value
|
41
|
+
end
|
42
|
+
|
43
|
+
# meaningful alias of deep_merge
|
44
|
+
def variables(*variables)
|
45
|
+
deep_merge *variables
|
46
|
+
end
|
47
|
+
|
48
|
+
def index(val)
|
49
|
+
deep_merge :index => val
|
50
|
+
end
|
51
|
+
|
52
|
+
def type(val)
|
53
|
+
deep_merge :type => val
|
54
|
+
end
|
55
|
+
|
56
|
+
# script_fields(:my_field => 'script ...', # simpler form
|
57
|
+
# :my_other_field => {:script => 'script ...', ...}) # ES API
|
58
|
+
def script_fields(hash)
|
59
|
+
hash.keys.each do |k|
|
60
|
+
v = hash[k]
|
61
|
+
hash[k] = {:script => v} unless v.is_a?(Hash)
|
62
|
+
hash[k][:script].gsub!(/\n+\s*/,' ')
|
63
|
+
end
|
64
|
+
deep_merge :script_fields => hash
|
65
|
+
end
|
66
|
+
|
67
|
+
def facets(hash)
|
68
|
+
deep_merge :facets => hash
|
69
|
+
end
|
70
|
+
|
71
|
+
def highlight(hash)
|
72
|
+
deep_merge :highlight => hash
|
73
|
+
end
|
74
|
+
|
75
|
+
def metrics
|
76
|
+
deep_merge :params => {:search_type => 'count'}
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/flex/scopes.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
module Flex
|
2
|
+
module Scopes
|
3
|
+
|
4
|
+
def self.included(context)
|
5
|
+
context.class_eval do
|
6
|
+
@flex ||= ClassProxy::Base.new(context)
|
7
|
+
def self.flex; @flex end
|
8
|
+
|
9
|
+
extend ClassMethods
|
10
|
+
|
11
|
+
@scope_methods = []
|
12
|
+
def self.scope_methods; @scope_methods end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
|
18
|
+
# Scope methods. They returns a Scope object similar to AR.
|
19
|
+
# You can chain scopes, then you can call :count, :first, :all and :scan_all to get your result
|
20
|
+
# See Flex::Scope
|
21
|
+
#
|
22
|
+
# scoped = MyModel.terms(:field_one => 'something', :field_two => nil)
|
23
|
+
# .sort(:field_three => :desc)
|
24
|
+
# .filters(:range => {:created_at => {:from => 2.days.ago, :to => Time.now})
|
25
|
+
# .fields('field_one,field_two,field_three') # or [:field_one, :field_two, ...]
|
26
|
+
# .params(:any => 'param')
|
27
|
+
#
|
28
|
+
# # add another filter or other terms at any time
|
29
|
+
# scoped2 = scoped.terms(...).filters(...)
|
30
|
+
#
|
31
|
+
# scoped2.count
|
32
|
+
# scoped2.first
|
33
|
+
# scoped2.all
|
34
|
+
# scoped2.scan_all {|batch| do_something_with_results batch}
|
35
|
+
#
|
36
|
+
Utils.define_delegation :to => :scoped,
|
37
|
+
:in => self,
|
38
|
+
:by => :module_eval,
|
39
|
+
:for => Scope::SCOPED_METHODS
|
40
|
+
|
41
|
+
|
42
|
+
# You can start with a non restricted Flex::Scope object
|
43
|
+
def scoped
|
44
|
+
@scoped ||= Scope[:context => flex.context]
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
# define scopes as class methods
|
49
|
+
#
|
50
|
+
# class MyModel
|
51
|
+
# include Flex::StoredModel
|
52
|
+
# ...
|
53
|
+
# scope :red, terms(:color => 'red').sort(:supplier => :asc)
|
54
|
+
# scope :size do |size|
|
55
|
+
# terms(:size => size)
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# MyModel.size('large').first
|
59
|
+
# MyModel.red.all
|
60
|
+
# MyModel.size('small').red.all
|
61
|
+
#
|
62
|
+
def scope(name, scope=nil, &block)
|
63
|
+
raise ArgumentError, "Dangerous scope name: a :#{name} method is already defined. Please, use another one." \
|
64
|
+
if respond_to?(name)
|
65
|
+
proc = case
|
66
|
+
when block_given?
|
67
|
+
block
|
68
|
+
when scope.is_a?(Flex::Scope)
|
69
|
+
lambda {scope}
|
70
|
+
when scope.is_a?(Proc)
|
71
|
+
scope
|
72
|
+
else
|
73
|
+
raise ArgumentError, "Scope object or Proc expected (got #{scope.inspect})"
|
74
|
+
end
|
75
|
+
metaclass = class << self; self end
|
76
|
+
metaclass.send(:define_method, name) do |*args|
|
77
|
+
scope = proc.call(*args)
|
78
|
+
raise Scope::Error, "The scope :#{name} does not return a Flex::Scope object (got #{scope.inspect})" \
|
79
|
+
unless scope.is_a?(Flex::Scope)
|
80
|
+
scope
|
81
|
+
end
|
82
|
+
scope_methods << name
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: flex-scopes
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Domizio Demichelis
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-08-12 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: flex
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - '='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.0.1
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - '='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.0.1
|
30
|
+
description: Provides an easy to use ruby API to search elasticsearch with ActiveRecord-like
|
31
|
+
chainable and mergeables scopes.
|
32
|
+
email: dd.nexus@gmail.com
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files:
|
36
|
+
- README.md
|
37
|
+
files:
|
38
|
+
- LICENSE
|
39
|
+
- README.md
|
40
|
+
- VERSION
|
41
|
+
- flex-scopes.gemspec
|
42
|
+
- lib/flex-scopes.rb
|
43
|
+
- lib/flex/result/scope.rb
|
44
|
+
- lib/flex/scope.rb
|
45
|
+
- lib/flex/scope/filter_methods.rb
|
46
|
+
- lib/flex/scope/queries.yml
|
47
|
+
- lib/flex/scope/query_methods.rb
|
48
|
+
- lib/flex/scope/utils.rb
|
49
|
+
- lib/flex/scope/vars_methods.rb
|
50
|
+
- lib/flex/scopes.rb
|
51
|
+
homepage: http://github.com/ddnexus/flex-scopes
|
52
|
+
licenses: []
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options:
|
55
|
+
- --charset=UTF-8
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ! '>='
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.3.6
|
70
|
+
requirements: []
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 1.8.25
|
73
|
+
signing_key:
|
74
|
+
specification_version: 3
|
75
|
+
summary: ActiveRecord-like chainable scopes and finders for Flex.
|
76
|
+
test_files: []
|