meta_search 0.5.0 → 0.5.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/CHANGELOG +3 -0
- data/VERSION +1 -1
- data/lib/meta_search/builder.rb +40 -1
- data/lib/meta_search/helpers/form_builder.rb +7 -11
- data/meta_search.gemspec +3 -2
- data/test/helper.rb +1 -1
- data/test/test_search.rb +38 -0
- data/test/test_view_helpers.rb +31 -31
- metadata +4 -3
data/CHANGELOG
ADDED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.1
|
data/lib/meta_search/builder.rb
CHANGED
@@ -37,7 +37,7 @@ module MetaSearch
|
|
37
37
|
@relation = base_or_relation.scoped
|
38
38
|
@base = @relation.klass
|
39
39
|
@opts = opts
|
40
|
-
@join_dependency =
|
40
|
+
@join_dependency = build_join_dependency
|
41
41
|
@search_attributes = {}
|
42
42
|
end
|
43
43
|
|
@@ -134,6 +134,45 @@ module MetaSearch
|
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
137
|
+
def build_join_dependency
|
138
|
+
joins = @relation.joins_values.map {|j| j.respond_to?(:strip) ? j.strip : j}.uniq
|
139
|
+
|
140
|
+
association_joins = joins.select do |j|
|
141
|
+
[Hash, Array, Symbol].include?(j.class) && !array_of_strings?(j)
|
142
|
+
end
|
143
|
+
|
144
|
+
stashed_association_joins = joins.select do |j|
|
145
|
+
j.is_a?(ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation)
|
146
|
+
end
|
147
|
+
|
148
|
+
non_association_joins = (joins - association_joins - stashed_association_joins)
|
149
|
+
custom_joins = custom_join_sql(*non_association_joins)
|
150
|
+
|
151
|
+
ActiveRecord::Associations::ClassMethods::JoinDependency.new(@base, association_joins, custom_joins)
|
152
|
+
end
|
153
|
+
|
154
|
+
def custom_join_sql(*joins)
|
155
|
+
arel = @relation.table
|
156
|
+
joins.each do |join|
|
157
|
+
next if join.blank?
|
158
|
+
|
159
|
+
case join
|
160
|
+
when Hash, Array, Symbol
|
161
|
+
if array_of_strings?(join)
|
162
|
+
join_string = join.join(' ')
|
163
|
+
arel = arel.join(join_string)
|
164
|
+
end
|
165
|
+
else
|
166
|
+
arel = arel.join(join)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
arel.joins(arel)
|
170
|
+
end
|
171
|
+
|
172
|
+
def array_of_strings?(o)
|
173
|
+
o.is_a?(Array) && o.all?{|obj| obj.is_a?(String)}
|
174
|
+
end
|
175
|
+
|
137
176
|
def build_sort_method
|
138
177
|
singleton_class.instance_eval do
|
139
178
|
define_method(:meta_sort) do
|
@@ -2,15 +2,11 @@ require 'action_view'
|
|
2
2
|
require 'action_view/template'
|
3
3
|
module MetaSearch
|
4
4
|
Check = Struct.new(:box, :label)
|
5
|
-
|
5
|
+
|
6
6
|
module Helpers
|
7
7
|
module FormBuilder
|
8
8
|
extend ActiveSupport::Concern
|
9
|
-
|
10
|
-
included do
|
11
|
-
self.field_helpers += ['multiparameter_field', 'check_boxes', 'collection_check_boxes']
|
12
|
-
end
|
13
|
-
|
9
|
+
|
14
10
|
# Like other form_for field methods (text_field, hidden_field, password_field) etc,
|
15
11
|
# but takes a list of hashes between the +method+ parameter and the trailing option hash,
|
16
12
|
# if any, to specify a number of fields to create in multiparameter fashion.
|
@@ -55,7 +51,7 @@ module MetaSearch
|
|
55
51
|
end
|
56
52
|
html
|
57
53
|
end
|
58
|
-
|
54
|
+
|
59
55
|
# Behaves almost exactly like the select method, but instead of generating a select tag,
|
60
56
|
# generates <tt>MetaSearch::Check</tt>s. These consist of two attributes, +box+ and +label+,
|
61
57
|
# which are (unsurprisingly) the HTML for the check box and the label. Called without a block,
|
@@ -107,13 +103,13 @@ module MetaSearch
|
|
107
103
|
end
|
108
104
|
collection_check_boxes(method, choices, :last, :first, options, &block)
|
109
105
|
end
|
110
|
-
|
106
|
+
|
111
107
|
# Just like +check_boxes+, but this time you can pass in a collection, value, and text method,
|
112
108
|
# as with collection_select.
|
113
109
|
#
|
114
110
|
# Example:
|
115
111
|
#
|
116
|
-
#
|
112
|
+
# <% f.collection_check_boxes :head_sizes_in, HeadSize.all,
|
117
113
|
# :id, :name, :class => 'headcheck' do |check| %>
|
118
114
|
# <%= check.box %> <%= check.label %>
|
119
115
|
# <% end %>
|
@@ -139,9 +135,9 @@ module MetaSearch
|
|
139
135
|
end
|
140
136
|
check_boxes unless block_given?
|
141
137
|
end
|
142
|
-
|
138
|
+
|
143
139
|
private
|
144
|
-
|
140
|
+
|
145
141
|
# If the last element of the arguments to multiparameter_field has no :field_type
|
146
142
|
# key, we assume it's got some defaults to be used in the other hashes.
|
147
143
|
def has_multiparameter_defaults?(args)
|
data/meta_search.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{meta_search}
|
8
|
-
s.version = "0.5.
|
8
|
+
s.version = "0.5.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Ernie Miller"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-07-20}
|
13
13
|
s.description = %q{
|
14
14
|
Allows simple search forms to be created against an AR3 model
|
15
15
|
and its associations, has useful view helpers for sort links
|
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
|
|
24
24
|
".document",
|
25
25
|
".gitignore",
|
26
26
|
".gitmodules",
|
27
|
+
"CHANGELOG",
|
27
28
|
"Gemfile",
|
28
29
|
"LICENSE",
|
29
30
|
"README.rdoc",
|
data/test/helper.rb
CHANGED
@@ -15,7 +15,7 @@ ActiveRecord::Base.establish_connection(
|
|
15
15
|
)
|
16
16
|
|
17
17
|
dep = defined?(ActiveSupport::Dependencies) ? ActiveSupport::Dependencies : ::Dependencies
|
18
|
-
dep.
|
18
|
+
dep.autoload_paths.unshift FIXTURES_PATH
|
19
19
|
|
20
20
|
ActiveRecord::Base.silence do
|
21
21
|
ActiveRecord::Migration.verbose = false
|
data/test/test_search.rb
CHANGED
@@ -562,4 +562,42 @@ class TestSearch < Test::Unit::TestCase
|
|
562
562
|
end
|
563
563
|
end
|
564
564
|
end
|
565
|
+
|
566
|
+
context_a_search_against "a relation derived from a joined association",
|
567
|
+
Company.where(:name => "Initech").first.developers do
|
568
|
+
should "not raise an error" do
|
569
|
+
assert_nothing_raised do
|
570
|
+
@s.all
|
571
|
+
end
|
572
|
+
end
|
573
|
+
|
574
|
+
should "return all developers for that company without conditions" do
|
575
|
+
assert_equal Company.where(:name => 'Initech').first.developers.all, @s.all
|
576
|
+
end
|
577
|
+
|
578
|
+
should "allow conditions on the search" do
|
579
|
+
@s.name_equals = 'Peter Gibbons'
|
580
|
+
assert_equal Developer.where(:name => 'Peter Gibbons').first,
|
581
|
+
@s.first
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
585
|
+
context_a_search_against "a relation derived from a joined HM:T association",
|
586
|
+
Company.where(:name => "Initech").first.developer_notes do
|
587
|
+
should "not raise an error" do
|
588
|
+
assert_nothing_raised do
|
589
|
+
@s.all
|
590
|
+
end
|
591
|
+
end
|
592
|
+
|
593
|
+
should "return all developer notes for that company without conditions" do
|
594
|
+
assert_equal Company.where(:name => 'Initech').first.developer_notes.all, @s.all
|
595
|
+
end
|
596
|
+
|
597
|
+
should "allow conditions on the search" do
|
598
|
+
@s.note_equals = 'A straight shooter with upper management written all over him.'
|
599
|
+
assert_equal Note.where(:note => 'A straight shooter with upper management written all over him.').first,
|
600
|
+
@s.first
|
601
|
+
end
|
602
|
+
end
|
565
603
|
end
|
data/test/test_view_helpers.rb
CHANGED
@@ -5,7 +5,7 @@ require 'action_view/test_case'
|
|
5
5
|
class TestViewHelpers < ActionView::TestCase
|
6
6
|
tests MetaSearch::Helpers::FormHelper
|
7
7
|
include MetaSearch::Helpers::UrlHelper
|
8
|
-
|
8
|
+
|
9
9
|
router = ActionDispatch::Routing::RouteSet.new
|
10
10
|
router.draw do |map|
|
11
11
|
resources :developers
|
@@ -15,23 +15,23 @@ class TestViewHelpers < ActionView::TestCase
|
|
15
15
|
match ':controller(/:action(/:id(.:format)))'
|
16
16
|
end
|
17
17
|
include router.url_helpers
|
18
|
-
|
18
|
+
|
19
19
|
def setup
|
20
20
|
@controller = Class.new do
|
21
|
-
|
21
|
+
|
22
22
|
attr_reader :url_for_options
|
23
23
|
def url_for(options)
|
24
24
|
@url_for_options = options
|
25
25
|
"http://www.example.com"
|
26
26
|
end
|
27
|
-
|
28
|
-
def
|
29
|
-
@
|
27
|
+
|
28
|
+
def _routes
|
29
|
+
@routes ||= ActionDispatch::Routing::RouteSet.new
|
30
30
|
end
|
31
31
|
end
|
32
32
|
@controller = @controller.new
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
context "A previously-filled search form" do
|
36
36
|
setup do
|
37
37
|
@s = Company.search
|
@@ -54,7 +54,7 @@ class TestViewHelpers < ActionView::TestCase
|
|
54
54
|
@f.text_field(:name_contains)
|
55
55
|
end
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
context "A form using mutiparameter_field with default size option" do
|
59
59
|
setup do
|
60
60
|
@s = Developer.search
|
@@ -62,9 +62,9 @@ class TestViewHelpers < ActionView::TestCase
|
|
62
62
|
@f = f
|
63
63
|
end
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
should "apply proper cast and default size attribute to text fields" do
|
67
|
-
html = @f.multiparameter_field :salary_in,
|
67
|
+
html = @f.multiparameter_field :salary_in,
|
68
68
|
{:field_type => :text_field, :type_cast => 'i'},
|
69
69
|
{:field_type => :text_field, :type_cast => 'i'}, :size => 10
|
70
70
|
assert_dom_equal '<input id="search_salary_in(1i)" name="search[salary_in(1i)]" ' +
|
@@ -74,7 +74,7 @@ class TestViewHelpers < ActionView::TestCase
|
|
74
74
|
html
|
75
75
|
end
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
context "A form using check_boxes with three choices" do
|
79
79
|
setup do
|
80
80
|
@s = Company.search
|
@@ -82,11 +82,11 @@ class TestViewHelpers < ActionView::TestCase
|
|
82
82
|
@f = f
|
83
83
|
end
|
84
84
|
end
|
85
|
-
|
85
|
+
|
86
86
|
should "return an array of check boxes without a block" do
|
87
87
|
assert @f.check_boxes(:id_in, [['One', 1], ['Two', 2], ['Three', 3]]).all?{|c| c.is_a?(MetaSearch::Check)}
|
88
88
|
end
|
89
|
-
|
89
|
+
|
90
90
|
should "generate the expected HTML with a block" do
|
91
91
|
expected = <<-EXPECTED
|
92
92
|
<p>
|
@@ -113,7 +113,7 @@ class TestViewHelpers < ActionView::TestCase
|
|
113
113
|
ERB
|
114
114
|
end
|
115
115
|
end
|
116
|
-
|
116
|
+
|
117
117
|
context "A form using check_boxes with three choices and a previous selection" do
|
118
118
|
setup do
|
119
119
|
@s = Company.search
|
@@ -122,11 +122,11 @@ class TestViewHelpers < ActionView::TestCase
|
|
122
122
|
@f = f
|
123
123
|
end
|
124
124
|
end
|
125
|
-
|
125
|
+
|
126
126
|
should "return an array of check boxes without a block" do
|
127
127
|
assert @f.check_boxes(:id_in, [['One', 1], ['Two', 2], ['Three', 3]]).all?{|c| c.is_a?(MetaSearch::Check)}
|
128
128
|
end
|
129
|
-
|
129
|
+
|
130
130
|
should "generate the expected HTML with a block" do
|
131
131
|
expected = <<-EXPECTED
|
132
132
|
<p>
|
@@ -152,7 +152,7 @@ class TestViewHelpers < ActionView::TestCase
|
|
152
152
|
<% end -%>
|
153
153
|
ERB
|
154
154
|
end
|
155
|
-
|
155
|
+
|
156
156
|
context "A form using collection_check_boxes with companies" do
|
157
157
|
setup do
|
158
158
|
@s = Company.search
|
@@ -160,11 +160,11 @@ class TestViewHelpers < ActionView::TestCase
|
|
160
160
|
@f = f
|
161
161
|
end
|
162
162
|
end
|
163
|
-
|
163
|
+
|
164
164
|
should "return an array of check boxes without a block" do
|
165
165
|
assert @f.collection_check_boxes(:id_in, Company.all, :id, :name).all?{|c| c.is_a?(MetaSearch::Check)}
|
166
166
|
end
|
167
|
-
|
167
|
+
|
168
168
|
should "generate the expected HTML with a block" do
|
169
169
|
@f.collection_check_boxes(:id_in, Company.all, :id, :name) do |c|
|
170
170
|
concat render :to => :string, :inline => "<p><%= c.label %> <%= c.box %></p>", :locals => {:c => c}
|
@@ -179,32 +179,32 @@ class TestViewHelpers < ActionView::TestCase
|
|
179
179
|
end
|
180
180
|
end
|
181
181
|
end
|
182
|
-
|
182
|
+
|
183
183
|
context "A company search" do
|
184
184
|
setup do
|
185
185
|
@s = Company.search
|
186
186
|
end
|
187
|
-
|
187
|
+
|
188
188
|
context "sorted by name ascending" do
|
189
189
|
setup do
|
190
190
|
@s.meta_sort = 'name.asc'
|
191
191
|
end
|
192
|
-
|
192
|
+
|
193
193
|
should "generate a sort link with an up arrow for the sorted column" do
|
194
194
|
assert_match /Name ▲/,
|
195
195
|
sort_link(@s, :name, :controller => 'companies')
|
196
196
|
end
|
197
|
-
|
197
|
+
|
198
198
|
should "not generate a sort link with an up arrow for a non-sorted column" do
|
199
199
|
assert_no_match /Created at ▲/,
|
200
200
|
sort_link(@s, :created_at, :controller => 'companies')
|
201
201
|
end
|
202
|
-
|
202
|
+
|
203
203
|
context "with existing search options" do
|
204
204
|
setup do
|
205
205
|
@s.name_contains = 'a'
|
206
206
|
end
|
207
|
-
|
207
|
+
|
208
208
|
should "maintain previous search options in its sort links" do
|
209
209
|
assert_match /search\[name_contains\]=a/,
|
210
210
|
sort_link(@s, :name, :controller => 'companies')
|
@@ -212,32 +212,32 @@ class TestViewHelpers < ActionView::TestCase
|
|
212
212
|
end
|
213
213
|
end
|
214
214
|
end
|
215
|
-
|
215
|
+
|
216
216
|
context "A developer search" do
|
217
217
|
setup do
|
218
218
|
@s = Developer.search
|
219
219
|
end
|
220
|
-
|
220
|
+
|
221
221
|
context "sorted by company name descending" do
|
222
222
|
setup do
|
223
223
|
@s.meta_sort = 'company_name.desc'
|
224
224
|
end
|
225
|
-
|
225
|
+
|
226
226
|
should "generate a sort link with a down arrow for the sorted column" do
|
227
227
|
assert_match /Company name ▼/,
|
228
228
|
sort_link(@s, :company_name, :controller => 'developers')
|
229
229
|
end
|
230
|
-
|
230
|
+
|
231
231
|
should "not generate a sort link with a down arrow for a non-sorted column" do
|
232
232
|
assert_no_match /Created at ▼/,
|
233
233
|
sort_link(@s, :created_at, :controller => 'developers')
|
234
234
|
end
|
235
|
-
|
235
|
+
|
236
236
|
context "with existing search options" do
|
237
237
|
setup do
|
238
238
|
@s.name_contains = 'a'
|
239
239
|
end
|
240
|
-
|
240
|
+
|
241
241
|
should "maintain previous search options in its sort links" do
|
242
242
|
assert_match /search\[name_contains\]=a/,
|
243
243
|
sort_link(@s, :company_name, :controller => 'companies')
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 5
|
8
|
-
-
|
9
|
-
version: 0.5.
|
8
|
+
- 1
|
9
|
+
version: 0.5.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Ernie Miller
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-07-20 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -106,6 +106,7 @@ files:
|
|
106
106
|
- .document
|
107
107
|
- .gitignore
|
108
108
|
- .gitmodules
|
109
|
+
- CHANGELOG
|
109
110
|
- Gemfile
|
110
111
|
- LICENSE
|
111
112
|
- README.rdoc
|