albanpeignier-searchapi 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/MIT-LICENSE +20 -0
- data/Manifest.txt +25 -0
- data/README +98 -0
- data/Rakefile +50 -0
- data/db/migrate/001_create_searchable.rb +33 -0
- data/init.rb +25 -0
- data/install.rb +1 -0
- data/lib/search_api.rb +13 -0
- data/lib/search_api/active_record_bridge.rb +385 -0
- data/lib/search_api/active_record_integration.rb +272 -0
- data/lib/search_api/bridge.rb +75 -0
- data/lib/search_api/callbacks.rb +65 -0
- data/lib/search_api/errors.rb +11 -0
- data/lib/search_api/search.rb +473 -0
- data/lib/search_api/sql_fragment.rb +98 -0
- data/lib/search_api/text_criterion.rb +132 -0
- data/searchapi.gemspec +35 -0
- data/tasks/search_api_tasks.rake +8 -0
- data/test/active_record_bridge_test.rb +488 -0
- data/test/active_record_integration_test.rb +49 -0
- data/test/bridge_test.rb +69 -0
- data/test/callbacks_test.rb +157 -0
- data/test/mock_model.rb +54 -0
- data/test/search_test.rb +340 -0
- data/uninstall.rb +1 -0
- metadata +98 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
RAILS_ENV = "test" unless defined?(RAILS_ENV)
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../../../../config/environment.rb'))
|
4
|
+
require 'search_api'
|
5
|
+
require 'active_record_bridge'
|
6
|
+
require 'active_record_integration'
|
7
|
+
require 'test/mock_model'
|
8
|
+
|
9
|
+
class ActiveRecordIntegrationTest < Test::Unit::TestCase
|
10
|
+
|
11
|
+
def setup
|
12
|
+
begin
|
13
|
+
Searchable.find(:first)
|
14
|
+
rescue
|
15
|
+
raise "run 'rake searchapi_migrate_test_db' in the application directory before running searchapi tests"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_integration
|
20
|
+
Searchable.class_eval do
|
21
|
+
has_search_api
|
22
|
+
|
23
|
+
search :old do |search|
|
24
|
+
if search.old
|
25
|
+
{ :conditions => ['age > 80'] }
|
26
|
+
else
|
27
|
+
{ :conditions => ['age < 80'] }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
assert_equivalent_request({:conditions => 'age > 80'},
|
34
|
+
{:conditions => {:old => true}})
|
35
|
+
|
36
|
+
assert_equivalent_request({:conditions => 'age < 80'},
|
37
|
+
{:conditions => {:old => false}})
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
|
43
|
+
def assert_equivalent_request(traditional_find_options, search_options)
|
44
|
+
traditional_result_ids = Searchable.find(:all, traditional_find_options).map(&:id).sort
|
45
|
+
search_result_ids = Searchable.find(:all, search_options).map(&:id).sort
|
46
|
+
assert !traditional_result_ids.empty?
|
47
|
+
assert_equal traditional_result_ids, search_result_ids
|
48
|
+
end
|
49
|
+
end
|
data/test/bridge_test.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
RAILS_ENV = "test" unless defined?(RAILS_ENV)
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../../../../config/environment.rb'))
|
4
|
+
require 'search_api'
|
5
|
+
require 'active_record_bridge'
|
6
|
+
require 'test/mock_model'
|
7
|
+
|
8
|
+
class BridgteTest < Test::Unit::TestCase
|
9
|
+
def test_rewriter_bridge
|
10
|
+
# create a search class
|
11
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
12
|
+
|
13
|
+
assert_nothing_raised do
|
14
|
+
search_class.class_eval do
|
15
|
+
model ModelWithRewriterBridge
|
16
|
+
search_accessor :a, :b
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# assert accessors are there, and store_as option is active
|
21
|
+
search = search_class.new(:a => '1', :b=>'2')
|
22
|
+
assert_equal 2, search.a
|
23
|
+
assert_equal 3, search.b
|
24
|
+
|
25
|
+
# assert find_options_for_xxx exist, and behave correctly
|
26
|
+
assert_equal 3, search.find_options_for_a
|
27
|
+
assert_equal 4, search.find_options_for_b
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_automatic_bridge
|
31
|
+
# create a search class
|
32
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
33
|
+
|
34
|
+
assert_nothing_raised do
|
35
|
+
search_class.class_eval do
|
36
|
+
model ModelWithAutomaticBridge
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# assert automatic search attributes are there
|
41
|
+
assert_equal [:a], search_class.search_attributes.sort
|
42
|
+
|
43
|
+
# assert accessors are there
|
44
|
+
search = search_class.new(:a => 'a')
|
45
|
+
assert_equal 'a', search.a
|
46
|
+
|
47
|
+
# assert find_options_for_a exists, and behaves correctly
|
48
|
+
assert_equal 'b', search.find_options_for_a
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_merger_bridge
|
52
|
+
# create a search class
|
53
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
54
|
+
|
55
|
+
assert_nothing_raised do
|
56
|
+
search_class.class_eval do
|
57
|
+
model ModelWithMergerBridge
|
58
|
+
search_accessor :a do |search| search.a end
|
59
|
+
search_accessor :b do |search| search.b end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# assert accessors are there, and store_as option is active
|
64
|
+
search = search_class.new(:a => 1, :b=>2)
|
65
|
+
assert_equal 3, search.find_options
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
RAILS_ENV = "test" unless defined?(RAILS_ENV)
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../../../../config/environment.rb'))
|
4
|
+
require 'search_api'
|
5
|
+
require 'active_record_bridge'
|
6
|
+
require 'test/mock_model'
|
7
|
+
|
8
|
+
class CallbacksTest < Test::Unit::TestCase
|
9
|
+
def test_before_find_options_method
|
10
|
+
# create a search class
|
11
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
12
|
+
|
13
|
+
search_class.class_eval do
|
14
|
+
model Searchable
|
15
|
+
end
|
16
|
+
|
17
|
+
# get some attributes that fills some find_options (should we test the test ?)
|
18
|
+
assert_not_equal search_class.new.find_options, search_class.new(:age=>12).find_options
|
19
|
+
|
20
|
+
# reopen the search class
|
21
|
+
search_class.class_eval do
|
22
|
+
def before_find_options
|
23
|
+
self.class.search_attributes.each do |search_attribute|
|
24
|
+
ignore!(search_attribute)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# those same attributes should now be ignored
|
30
|
+
assert_equal search_class.new.find_options, search_class.new(:age=>12).find_options
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def test_before_find_options_symbol
|
35
|
+
# create a search class
|
36
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
37
|
+
|
38
|
+
search_class.class_eval do
|
39
|
+
model Searchable
|
40
|
+
end
|
41
|
+
|
42
|
+
# get some attributes that fills some find_options (should we test the test ?)
|
43
|
+
assert_not_equal search_class.new.find_options, search_class.new(:age=>12).find_options
|
44
|
+
|
45
|
+
# reopen the search class
|
46
|
+
search_class.class_eval do
|
47
|
+
before_find_options :ignore_all_attributes
|
48
|
+
|
49
|
+
def ignore_all_attributes
|
50
|
+
self.class.search_attributes.each do |search_attribute|
|
51
|
+
ignore!(search_attribute)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# those same attributes should now be ignored
|
57
|
+
assert_equal search_class.new.find_options, search_class.new(:age=>12).find_options
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def test_before_find_options_symbol
|
62
|
+
# create a search class
|
63
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
64
|
+
|
65
|
+
search_class.class_eval do
|
66
|
+
model Searchable
|
67
|
+
end
|
68
|
+
|
69
|
+
# get some attributes that fills some find_options (should we test the test ?)
|
70
|
+
assert_not_equal search_class.new.find_options, search_class.new(:age=>12).find_options
|
71
|
+
|
72
|
+
# reopen the search class
|
73
|
+
search_class.class_eval do
|
74
|
+
before_find_options "self.ignore_all_attributes"
|
75
|
+
|
76
|
+
def ignore_all_attributes
|
77
|
+
self.class.search_attributes.each do |search_attribute|
|
78
|
+
ignore!(search_attribute)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# those same attributes should now be ignored
|
84
|
+
assert_equal search_class.new.find_options, search_class.new(:age=>12).find_options
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
def test_before_find_options_proc
|
89
|
+
# create a search class
|
90
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
91
|
+
|
92
|
+
search_class.class_eval do
|
93
|
+
model Searchable
|
94
|
+
end
|
95
|
+
|
96
|
+
# get some attributes that fills some find_options (should we test the test ?)
|
97
|
+
assert_not_equal search_class.new.find_options, search_class.new(:age=>12).find_options
|
98
|
+
|
99
|
+
# reopen the search class
|
100
|
+
search_class.class_eval do
|
101
|
+
before_find_options { |search| search.ignore_all_attributes }
|
102
|
+
|
103
|
+
def ignore_all_attributes
|
104
|
+
self.class.search_attributes.each do |search_attribute|
|
105
|
+
ignore!(search_attribute)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# those same attributes should now be ignored
|
111
|
+
assert_equal search_class.new.find_options, search_class.new(:age=>12).find_options
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
class BlackHole
|
116
|
+
# ignore all attributes of search
|
117
|
+
def before_find_options(search)
|
118
|
+
search.class.search_attributes.each do |search_attribute|
|
119
|
+
search.ignore!(search_attribute)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_before_find_options_object
|
125
|
+
# create a search class
|
126
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
127
|
+
|
128
|
+
search_class.class_eval do
|
129
|
+
model Searchable
|
130
|
+
end
|
131
|
+
|
132
|
+
# get some attributes that fills some find_options (should we test the test ?)
|
133
|
+
assert_not_equal search_class.new.find_options, search_class.new(:age=>12).find_options
|
134
|
+
|
135
|
+
# reopen the search class
|
136
|
+
search_class.class_eval do
|
137
|
+
before_find_options BlackHole.new
|
138
|
+
end
|
139
|
+
|
140
|
+
# those same attributes should now be ignored
|
141
|
+
assert_equal search_class.new.find_options, search_class.new(:age=>12).find_options
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_bad_before_find_options
|
145
|
+
# create a search class
|
146
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
147
|
+
|
148
|
+
search_class.class_eval do
|
149
|
+
model Searchable
|
150
|
+
before_find_options 1
|
151
|
+
end
|
152
|
+
|
153
|
+
assert_raise SearchApi::SearchApiError do
|
154
|
+
search_class.new.find_options
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
data/test/mock_model.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
class Searchable < ActiveRecord::Base
|
2
|
+
end
|
3
|
+
|
4
|
+
|
5
|
+
# bridge for testing of SearchAttributeBuilder rewriting
|
6
|
+
class RewriterBridge < SearchApi::Bridge::Base
|
7
|
+
def rewrite_search_attribute_builder(search_attribute_builder)
|
8
|
+
search_attribute_builder.options = { :store_as => proc do |x| x.to_i + 1 end }
|
9
|
+
search_attribute_builder.block = proc do |search| search.send(search_attribute_builder.name)+1 end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# model using RewriterBridge
|
14
|
+
class ModelWithRewriterBridge
|
15
|
+
class << self
|
16
|
+
def search_api_bridge
|
17
|
+
RewriterBridge.new
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
# bridge for testing of automatic search attributes
|
24
|
+
class AutomaticBridge < SearchApi::Bridge::Base
|
25
|
+
def automatic_search_attribute_builders(options)
|
26
|
+
[SearchApi::Search::SearchAttributeBuilder.new(:a) do |search| search.a.succ end]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# model using AutomaticBridge
|
31
|
+
class ModelWithAutomaticBridge
|
32
|
+
class << self
|
33
|
+
def search_api_bridge
|
34
|
+
AutomaticBridge.new
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
# bridge for testing of find options merging
|
41
|
+
class MergerBridge < SearchApi::Bridge::Base
|
42
|
+
def merge_find_options(options_array)
|
43
|
+
options_array.inject(0) { |sum, x| sum + x}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# model using MergerBridge
|
48
|
+
class ModelWithMergerBridge
|
49
|
+
class << self
|
50
|
+
def search_api_bridge
|
51
|
+
MergerBridge.new
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/test/search_test.rb
ADDED
@@ -0,0 +1,340 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
RAILS_ENV = "test" unless defined?(RAILS_ENV)
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../../../../config/environment.rb'))
|
4
|
+
require 'search_api'
|
5
|
+
require 'active_record_bridge'
|
6
|
+
require 'test/mock_model'
|
7
|
+
|
8
|
+
class SearchTest < Test::Unit::TestCase
|
9
|
+
def test_model
|
10
|
+
# create a search class
|
11
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
12
|
+
|
13
|
+
# assert model is a public method and that it behaves correctly
|
14
|
+
assert_nil search_class.model
|
15
|
+
|
16
|
+
# bad usage of ::SearchApi::Search.model
|
17
|
+
assert_raise ArgumentError do
|
18
|
+
search_class.class_eval do
|
19
|
+
model Searchable, Searchable
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# bad model
|
24
|
+
assert_raise ArgumentError do
|
25
|
+
search_class.class_eval do
|
26
|
+
model 1
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# assert ActiveRecord::Base can be used as a model.
|
31
|
+
assert_nothing_raised do
|
32
|
+
search_class.class_eval do
|
33
|
+
model Searchable
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# test reader behavior
|
38
|
+
assert_equal Searchable, search_class.model
|
39
|
+
|
40
|
+
# test unicity
|
41
|
+
assert_raise RuntimeError do
|
42
|
+
search_class.class_eval do
|
43
|
+
model Searchable
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_search_accessor
|
49
|
+
# create a search class
|
50
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
51
|
+
|
52
|
+
# correct usage of search_accessor
|
53
|
+
assert_nothing_raised do
|
54
|
+
search_class.class_eval do
|
55
|
+
search_accessor :a1
|
56
|
+
search_accessor 'a2', {}
|
57
|
+
search_accessor :a3, :a4
|
58
|
+
search_accessor :a5, 'a6', {}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# check bad options
|
63
|
+
assert_raise ArgumentError do
|
64
|
+
search_class.class_eval do
|
65
|
+
search_accessor :a7, :foo => :bar
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_search_attributes
|
71
|
+
# create a search class
|
72
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
73
|
+
|
74
|
+
# assert search_attributes is empty
|
75
|
+
assert_equal [], search_class.search_attributes
|
76
|
+
|
77
|
+
# define some search_accessors
|
78
|
+
search_class.class_eval do
|
79
|
+
search_accessor :a1
|
80
|
+
search_accessor 'a2', :a3, 'a4'
|
81
|
+
end
|
82
|
+
|
83
|
+
# assert search_attributes are symbols
|
84
|
+
assert search_class.search_attributes.all? { |x| x.is_a?(Symbol) }
|
85
|
+
|
86
|
+
# assert accessors are there
|
87
|
+
assert %w(a1 a2 a3 a4).all? { |search_attribute| search_class.search_attributes.include?(search_attribute.to_sym)}
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_initialize
|
91
|
+
# create a search class
|
92
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
93
|
+
|
94
|
+
# assert no instance can be created without a model
|
95
|
+
assert_raise RuntimeError do
|
96
|
+
search_class.new
|
97
|
+
end
|
98
|
+
|
99
|
+
# define some search_accessors
|
100
|
+
search_class.class_eval do
|
101
|
+
model Searchable
|
102
|
+
search_accessor :a, 'b'
|
103
|
+
end
|
104
|
+
|
105
|
+
# build an instance with an unknown attribute
|
106
|
+
assert_raise NoMethodError do
|
107
|
+
search_class.new(:foo=>22)
|
108
|
+
end
|
109
|
+
|
110
|
+
# build an instance with an unknown attribute
|
111
|
+
assert_raise NoMethodError do
|
112
|
+
search_class.new('foo'=>22)
|
113
|
+
end
|
114
|
+
|
115
|
+
# build an instance without attributes
|
116
|
+
assert_nothing_raised do
|
117
|
+
search_class.new
|
118
|
+
end
|
119
|
+
|
120
|
+
# assert all atributes are ignored for an instance built without attributes
|
121
|
+
search = search_class.new
|
122
|
+
assert search_class.search_attributes.all? { |search_attribute|
|
123
|
+
search.ignored?(search_attribute) &&
|
124
|
+
search.send("#{search_attribute}_ignored?")
|
125
|
+
}
|
126
|
+
|
127
|
+
# build an instance with attributes
|
128
|
+
assert_nothing_raised do
|
129
|
+
search_class.new(:age => 33, :funny => true, :name => 'jesus', :a => [], :b=>{}, :id => nil)
|
130
|
+
search_class.new('age' => 33, 'funny' => true, 'name' => 'jesus', 'a' => [], 'b'=>{}, 'id' => nil)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_default_values
|
135
|
+
# create a search class
|
136
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
137
|
+
|
138
|
+
# define some search_accessors
|
139
|
+
search_class.class_eval do
|
140
|
+
model Searchable
|
141
|
+
search_accessor :a, :default => 1
|
142
|
+
search_accessor :b
|
143
|
+
end
|
144
|
+
|
145
|
+
search = search_class.new
|
146
|
+
|
147
|
+
assert !search.ignored?(:a)
|
148
|
+
assert !search.a_ignored?
|
149
|
+
assert_equal 1, search.a
|
150
|
+
|
151
|
+
assert search.ignored?(:b)
|
152
|
+
assert search.b_ignored?
|
153
|
+
assert_equal SearchApi::Search.ignored, search.b
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_accessors
|
157
|
+
# create a search class
|
158
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
159
|
+
|
160
|
+
# define some search_accessors
|
161
|
+
search_class.class_eval do
|
162
|
+
model Searchable
|
163
|
+
search_accessor :a
|
164
|
+
end
|
165
|
+
|
166
|
+
# build an instance without attributes
|
167
|
+
search = search_class.new
|
168
|
+
|
169
|
+
# test default instance_methods are defined, and well-behaved
|
170
|
+
search_class.search_attributes.each do |attribute|
|
171
|
+
search.ignore!(attribute)
|
172
|
+
assert_equal true, search.send("#{attribute}?")
|
173
|
+
assert search.ignored?(attribute)
|
174
|
+
assert search.send("#{attribute}_ignored?")
|
175
|
+
|
176
|
+
search.send("#{attribute}=", nil)
|
177
|
+
assert_nil search.send(attribute)
|
178
|
+
assert_equal false, search.send("#{attribute}?")
|
179
|
+
assert !search.send("#{attribute}_ignored?")
|
180
|
+
assert !search.ignored?(attribute)
|
181
|
+
|
182
|
+
search.send("#{attribute}=", false)
|
183
|
+
assert_equal false, search.send(attribute)
|
184
|
+
assert_equal false, search.send("#{attribute}?")
|
185
|
+
assert !search.send("#{attribute}_ignored?")
|
186
|
+
assert !search.ignored?(attribute)
|
187
|
+
|
188
|
+
search.send("#{attribute}=", true)
|
189
|
+
assert_equal true, search.send(attribute)
|
190
|
+
assert_equal true, search.send("#{attribute}?")
|
191
|
+
assert !search.send("#{attribute}_ignored?")
|
192
|
+
assert !search.ignored?(attribute)
|
193
|
+
|
194
|
+
search.send("#{attribute}=", 'thing')
|
195
|
+
assert_equal 'thing', search.send(attribute)
|
196
|
+
assert_equal true, search.send("#{attribute}?")
|
197
|
+
assert !search.send("#{attribute}_ignored?")
|
198
|
+
assert !search.ignored?(attribute)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_attributes
|
203
|
+
# create a search class
|
204
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
205
|
+
|
206
|
+
# define some search_accessors
|
207
|
+
search_class.class_eval do
|
208
|
+
model Searchable
|
209
|
+
search_accessor :a, 'b'
|
210
|
+
end
|
211
|
+
|
212
|
+
# build an instance without attributes
|
213
|
+
search = search_class.new
|
214
|
+
|
215
|
+
# assert attributes keys are symbols
|
216
|
+
assert search.attributes.keys.all? { |x| x.is_a?(Symbol) }
|
217
|
+
|
218
|
+
# assert attributes keys are search_class.search_attributes
|
219
|
+
assert_equal search_class.search_attributes.map(&:to_s).sort, search.attributes.keys.map(&:to_s).sort
|
220
|
+
|
221
|
+
# build an instance with attributes
|
222
|
+
attributes = { 'age' => 33, :funny => true, 'name' => 'jesus', :a => [], 'b'=>{}, :id => nil }
|
223
|
+
search = search_class.new(Marshal.load(Marshal.dump(attributes)))
|
224
|
+
|
225
|
+
# assert set attributes values are what is expected
|
226
|
+
attributes.each do |key, value|
|
227
|
+
assert_equal value, search.attributes[key.to_sym]
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_attributes=
|
232
|
+
# create a search class
|
233
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
234
|
+
|
235
|
+
# define some search_accessors
|
236
|
+
search_class.class_eval do
|
237
|
+
model Searchable
|
238
|
+
search_accessor 'a', :b
|
239
|
+
end
|
240
|
+
|
241
|
+
# build an instance without attributes
|
242
|
+
search = search_class.new
|
243
|
+
|
244
|
+
# assert attributes can be set
|
245
|
+
attributes = { :age => 33, 'funny' => true, :name => 'jesus', 'a' => [], :b => {}, 'id' => nil }
|
246
|
+
assert_nothing_raised do
|
247
|
+
search.attributes = Marshal.load(Marshal.dump(attributes))
|
248
|
+
end
|
249
|
+
|
250
|
+
# assert set attributes values are what is expected
|
251
|
+
attributes.each do |key, value|
|
252
|
+
assert_equal value, search.attributes[key.to_sym]
|
253
|
+
end
|
254
|
+
|
255
|
+
# assert partial attributes can be set
|
256
|
+
search.attributes = nil
|
257
|
+
attributes.each do |key, value|
|
258
|
+
assert_equal value, search.attributes[key.to_sym]
|
259
|
+
end
|
260
|
+
|
261
|
+
search.attributes = {}
|
262
|
+
attributes.each do |key, value|
|
263
|
+
assert_equal value, search.attributes[key.to_sym]
|
264
|
+
end
|
265
|
+
|
266
|
+
search.attributes = { :a => 'thing', 'b' => 'other' }
|
267
|
+
attributes.update('a' => 'thing', :b => 'other').each do |key, value|
|
268
|
+
assert_equal value, search.attributes[key.to_sym]
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
def test_attributes_and_setters_equivalence
|
273
|
+
# create a search class
|
274
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
275
|
+
|
276
|
+
# define some search_accessors
|
277
|
+
search_class.class_eval do
|
278
|
+
model Searchable
|
279
|
+
search_accessor :a
|
280
|
+
end
|
281
|
+
|
282
|
+
# build an instance
|
283
|
+
search = search_class.new
|
284
|
+
|
285
|
+
# assert calling a setter alters attributes
|
286
|
+
search.a = 'thing'
|
287
|
+
assert_equal 'thing', search.attributes[:a]
|
288
|
+
|
289
|
+
# assert calling attributes= calls setters
|
290
|
+
assert_nothing_raised do
|
291
|
+
search.attributes = { :a => 12 }
|
292
|
+
end
|
293
|
+
def search.a=(value)
|
294
|
+
raise
|
295
|
+
end
|
296
|
+
assert_raise RuntimeError do
|
297
|
+
search.attributes = { :a => 12 }
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
def test_initialize_and_setters_equivalence
|
302
|
+
# create a search class
|
303
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
304
|
+
|
305
|
+
# define some search_accessors
|
306
|
+
search_class.class_eval do
|
307
|
+
model Searchable
|
308
|
+
search_accessor :a
|
309
|
+
end
|
310
|
+
|
311
|
+
assert_nothing_raised do
|
312
|
+
search_class.new(:a => 12)
|
313
|
+
end
|
314
|
+
search_class.class_eval do
|
315
|
+
define_method(:a=) do
|
316
|
+
raise
|
317
|
+
end
|
318
|
+
end
|
319
|
+
assert_raise RuntimeError do
|
320
|
+
search_class.new(:a => 12)
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
def test_store_as_option
|
325
|
+
# create a search class
|
326
|
+
search_class = Class.new(::SearchApi::Search::Base)
|
327
|
+
|
328
|
+
# define some search_accessors
|
329
|
+
search_class.class_eval do
|
330
|
+
model Searchable
|
331
|
+
search_accessor :a, :store_as => proc { |value| value+1 }
|
332
|
+
end
|
333
|
+
|
334
|
+
search = search_class.new
|
335
|
+
|
336
|
+
search.a = 1
|
337
|
+
assert_equal 2, search.a
|
338
|
+
end
|
339
|
+
|
340
|
+
end
|