meta_search 0.9.10 → 0.9.11
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +9 -0
- data/VERSION +1 -1
- data/lib/meta_search/builder.rb +12 -21
- data/lib/meta_search/join_dependency.rb +19 -21
- data/lib/meta_search/locale/en.yml +1 -0
- data/lib/meta_search/model_compatibility.rb +4 -1
- data/lib/meta_search/searches/active_record.rb +78 -7
- data/lib/meta_search.rb +9 -3
- data/meta_search.gemspec +2 -2
- data/test/fixtures/company.rb +5 -5
- data/test/fixtures/developer.rb +2 -2
- data/test/locales/flanders.yml +5 -0
- data/test/test_search.rb +124 -12
- data/test/test_view_helpers.rb +4 -0
- metadata +3 -3
data/CHANGELOG
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
Changes since 0.9.10 (2010-11-18):
|
2
|
+
* Skip attempts to sort if someone passes an empty string to meta_sort
|
3
|
+
* Allow conditions on search_methods, (attr|assoc)_(un)?searchable using :if.
|
4
|
+
Option should be an object that responds to call and accepts the
|
5
|
+
MetaSearch::Builder instance as a parameter. Unused options passed to the
|
6
|
+
Model.search method will be available for your conditions to act on.
|
7
|
+
* Access attribute setters if a param is supplied - @search.attr_name(val)
|
8
|
+
behaves like @search.attr_name = val
|
9
|
+
|
1
10
|
Changes since 0.9.9 (2010-11-15):
|
2
11
|
* Fix bug introduced by new polymorphic belongs_to association code in
|
3
12
|
honoring :url param to form_for
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.9.
|
1
|
+
0.9.11
|
data/lib/meta_search/builder.rb
CHANGED
@@ -22,38 +22,28 @@ module MetaSearch
|
|
22
22
|
include ModelCompatibility
|
23
23
|
include Utility
|
24
24
|
|
25
|
-
attr_reader :base, :relation, :search_key, :search_attributes, :join_dependency, :errors
|
25
|
+
attr_reader :base, :relation, :search_key, :search_attributes, :join_dependency, :errors, :options
|
26
26
|
delegate *RELATION_METHODS + [:to => :relation]
|
27
27
|
|
28
28
|
# Initialize a new Builder. Requires a base model to wrap, and supports a couple of options
|
29
29
|
# for how it will expose this model and its associations to your controllers/views.
|
30
30
|
def initialize(base_or_relation, opts = {})
|
31
|
+
opts = opts.dup
|
31
32
|
@relation = base_or_relation.scoped
|
32
33
|
@base = @relation.klass
|
33
|
-
@search_key = opts
|
34
|
+
@search_key = (opts.delete(:search_key) || 'search').to_s
|
35
|
+
@options = opts # Let's just hang on to other options for use in authorization blocks
|
34
36
|
@join_dependency = build_join_dependency
|
35
37
|
@search_attributes = {}
|
36
38
|
@errors = ActiveModel::Errors.new(self)
|
37
39
|
end
|
38
40
|
|
39
41
|
def get_column(column, base = @base)
|
40
|
-
base.columns_hash[column.to_s]
|
41
|
-
end
|
42
|
-
|
43
|
-
def base_excludes_attribute(base, column)
|
44
|
-
base._metasearch_include_attributes.blank? ?
|
45
|
-
base._metasearch_exclude_attributes.include?(column.to_s) :
|
46
|
-
!base._metasearch_include_attributes.include?(column.to_s)
|
42
|
+
base.columns_hash[column.to_s] if base._metasearch_attribute_authorized?(column, self)
|
47
43
|
end
|
48
44
|
|
49
45
|
def get_association(assoc, base = @base)
|
50
|
-
base.reflect_on_association(assoc.to_sym)
|
51
|
-
end
|
52
|
-
|
53
|
-
def base_excludes_association(base, assoc)
|
54
|
-
base._metasearch_include_associations.blank? ?
|
55
|
-
base._metasearch_exclude_associations.include?(assoc.to_s) :
|
56
|
-
!base._metasearch_include_associations.include?(assoc.to_s)
|
46
|
+
base.reflect_on_association(assoc.to_sym) if base._metasearch_association_authorized?(assoc, self)
|
57
47
|
end
|
58
48
|
|
59
49
|
def get_attribute(name, parent = @join_dependency.join_base)
|
@@ -134,16 +124,16 @@ module MetaSearch
|
|
134
124
|
def method_missing(method_id, *args, &block)
|
135
125
|
method_name = method_id.to_s
|
136
126
|
if method_name =~ /^meta_sort=?$/
|
137
|
-
method_name =~ /=$/ ? set_sort(args.first) : get_sort
|
127
|
+
(args.any? || method_name =~ /=$/) ? set_sort(args.first) : get_sort
|
138
128
|
elsif match = method_name.match(/^(.*)\(([0-9]+).*\)$/) # Multiparameter reader
|
139
129
|
method_name, index = match.captures
|
140
130
|
vals = self.send(method_name)
|
141
131
|
vals.is_a?(Array) ? vals[index.to_i - 1] : nil
|
142
132
|
elsif match = matches_named_method(method_name)
|
143
|
-
method_name =~ /=$/ ? set_named_method_value(match, args.first) : get_named_method_value(match)
|
133
|
+
(args.any? || method_name =~ /=$/) ? set_named_method_value(match, args.first) : get_named_method_value(match)
|
144
134
|
elsif match = matches_attribute_method(method_id)
|
145
135
|
attribute, predicate = match.captures
|
146
|
-
|
136
|
+
(args.any? || method_name =~ /=$/) ? set_attribute_method_value(attribute, predicate, args.first) : get_attribute_method_value(attribute, predicate)
|
147
137
|
else
|
148
138
|
super
|
149
139
|
end
|
@@ -151,7 +141,7 @@ module MetaSearch
|
|
151
141
|
|
152
142
|
def matches_named_method(name)
|
153
143
|
method_name = name.to_s.sub(/\=$/, '')
|
154
|
-
return method_name if @base.
|
144
|
+
return method_name if @base._metasearch_method_authorized?(method_name, self)
|
155
145
|
end
|
156
146
|
|
157
147
|
def matches_attribute_method(method_id)
|
@@ -172,6 +162,7 @@ module MetaSearch
|
|
172
162
|
end
|
173
163
|
|
174
164
|
def set_sort(val)
|
165
|
+
return if val.blank?
|
175
166
|
column, direction = val.split('.')
|
176
167
|
direction ||= 'asc'
|
177
168
|
if ['asc','desc'].include?(direction)
|
@@ -199,7 +190,7 @@ module MetaSearch
|
|
199
190
|
end
|
200
191
|
|
201
192
|
def set_named_method_value(name, val)
|
202
|
-
meth = @base._metasearch_methods[name]
|
193
|
+
meth = @base._metasearch_methods[name][:method]
|
203
194
|
search_attributes[name] = meth.cast_param(val)
|
204
195
|
if meth.validate(search_attributes[name])
|
205
196
|
return_value = meth.evaluate(@relation, search_attributes[name])
|
@@ -22,25 +22,27 @@ module MetaSearch
|
|
22
22
|
|
23
23
|
protected
|
24
24
|
|
25
|
-
def build_with_metasearch(
|
25
|
+
def build_with_metasearch(associations, parent = nil, join_type = Arel::Nodes::InnerJoin, polymorphic_class = nil)
|
26
26
|
parent ||= @joins.last
|
27
|
-
|
27
|
+
|
28
|
+
case associations
|
28
29
|
when Symbol, String
|
29
|
-
reflection = parent.reflections[
|
30
|
-
|
31
|
-
|
30
|
+
reflection = parent.reflections[associations.to_s.intern] or
|
31
|
+
raise ConfigurationError, "Association named '#{ association }' was not found; perhaps you misspelled it?"
|
32
|
+
unless (association = find_join_association(reflection, parent)) && (!polymorphic_class || association.active_record == polymorphic_class)
|
32
33
|
@reflections << reflection
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
if reflection.options[:polymorphic]
|
35
|
+
raise ArgumentError, "You can't create a polymorphic belongs_to join without specifying the polymorphic class!" unless polymorphic_class
|
36
|
+
association = build_polymorphic_join_association(reflection, parent, polymorphic_class)
|
37
|
+
else
|
38
|
+
association = build_join_association(reflection, parent)
|
39
|
+
end
|
39
40
|
association.join_type = join_type
|
40
41
|
@joins << association
|
41
42
|
end
|
43
|
+
association
|
42
44
|
else
|
43
|
-
build(
|
45
|
+
build(associations, parent, join_type)
|
44
46
|
end
|
45
47
|
end
|
46
48
|
|
@@ -58,12 +60,12 @@ module MetaSearch
|
|
58
60
|
@join_dependency = join_dependency
|
59
61
|
@parent = parent || join_dependency.join_base
|
60
62
|
@reflection = reflection.clone
|
61
|
-
@reflection.
|
63
|
+
@reflection.instance_variable_set(:"@klass", polymorphic_class)
|
62
64
|
@aliased_prefix = "t#{ join_dependency.joins.size }"
|
63
65
|
@parent_table_name = @parent.active_record.table_name
|
64
66
|
@aliased_table_name = aliased_table_name_for(table_name)
|
65
67
|
@join = nil
|
66
|
-
@join_type
|
68
|
+
@join_type = Arel::Nodes::InnerJoin
|
67
69
|
end
|
68
70
|
|
69
71
|
def ==(other)
|
@@ -81,15 +83,11 @@ module MetaSearch
|
|
81
83
|
|
82
84
|
@join = [
|
83
85
|
aliased_table[options[:primary_key] || reflection.klass.primary_key].eq(parent_table[options[:foreign_key] || reflection.primary_key_name]),
|
84
|
-
parent_table[options[:foreign_type]].eq(active_record.
|
86
|
+
parent_table[options[:foreign_type]].eq(active_record.name)
|
85
87
|
]
|
86
88
|
|
87
|
-
|
88
|
-
|
89
|
-
sti_condition = sti_column.eq(klass.sti_name)
|
90
|
-
klass.descendants.each {|subclass| sti_condition = sti_condition.or(sti_column.eq(subclass.sti_name)) }
|
91
|
-
|
92
|
-
@join << sti_condition
|
89
|
+
if options[:conditions]
|
90
|
+
@join << interpolate_sql(sanitize_sql(options[:conditions], aliased_table_name))
|
93
91
|
end
|
94
92
|
|
95
93
|
@join
|
@@ -58,13 +58,16 @@ module MetaSearch
|
|
58
58
|
if method_name
|
59
59
|
predicate = Where.get(method_name)[:name]
|
60
60
|
predicate_attribute = method_name.sub(/_#{predicate}=?$/, '')
|
61
|
+
predicate_attributes = predicate_attribute.split(/_or_/).map { |att|
|
62
|
+
klass.human_attribute_name(att)
|
63
|
+
}.join(" #{I18n.translate(:"meta_search.or", :default => 'or')} ")
|
61
64
|
defaults << :"meta_search.predicates.#{predicate}"
|
62
65
|
end
|
63
66
|
|
64
67
|
defaults << options.delete(:default) if options[:default]
|
65
68
|
defaults << attribute.to_s.humanize
|
66
69
|
|
67
|
-
options.reverse_merge! :count => 1, :default => defaults, :attribute => klass.human_attribute_name(
|
70
|
+
options.reverse_merge! :count => 1, :default => defaults, :attribute => predicate_attributes || klass.human_attribute_name(attribute)
|
68
71
|
I18n.translate(defaults.shift, options)
|
69
72
|
end
|
70
73
|
end
|
@@ -17,7 +17,7 @@ module MetaSearch
|
|
17
17
|
self._metasearch_include_attributes =
|
18
18
|
self._metasearch_exclude_attributes =
|
19
19
|
self._metasearch_exclude_associations =
|
20
|
-
self._metasearch_include_associations =
|
20
|
+
self._metasearch_include_associations = {}
|
21
21
|
self._metasearch_methods = {}
|
22
22
|
end
|
23
23
|
end
|
@@ -34,6 +34,30 @@ module MetaSearch
|
|
34
34
|
|
35
35
|
alias_method :search, :metasearch unless respond_to?(:search)
|
36
36
|
|
37
|
+
def _metasearch_method_authorized?(name, metasearch_object)
|
38
|
+
name = name.to_s
|
39
|
+
meth = self._metasearch_methods[name]
|
40
|
+
meth && (meth[:if] ? meth[:if].call(metasearch_object) : true)
|
41
|
+
end
|
42
|
+
|
43
|
+
def _metasearch_attribute_authorized?(name, metasearch_object)
|
44
|
+
name = name.to_s
|
45
|
+
if self._metasearch_include_attributes.empty?
|
46
|
+
!_metasearch_excludes_attribute?(name, metasearch_object)
|
47
|
+
else
|
48
|
+
_metasearch_includes_attribute?(name, metasearch_object)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def _metasearch_association_authorized?(name, metasearch_object)
|
53
|
+
name = name.to_s
|
54
|
+
if self._metasearch_include_associations.empty?
|
55
|
+
!_metasearch_excludes_association?(name, metasearch_object)
|
56
|
+
else
|
57
|
+
_metasearch_includes_association?(name, metasearch_object)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
37
61
|
private
|
38
62
|
|
39
63
|
# Excludes model attributes from searchability. This means that searches can't be created against
|
@@ -43,10 +67,15 @@ module MetaSearch
|
|
43
67
|
# like <tt>:user_id_equals</tt>, nor will an Article.search accept the parameter
|
44
68
|
# <tt>:comments_user_id_equals</tt>.
|
45
69
|
def attr_unsearchable(*args)
|
70
|
+
opts = args.extract_options!
|
46
71
|
args.flatten.each do |attr|
|
47
72
|
attr = attr.to_s
|
48
73
|
raise(ArgumentError, "No persisted attribute (column) named #{attr} in #{self}") unless self.columns_hash.has_key?(attr)
|
49
|
-
self._metasearch_exclude_attributes =
|
74
|
+
self._metasearch_exclude_attributes = self._metasearch_exclude_attributes.merge(
|
75
|
+
attr => {
|
76
|
+
:if => opts[:if]
|
77
|
+
}
|
78
|
+
)
|
50
79
|
end
|
51
80
|
end
|
52
81
|
|
@@ -54,10 +83,15 @@ module MetaSearch
|
|
54
83
|
# <tt>attr_searchable</tt> and <tt>attr_unsearchable</tt> are present, the latter
|
55
84
|
# is ignored.
|
56
85
|
def attr_searchable(*args)
|
86
|
+
opts = args.extract_options!
|
57
87
|
args.flatten.each do |attr|
|
58
88
|
attr = attr.to_s
|
59
89
|
raise(ArgumentError, "No persisted attribute (column) named #{attr} in #{self}") unless self.columns_hash.has_key?(attr)
|
60
|
-
self._metasearch_include_attributes =
|
90
|
+
self._metasearch_include_attributes = self._metasearch_include_attributes.merge(
|
91
|
+
attr => {
|
92
|
+
:if => opts[:if]
|
93
|
+
}
|
94
|
+
)
|
61
95
|
end
|
62
96
|
end
|
63
97
|
|
@@ -66,31 +100,68 @@ module MetaSearch
|
|
66
100
|
# searching by declaring <tt>assoc_unsearchable :comments</tt> won't make any of the
|
67
101
|
# <tt>comments_*</tt> methods available.
|
68
102
|
def assoc_unsearchable(*args)
|
103
|
+
opts = args.extract_options!
|
69
104
|
args.flatten.each do |assoc|
|
70
105
|
assoc = assoc.to_s
|
71
106
|
raise(ArgumentError, "No such association #{assoc} in #{self}") unless self.reflect_on_all_associations.map {|a| a.name.to_s}.include?(assoc)
|
72
|
-
self._metasearch_exclude_associations =
|
107
|
+
self._metasearch_exclude_associations = self._metasearch_exclude_associations.merge(
|
108
|
+
assoc => {
|
109
|
+
:if => opts[:if]
|
110
|
+
}
|
111
|
+
)
|
73
112
|
end
|
74
113
|
end
|
75
114
|
|
76
115
|
# As with <tt>attr_searchable</tt> this is the whitelist version of
|
77
116
|
# <tt>assoc_unsearchable</tt>
|
78
117
|
def assoc_searchable(*args)
|
118
|
+
opts = args.extract_options!
|
79
119
|
args.flatten.each do |assoc|
|
80
120
|
assoc = assoc.to_s
|
81
121
|
raise(ArgumentError, "No such association #{assoc} in #{self}") unless self.reflect_on_all_associations.map {|a| a.name.to_s}.include?(assoc)
|
82
|
-
self._metasearch_include_associations =
|
122
|
+
self._metasearch_include_associations = self._metasearch_include_associations.merge(
|
123
|
+
assoc => {
|
124
|
+
:if => opts[:if]
|
125
|
+
}
|
126
|
+
)
|
83
127
|
end
|
84
128
|
end
|
85
129
|
|
86
130
|
def search_methods(*args)
|
87
|
-
opts = args.
|
131
|
+
opts = args.extract_options!
|
132
|
+
authorizer = opts.delete(:if)
|
88
133
|
args.flatten.map(&:to_s).each do |arg|
|
89
|
-
self._metasearch_methods
|
134
|
+
self._metasearch_methods = self._metasearch_methods.merge(
|
135
|
+
arg => {
|
136
|
+
:method => MetaSearch::Method.new(arg, opts),
|
137
|
+
:if => authorizer
|
138
|
+
}
|
139
|
+
)
|
90
140
|
end
|
91
141
|
end
|
92
142
|
|
93
143
|
alias_method :search_method, :search_methods
|
144
|
+
|
145
|
+
def _metasearch_includes_attribute?(name, metasearch_object)
|
146
|
+
attr = self._metasearch_include_attributes[name]
|
147
|
+
attr && (attr[:if] ? attr[:if].call(metasearch_object) : true)
|
148
|
+
end
|
149
|
+
|
150
|
+
def _metasearch_excludes_attribute?(name, metasearch_object)
|
151
|
+
attr = self._metasearch_exclude_attributes[name]
|
152
|
+
attr && (attr[:if] ? attr[:if].call(metasearch_object) : true)
|
153
|
+
end
|
154
|
+
|
155
|
+
def _metasearch_includes_association?(name, metasearch_object)
|
156
|
+
assoc = self._metasearch_include_associations[name]
|
157
|
+
assoc && (assoc[:if] ? assoc[:if].call(metasearch_object) : true)
|
158
|
+
end
|
159
|
+
|
160
|
+
def _metasearch_excludes_association?(name, metasearch_object)
|
161
|
+
assoc = self._metasearch_exclude_associations[name]
|
162
|
+
assoc && (assoc[:if] ? assoc[:if].call(metasearch_object) : true)
|
163
|
+
end
|
164
|
+
|
94
165
|
end
|
95
166
|
end
|
96
167
|
|
data/lib/meta_search.rb
CHANGED
@@ -32,9 +32,15 @@ module MetaSearch
|
|
32
32
|
['is_not_null', {:types => ALL_TYPES, :predicate => :not_eq, :skip_compounds => true, :cast => :boolean, :formatter => Proc.new {|param| nil}}]
|
33
33
|
]
|
34
34
|
|
35
|
-
RELATION_METHODS = [
|
36
|
-
|
37
|
-
|
35
|
+
RELATION_METHODS = [
|
36
|
+
# Query construction
|
37
|
+
:joins, :includes, :select, :order, :where, :having, :group,
|
38
|
+
# Results, debug, array methods
|
39
|
+
:to_a, :all, :length, :size, :to_sql, :debug_sql, :paginate,
|
40
|
+
:find_each, :first, :last, :each, :arel, :in_groups_of, :group_by,
|
41
|
+
# Calculations
|
42
|
+
:count, :average, :minimum, :maximum, :sum
|
43
|
+
]
|
38
44
|
end
|
39
45
|
|
40
46
|
require 'active_record'
|
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.9.
|
8
|
+
s.version = "0.9.11"
|
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{
|
12
|
+
s.date = %q{2011-01-06}
|
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
|
data/test/fixtures/company.rb
CHANGED
@@ -4,18 +4,18 @@ class Company < ActiveRecord::Base
|
|
4
4
|
has_many :slackers, :class_name => "Developer", :conditions => {:slacker => true}
|
5
5
|
has_many :notes, :as => :notable
|
6
6
|
has_many :data_types
|
7
|
-
|
7
|
+
|
8
8
|
scope :backwards_name, lambda {|name| where(:name => name.reverse)}
|
9
9
|
scope :with_slackers_by_name_and_salary_range,
|
10
10
|
lambda {|name, low, high|
|
11
11
|
joins(:slackers).where(:developers => {:name => name, :salary => low..high})
|
12
12
|
}
|
13
|
-
search_methods :backwards_name, :backwards_name_as_string
|
13
|
+
search_methods :backwards_name, :backwards_name_as_string, :if => proc {|s| s.options[:user] != 'blocked'}
|
14
14
|
search_methods :with_slackers_by_name_and_salary_range,
|
15
15
|
:splat_param => true, :type => [:string, :integer, :integer]
|
16
|
-
attr_unsearchable :updated_at
|
17
|
-
assoc_unsearchable :notes
|
18
|
-
|
16
|
+
attr_unsearchable :updated_at, :if => proc {|s| s.options[:user] == 'blocked' || !s.options[:user]}
|
17
|
+
assoc_unsearchable :notes, :if => proc {|s| s.options[:user] == 'blocked' || !s.options[:user]}
|
18
|
+
|
19
19
|
def self.backwards_name_as_string(name)
|
20
20
|
name.reverse
|
21
21
|
end
|
data/test/fixtures/developer.rb
CHANGED
@@ -3,8 +3,8 @@ class Developer < ActiveRecord::Base
|
|
3
3
|
has_and_belongs_to_many :projects
|
4
4
|
has_many :notes, :as => :notable
|
5
5
|
|
6
|
-
attr_searchable :name, :salary
|
7
|
-
assoc_searchable :notes, :projects, :company
|
6
|
+
attr_searchable :name, :salary, :if => proc {|s| !s.options[:user] || s.options[:user] == 'privileged'}
|
7
|
+
assoc_searchable :notes, :projects, :company, :if => proc {|s| !s.options[:user] || s.options[:user] == 'privileged'}
|
8
8
|
|
9
9
|
scope :sort_by_salary_and_name_asc, order('salary ASC, name ASC')
|
10
10
|
scope :sort_by_salary_and_name_desc, order('salary DESC, name DESC')
|
data/test/locales/flanders.yml
CHANGED
@@ -3,9 +3,14 @@ flanders:
|
|
3
3
|
attributes:
|
4
4
|
company:
|
5
5
|
name: "Company name-diddly"
|
6
|
+
developer:
|
7
|
+
name: "Developer name-diddly"
|
8
|
+
salary: "Developer salary-doodly"
|
6
9
|
meta_search:
|
10
|
+
or: 'or-diddly'
|
7
11
|
predicates:
|
8
12
|
contains: "%{attribute} contains-diddly"
|
13
|
+
equals: "%{attribute} equals-diddly"
|
9
14
|
attributes:
|
10
15
|
company:
|
11
16
|
reverse_name: "Company reverse name-diddly"
|
data/test/test_search.rb
CHANGED
@@ -2,6 +2,78 @@ require 'helper'
|
|
2
2
|
|
3
3
|
class TestSearch < Test::Unit::TestCase
|
4
4
|
|
5
|
+
context "A Company search where options[:user] = 'blocked'" do
|
6
|
+
setup do
|
7
|
+
@s = Company.search({}, :user => 'blocked')
|
8
|
+
end
|
9
|
+
|
10
|
+
should "not respond_to? a search against backwards_name" do
|
11
|
+
assert !@s.respond_to?(:backwards_name), "The search responded to :backwards_name"
|
12
|
+
end
|
13
|
+
|
14
|
+
should "raise an error if we try to search on backwards_name" do
|
15
|
+
assert_raise NoMethodError do
|
16
|
+
@s.backwards_name = 'blah'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
should "not respond_to? a search against updated_at_eq" do
|
21
|
+
assert !@s.respond_to?(:updated_at_eq), "The search responded to :updated_at_eq"
|
22
|
+
end
|
23
|
+
|
24
|
+
should "raise an error if we try to search on updated_at" do
|
25
|
+
assert_raise NoMethodError do
|
26
|
+
@s.updated_at_eq = 'blah'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
should "not respond_to? a search against notes_note_matches" do
|
31
|
+
assert !@s.respond_to?(:notes_note_matches), "The search responded to :notes_note_matches"
|
32
|
+
end
|
33
|
+
|
34
|
+
should "raise an error if we try to search on notes_note_matches" do
|
35
|
+
assert_raise NoMethodError do
|
36
|
+
@s.notes_note_matches = '%blah%'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "A Developer search where options[:user] = 'privileged'" do
|
42
|
+
setup do
|
43
|
+
@s = Developer.search({}, :user => 'privileged')
|
44
|
+
end
|
45
|
+
|
46
|
+
should "respond_to? a search against name_eq" do
|
47
|
+
assert_respond_to @s, :name_eq
|
48
|
+
end
|
49
|
+
|
50
|
+
should "not raise an error on a search against name_eq" do
|
51
|
+
assert_nothing_raised do
|
52
|
+
@s.name_eq = 'blah'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
should "respond_to? a search against company_name_eq" do
|
57
|
+
assert_respond_to @s, :company_name_eq
|
58
|
+
end
|
59
|
+
|
60
|
+
should "not raise an error on a search against name_eq" do
|
61
|
+
assert_nothing_raised do
|
62
|
+
@s.company_name_eq = 'blah'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
should "respond_to? a search against company_updated_at_eq" do
|
67
|
+
assert_respond_to @s, :company_updated_at_eq
|
68
|
+
end
|
69
|
+
|
70
|
+
should "not raise an error on a search against company_updated_at_eq" do
|
71
|
+
assert_nothing_raised do
|
72
|
+
@s.company_updated_at_eq = Time.now
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
5
77
|
[{:name => 'Company', :object => Company},
|
6
78
|
{:name => 'Company as a Relation', :object => Company.scoped}].each do |object|
|
7
79
|
context_a_search_against object[:name], object[:object] do
|
@@ -86,31 +158,57 @@ class TestSearch < Test::Unit::TestCase
|
|
86
158
|
end
|
87
159
|
end
|
88
160
|
|
89
|
-
context "
|
161
|
+
context "when meta_sort value is empty string" do
|
90
162
|
setup do
|
91
|
-
@s.meta_sort = '
|
163
|
+
@s.meta_sort = ''
|
92
164
|
end
|
93
165
|
|
94
|
-
should "
|
95
|
-
|
96
|
-
|
166
|
+
should "not raise an error, just ignore sorting" do
|
167
|
+
assert_nothing_raised do
|
168
|
+
assert_equal Company.all, @s.all
|
169
|
+
end
|
97
170
|
end
|
98
171
|
end
|
99
172
|
|
100
|
-
|
173
|
+
should "sort by name in ascending order" do
|
174
|
+
@s.meta_sort = 'name.asc'
|
175
|
+
assert_equal Company.order('name asc').all,
|
176
|
+
@s.all
|
177
|
+
end
|
178
|
+
|
179
|
+
should "sort by name in ascending order as a method call" do
|
180
|
+
@s.meta_sort 'name.asc'
|
181
|
+
assert_equal Company.order('name asc').all,
|
182
|
+
@s.all
|
183
|
+
end
|
184
|
+
|
185
|
+
should "sort by name in descending order" do
|
186
|
+
@s.meta_sort = 'name.desc'
|
187
|
+
assert_equal Company.order('name desc').all,
|
188
|
+
@s.all
|
189
|
+
end
|
190
|
+
|
191
|
+
context "where name contains optical" do
|
101
192
|
setup do
|
102
|
-
@s.
|
193
|
+
@s.name_contains = 'optical'
|
103
194
|
end
|
104
195
|
|
105
|
-
should "
|
106
|
-
assert_equal
|
107
|
-
|
196
|
+
should "return one result" do
|
197
|
+
assert_equal 1, @s.all.size
|
198
|
+
end
|
199
|
+
|
200
|
+
should "return a company named Advanced Optical Solutions" do
|
201
|
+
assert_contains @s.all, Company.where(:name => 'Advanced Optical Solutions').first
|
202
|
+
end
|
203
|
+
|
204
|
+
should "not return a company named Initech" do
|
205
|
+
assert_does_not_contain @s.all, Company.where(:name => "Initech").first
|
108
206
|
end
|
109
207
|
end
|
110
208
|
|
111
|
-
context "where name contains optical" do
|
209
|
+
context "where name contains optical as a method call" do
|
112
210
|
setup do
|
113
|
-
@s.name_contains
|
211
|
+
@s.name_contains 'optical'
|
114
212
|
end
|
115
213
|
|
116
214
|
should "return one result" do
|
@@ -217,6 +315,20 @@ class TestSearch < Test::Unit::TestCase
|
|
217
315
|
end
|
218
316
|
end
|
219
317
|
|
318
|
+
context "where backwards name is hcetinI as a method call" do
|
319
|
+
setup do
|
320
|
+
@s.backwards_name 'hcetinI'
|
321
|
+
end
|
322
|
+
|
323
|
+
should "return 1 result" do
|
324
|
+
assert_equal 1, @s.all.size
|
325
|
+
end
|
326
|
+
|
327
|
+
should "return a company named Initech" do
|
328
|
+
assert_contains @s.all, Company.where(:name => 'Initech').first
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
220
332
|
context "where backwards name is hcetinI" do
|
221
333
|
setup do
|
222
334
|
@s.backwards_name = 'hcetinI'
|
data/test/test_view_helpers.rb
CHANGED
@@ -63,6 +63,10 @@ class TestViewHelpers < ActionView::TestCase
|
|
63
63
|
assert_match /Company reverse name-diddly/, @f1.label(:reverse_name)
|
64
64
|
assert_match /Developer name-diddly contains-aroonie/, @f2.label(:name_like)
|
65
65
|
end
|
66
|
+
|
67
|
+
should "localize more than one attribute when joined with or" do
|
68
|
+
assert_match /Developer name-diddly or-diddly Developer salary-doodly equals-diddly/, @f2.label(:name_or_salary_eq)
|
69
|
+
end
|
66
70
|
end
|
67
71
|
end
|
68
72
|
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 9
|
8
|
-
-
|
9
|
-
version: 0.9.
|
8
|
+
- 11
|
9
|
+
version: 0.9.11
|
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:
|
17
|
+
date: 2011-01-06 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|