arspy 0.0.5 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +10 -0
- data/Rakefile +1 -1
- data/lib/arspy/class_extensions.rb +2 -2
- data/lib/arspy/delegators/active_record_extensions.rb +2 -2
- data/lib/arspy/delegators/array_extensions.rb +4 -4
- data/lib/arspy/delegators/association_collection_extensions.rb +4 -4
- data/lib/arspy/delegators/null_extensions.rb +2 -2
- data/lib/arspy/operators/abbreviations.rb +68 -0
- data/lib/arspy/operators/attribute_test/base.rb +11 -0
- data/lib/arspy/operators/attribute_test/float_test.rb +24 -0
- data/lib/arspy/operators/attribute_test/integer_test.rb +24 -0
- data/lib/arspy/operators/attribute_test/range_test.rb +24 -0
- data/lib/arspy/operators/attribute_test/regexp_test.rb +23 -0
- data/lib/arspy/operators/attribute_test/string_test.rb +23 -0
- data/lib/arspy/operators/attribute_test/unsupported_test.rb +17 -0
- data/lib/arspy/operators/attribute_test.rb +20 -0
- data/lib/arspy/operators/interpreter/abbreviated_association_interpreter.rb +22 -0
- data/lib/arspy/operators/interpreter/abbreviated_attribute_interpreter.rb +22 -0
- data/lib/arspy/operators/interpreter/association_interpreter.rb +18 -0
- data/lib/arspy/operators/interpreter/attribute_interpreter.rb +21 -0
- data/lib/arspy/operators/interpreter/base.rb +11 -0
- data/lib/arspy/operators/interpreter/method_interpreter.rb +14 -0
- data/lib/arspy/operators/interpreter/null_interpreter.rb +12 -0
- data/lib/arspy/operators/interpreter.rb +29 -0
- data/lib/arspy/operators/selector/attribute_selector.rb +33 -0
- data/lib/arspy/operators/selector/base.rb +12 -0
- data/lib/arspy/operators/selector/hash_selector.rb +30 -0
- data/lib/arspy/operators/selector/integer_selector.rb +17 -0
- data/lib/arspy/operators/selector/range_selector.rb +17 -0
- data/lib/arspy/operators/selector/string_selector.rb +14 -0
- data/lib/arspy/operators/selector/unsupported_selector.rb +17 -0
- data/lib/arspy/operators/selector.rb +28 -0
- data/lib/arspy/operators.rb +40 -111
- data/lib/meta_programming/object.rb +2 -2
- data/spec/active_record.log +4327 -0
- data/spec/database.rb +85 -32
- data/spec/list_association_spec.rb +62 -0
- data/spec/list_field_spec.rb +5 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/with_command_spec.rb +106 -0
- metadata +39 -7
data/README.rdoc
CHANGED
@@ -113,6 +113,15 @@ Expressions using associations
|
|
113
113
|
Jenny Westmeyers 213 2
|
114
114
|
Maria Stone 8 88
|
115
115
|
|
116
|
+
=== Printing objects and classes
|
117
|
+
|
118
|
+
ARSpy integrates 'awesome print' to print lists of objects and classes. Print objects or
|
119
|
+
classes with the 'pr' command, or explicitly print with the 'ap' command.
|
120
|
+
|
121
|
+
User.ap # => prints the object attributes and columns with awesome print
|
122
|
+
User.find(2).blogs.title.pr #=> prints the titles of all blogs
|
123
|
+
User.find(2).blogs.pr # => prints the object fields and data usign awesome print
|
124
|
+
|
116
125
|
|
117
126
|
== Iterating Associations and Data
|
118
127
|
|
@@ -203,3 +212,4 @@ results that do not meet the conditions passed in the parameters.
|
|
203
212
|
|
204
213
|
* ActiveRecord
|
205
214
|
* ActiveSupport
|
215
|
+
* Awesome Print
|
data/Rakefile
CHANGED
@@ -12,7 +12,7 @@ spec = Gem::Specification.new do |s|
|
|
12
12
|
s.description = 'Active Record Spy'
|
13
13
|
s.summary = 'Rails console command line tool for browsing and inspecting the structure, associations and data of an ActiveRecord data model.'
|
14
14
|
|
15
|
-
s.add_dependency('awesome_print', '>= 0.1.
|
15
|
+
s.add_dependency('awesome_print', '>= 0.1.4')
|
16
16
|
|
17
17
|
exclude_folders = '' # 'spec/rails/{doc,lib,log,nbproject,tmp,vendor,test}'
|
18
18
|
exclude_files = [] # FileList['**/*.log'] + FileList[exclude_folders+'/**/*'] + FileList[exclude_folders]
|
@@ -2,8 +2,8 @@ module Arspy
|
|
2
2
|
module ClassExtensions
|
3
3
|
module ActiveRecord
|
4
4
|
module Base
|
5
|
-
def la; Arspy::Operators.list_associations(self); end
|
6
|
-
def lf; Arspy::Operators.list_fields(self); end
|
5
|
+
def la(*args); Arspy::Operators.list_associations(self, *args); end
|
6
|
+
def lf(*args); Arspy::Operators.list_fields(self, *args); end
|
7
7
|
def pr; Arspy::Operators.awesome_print(self); end
|
8
8
|
def ap(opts={}); Arspy::Operators.awesome_print(self, opts); end
|
9
9
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module Arspy
|
2
2
|
module Delegators
|
3
3
|
module ActiveRecordExtensions
|
4
|
-
def la; Arspy::Operators.list_associations(self.class); end
|
5
|
-
def lf; Arspy::Operators.list_fields(self.class); end
|
4
|
+
def la(*args); Arspy::Operators.list_associations(self.class, *args); end
|
5
|
+
def lf(*args); Arspy::Operators.list_fields(self.class, *args); end
|
6
6
|
def pr(*args); Arspy::Operators.print_object(self, *args); end
|
7
7
|
def ap(opts={}); Arspy::Operators.awesome_print(self, opts); end
|
8
8
|
end
|
@@ -13,11 +13,11 @@ module Arspy
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
def la
|
17
|
-
Arspy::Operators.list_associations(self.first) unless self.emtpy?
|
16
|
+
def la(*args)
|
17
|
+
Arspy::Operators.list_associations(self.first, *args) unless self.emtpy?
|
18
18
|
end
|
19
|
-
def lf
|
20
|
-
Arspy::Operators.list_fields(self.first) unless self.empty?
|
19
|
+
def lf(*args)
|
20
|
+
Arspy::Operators.list_fields(self.first, *args) unless self.empty?
|
21
21
|
end
|
22
22
|
def ap(opts={})
|
23
23
|
Arspy::Operators.awesome_print(self, opts={}) unless self.empty?
|
@@ -9,13 +9,13 @@ module Arspy
|
|
9
9
|
result
|
10
10
|
end
|
11
11
|
end
|
12
|
-
def la
|
12
|
+
def la(*args)
|
13
13
|
load_target unless loaded?
|
14
|
-
Arspy::Operators.list_associations(@target.first) unless @target.emtpy?
|
14
|
+
Arspy::Operators.list_associations(@target.first, *args) unless @target.emtpy?
|
15
15
|
end
|
16
|
-
def lf
|
16
|
+
def lf(*args)
|
17
17
|
load_target unless loaded?
|
18
|
-
Arspy::Operators.list_fields(@target.first) unless @target.empty?
|
18
|
+
Arspy::Operators.list_fields(@target.first, *args) unless @target.empty?
|
19
19
|
end
|
20
20
|
def pr(*args)
|
21
21
|
load_target unless loaded?
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Abbreviations
|
2
|
+
def self.included(base)
|
3
|
+
base.extend(ClassMethods)
|
4
|
+
end
|
5
|
+
|
6
|
+
def resolve_abbreviation_for_attributes_and_associations!(object, method_name)
|
7
|
+
self.class.resolve_abbreviation_for_attributes_and_associations!(object, method_name)
|
8
|
+
end
|
9
|
+
module ClassMethods
|
10
|
+
def resolve_abbreviation_for_attributes_and_associations!(object, method_name)
|
11
|
+
klass = object.class
|
12
|
+
setup_abbreviations(object) unless object.instance_variable_defined?('@arspy_abbreviations')
|
13
|
+
if (ambiguity = klass.instance_variable_get('@arspy_ambiguous_abbreviations')[method_name])
|
14
|
+
raise "Ambiguous abbreviation '#{ambiguity[:abbr]}' could be #{quote_and_join(ambiguity[:methods])}"
|
15
|
+
end
|
16
|
+
klass.instance_variable_get('@arspy_abbreviations')[method_name]
|
17
|
+
end
|
18
|
+
|
19
|
+
def setup_abbreviations(object)
|
20
|
+
associations = object.class.reflect_on_all_associations.map(&:name).map(&:to_sym)
|
21
|
+
attributes = object.attribute_names.map(&:to_sym)
|
22
|
+
assoc_descriptors = associations.map{|method_name| {:method_name=>method_name, :type=>:association, :abbr=>abbreviate_method_name(method_name)}}
|
23
|
+
attrib_descriptors = attributes.map{|method_name| {:method_name=>method_name, :type=>:attribute, :abbr=>abbreviate_method_name(method_name)}}
|
24
|
+
all_descriptors = assoc_descriptors + attrib_descriptors
|
25
|
+
object.class.instance_variable_set('@arspy_ambiguous_abbreviations', remove_ambiguities(all_descriptors))
|
26
|
+
object.class.instance_variable_set('@arspy_abbreviations', Hash[*all_descriptors.map{|desc| [desc[:abbr], desc] }.flatten])
|
27
|
+
end
|
28
|
+
def remove_ambiguities(descriptors)
|
29
|
+
list={}
|
30
|
+
ambiguities = {}
|
31
|
+
descriptors.each do |desc|
|
32
|
+
if list.include?(desc[:abbr])
|
33
|
+
if ambiguities[desc[:abbr]]
|
34
|
+
ambiguities[desc[:abbr]][:methods] << desc[:method_name]
|
35
|
+
else
|
36
|
+
ambiguities[desc[:abbr]] = {:abbr=>desc[:abbr], :methods=>[desc[:method_name]]}
|
37
|
+
ambiguities[desc[:abbr]][:methods] << list[desc[:abbr]][:method_name]
|
38
|
+
end
|
39
|
+
else
|
40
|
+
list[desc[:abbr]] = desc
|
41
|
+
end
|
42
|
+
end
|
43
|
+
descriptors.reject!{|desc| ambiguities.map{|hash| hash.first}.include?(desc[:abbr])}
|
44
|
+
ambiguities
|
45
|
+
end
|
46
|
+
def abbreviate_method_name(method_name)
|
47
|
+
words = method_name.to_s.split('_')
|
48
|
+
abbr=[]
|
49
|
+
if words.first == ''
|
50
|
+
abbr << '_'
|
51
|
+
end
|
52
|
+
words.reject!{|word| word == ''}
|
53
|
+
abbr += words.map do |word|
|
54
|
+
chars = word.split(//)
|
55
|
+
first = chars.shift
|
56
|
+
[first, chars.map{|ch| ch =~ /[0-9]/ ? ch : nil}].compact.flatten.join('')
|
57
|
+
end
|
58
|
+
|
59
|
+
abbr << '_' if (method_name.to_s =~ /_$/)
|
60
|
+
abbr.join('').to_sym
|
61
|
+
end
|
62
|
+
def quote_and_join(array)
|
63
|
+
return "'#{array.first}'" if array.size == 1
|
64
|
+
last = array.pop
|
65
|
+
"'#{array.join("', '")}' or '#{last}'"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Arspy
|
2
|
+
module Operators
|
3
|
+
module AttributeTest
|
4
|
+
|
5
|
+
|
6
|
+
class FloatTest < Base
|
7
|
+
|
8
|
+
def self.applies?(param)
|
9
|
+
param.is_a? Float
|
10
|
+
end
|
11
|
+
|
12
|
+
def match?(value_or_object)
|
13
|
+
case value_or_object
|
14
|
+
when ActiveRecord::Base
|
15
|
+
false
|
16
|
+
else
|
17
|
+
value_or_object.to_f == @param rescue nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Arspy
|
2
|
+
module Operators
|
3
|
+
module AttributeTest
|
4
|
+
|
5
|
+
|
6
|
+
class IntegerTest < Base
|
7
|
+
|
8
|
+
def self.applies?(param)
|
9
|
+
param.is_a? Integer
|
10
|
+
end
|
11
|
+
|
12
|
+
def match?(value_or_object)
|
13
|
+
case value_or_object
|
14
|
+
when ActiveRecord::Base
|
15
|
+
value_or_object.id == @param
|
16
|
+
else
|
17
|
+
value_or_object.to_i == @param rescue nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Arspy
|
2
|
+
module Operators
|
3
|
+
module AttributeTest
|
4
|
+
|
5
|
+
|
6
|
+
class RangeTest < Base
|
7
|
+
|
8
|
+
def self.applies?(param)
|
9
|
+
param.is_a? Range
|
10
|
+
end
|
11
|
+
|
12
|
+
def match?(value_or_object)
|
13
|
+
case value_or_object
|
14
|
+
when ActiveRecord::Base
|
15
|
+
@param.include?(value_or_object.id)
|
16
|
+
else
|
17
|
+
@param.include?(value_or_object.to_i)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Arspy
|
2
|
+
module Operators
|
3
|
+
module AttributeTest
|
4
|
+
|
5
|
+
class RegexpTest < Base
|
6
|
+
def self.applies?(param)
|
7
|
+
param.is_a? Regexp
|
8
|
+
end
|
9
|
+
|
10
|
+
def match?(value_or_object)
|
11
|
+
case value_or_object
|
12
|
+
when ActiveRecord::Base
|
13
|
+
raise "Test for '#{@param}' on object '#{value_or_object.class.name}' not supported."
|
14
|
+
else
|
15
|
+
value_or_object =~ @param
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Arspy
|
2
|
+
module Operators
|
3
|
+
module AttributeTest
|
4
|
+
|
5
|
+
class StringTest < Base
|
6
|
+
|
7
|
+
def self.applies?(param)
|
8
|
+
param.is_a? String
|
9
|
+
end
|
10
|
+
|
11
|
+
def match?(value_or_object)
|
12
|
+
case value_or_object
|
13
|
+
when ActiveRecord::Base
|
14
|
+
value_or_object.instance_eval{ value_or_object }
|
15
|
+
else
|
16
|
+
value_or_object.to_s == @param rescue nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Arspy
|
2
|
+
module Operators
|
3
|
+
module AttributeTest
|
4
|
+
class UnsupportedTest < Base
|
5
|
+
|
6
|
+
def self.applies?(param)
|
7
|
+
true
|
8
|
+
end
|
9
|
+
|
10
|
+
def match?(object)
|
11
|
+
raise "#{@param.class.name} '#{@param.inspect}' not supported."
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'arspy/operators/attribute_test/base'
|
2
|
+
require 'arspy/operators/attribute_test/integer_test'
|
3
|
+
require 'arspy/operators/attribute_test/range_test'
|
4
|
+
require 'arspy/operators/attribute_test/regexp_test'
|
5
|
+
require 'arspy/operators/attribute_test/string_test'
|
6
|
+
require 'arspy/operators/attribute_test/unsupported_test'
|
7
|
+
|
8
|
+
module Arspy
|
9
|
+
module Operators
|
10
|
+
module AttributeTest
|
11
|
+
@@attribute_test_classes = [
|
12
|
+
IntegerTest, RangeTest, StringTest, RegexpTest, UnsupportedTest
|
13
|
+
]
|
14
|
+
|
15
|
+
def self.for(param)
|
16
|
+
@@attribute_test_classes.detect{|klass| klass.applies?(param)}.new(param)
|
17
|
+
end
|
18
|
+
|
19
|
+
end end
|
20
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'arspy/operators/abbreviations'
|
2
|
+
module Arspy
|
3
|
+
module Operators
|
4
|
+
module Interpreter
|
5
|
+
class AbbreviatedAssociationInterpreter < AssociationInterpreter
|
6
|
+
include Abbreviations
|
7
|
+
|
8
|
+
def self.applies?(array, method_name)
|
9
|
+
descriptor = resolve_abbreviation_for_attributes_and_associations!(array.first, method_name)
|
10
|
+
descriptor && descriptor[:type] == :association
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(array, method_name)
|
14
|
+
descriptor = resolve_abbreviation_for_attributes_and_associations!(array.first, method_name)
|
15
|
+
super(array, descriptor[:method_name])
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'arspy/operators/abbreviations'
|
2
|
+
|
3
|
+
module Arspy
|
4
|
+
module Operators
|
5
|
+
module Interpreter
|
6
|
+
class AbbreviatedAttributeInterpreter < AttributeInterpreter
|
7
|
+
include Abbreviations
|
8
|
+
|
9
|
+
def self.applies?(array, method_name)
|
10
|
+
descriptor = resolve_abbreviation_for_attributes_and_associations!(array.first, method_name)
|
11
|
+
descriptor && descriptor[:type] == :attribute
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(array, method_name)
|
15
|
+
descriptor = resolve_abbreviation_for_attributes_and_associations!(array.first, method_name)
|
16
|
+
super(array, descriptor[:method_name])
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Arspy
|
2
|
+
module Operators
|
3
|
+
module Interpreter
|
4
|
+
|
5
|
+
class AssociationInterpreter < Base
|
6
|
+
|
7
|
+
def self.applies?(array, method_name)
|
8
|
+
array.first.class.reflect_on_all_associations.detect{|a| a.name == method_name}
|
9
|
+
end
|
10
|
+
|
11
|
+
def interpret(*args)
|
12
|
+
@array.map(&@method_name).flatten
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Arspy
|
2
|
+
module Operators
|
3
|
+
module Interpreter
|
4
|
+
class AttributeInterpreter < Base
|
5
|
+
|
6
|
+
def self.applies?(array, method_name)
|
7
|
+
array.first.attribute_names.include?(method_name.to_s)
|
8
|
+
end
|
9
|
+
|
10
|
+
def interpret(*args)
|
11
|
+
return @array.map(&@method_name) if args.empty?
|
12
|
+
raise 'Hash not supported as attribute conditionals' if args.any?{|arg| arg.is_a?(Hash)}
|
13
|
+
selector = Selector.for({@method_name => args})
|
14
|
+
@array.select{|obj| obj && selector.select?(obj)}
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Arspy
|
2
|
+
module Operators
|
3
|
+
module Interpreter
|
4
|
+
|
5
|
+
class MethodInterpreter < AttributeInterpreter
|
6
|
+
def self.applies?(array, method_name)
|
7
|
+
array.first.respond_to?(method_name) && array.first.method(method_name).arity == 0
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
require 'arspy/operators/interpreter/base'
|
3
|
+
require 'arspy/operators/interpreter/association_interpreter'
|
4
|
+
require 'arspy/operators/interpreter/attribute_interpreter'
|
5
|
+
require 'arspy/operators/interpreter/method_interpreter'
|
6
|
+
require 'arspy/operators/interpreter/abbreviated_association_interpreter'
|
7
|
+
require 'arspy/operators/interpreter/abbreviated_attribute_interpreter'
|
8
|
+
require 'arspy/operators/interpreter/null_interpreter'
|
9
|
+
|
10
|
+
module Arspy
|
11
|
+
module Operators
|
12
|
+
module Interpreter
|
13
|
+
@@interpreter_classes = [
|
14
|
+
AssociationInterpreter, AttributeInterpreter,
|
15
|
+
MethodInterpreter, AbbreviatedAssociationInterpreter,
|
16
|
+
AbbreviatedAttributeInterpreter,
|
17
|
+
NullInterpreter
|
18
|
+
]
|
19
|
+
|
20
|
+
def self.for(array, method_name)
|
21
|
+
return NullInterpreter.new(array, method_name) unless (array && method_name && array.is_a?(Array) && !array.empty? && array.first.is_a?(ActiveRecord::Base))
|
22
|
+
@@interpreter_classes.detect{|klass| klass.applies?(array, method_name)}.new(array, method_name)
|
23
|
+
end
|
24
|
+
|
25
|
+
@@abbreviations_enabled = true
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Arspy
|
2
|
+
module Operators
|
3
|
+
module Selector
|
4
|
+
|
5
|
+
class AttributeSelector < Base
|
6
|
+
def self.applies?(key_value)
|
7
|
+
key_value.first.is_a? Symbol
|
8
|
+
end
|
9
|
+
def initialize(key_value)
|
10
|
+
super
|
11
|
+
@attribute = key_value.first.to_sym
|
12
|
+
@test_values = key_value.last.is_a?(Array) ? key_value.last : [key_value.last]
|
13
|
+
end
|
14
|
+
|
15
|
+
def select?(obj)
|
16
|
+
raise "Attribute '#{@attribute}' not found for #{obj.class.name}" unless obj.attribute_names.include?(@attribute.to_s)
|
17
|
+
response = obj.__send__ @attribute
|
18
|
+
return nil unless response
|
19
|
+
raise "Attributes resulting in arrays not supported" if response.is_a?(Array)
|
20
|
+
response = [response] unless response.is_a?(Array)
|
21
|
+
response.any?{|value_or_object| attribute_tests.any?{|test| test.match?(value_or_object)}}
|
22
|
+
end
|
23
|
+
|
24
|
+
def attribute_tests
|
25
|
+
@attribute_tests ||= @test_values.map do |param|
|
26
|
+
AttributeTest.for(param)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Arspy
|
2
|
+
module Operators
|
3
|
+
module Selector
|
4
|
+
|
5
|
+
class HashSelector < Base
|
6
|
+
@@hash_selector_classes = [
|
7
|
+
Selector::AttributeSelector,
|
8
|
+
Selector::UnsupportedSelector
|
9
|
+
]
|
10
|
+
def self.applies?(arg)
|
11
|
+
arg.is_a? Hash
|
12
|
+
end
|
13
|
+
|
14
|
+
def select?(obj)
|
15
|
+
selectors.any?{|selector| selector.select?(obj) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def selectors
|
19
|
+
@selectors ||= @argument.map do |key_value|
|
20
|
+
hash_selector_class_for(key_value).new(key_value)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
def hash_selector_class_for(key_value)
|
24
|
+
@@hash_selector_classes.detect{|klass| klass.applies?(key_value) }
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Arspy
|
2
|
+
module Operators
|
3
|
+
module Selector
|
4
|
+
class UnsupportedSelector < Base
|
5
|
+
def self.applies?(arg)
|
6
|
+
true
|
7
|
+
end
|
8
|
+
def initialize(arg)
|
9
|
+
raise "#{arg.inspect} not supported."
|
10
|
+
end
|
11
|
+
def select?(obj)
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|