searchgasm 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +12 -2
- data/Manifest +5 -4
- data/README.rdoc +15 -17
- data/Rakefile +1 -2
- data/lib/searchgasm/active_record/associations.rb +19 -31
- data/lib/searchgasm/active_record/base.rb +40 -9
- data/lib/searchgasm/condition/base.rb +1 -1
- data/lib/searchgasm/condition/inclusive_descendant_of.rb +0 -2
- data/lib/searchgasm/condition/sibling_of.rb +0 -2
- data/lib/searchgasm/conditions/base.rb +21 -34
- data/lib/searchgasm/conditions/protection.rb +8 -2
- data/lib/searchgasm/helpers/control_types/links.rb +9 -6
- data/lib/searchgasm/helpers/control_types/remote_link.rb +1 -0
- data/lib/searchgasm/helpers/control_types/remote_links.rb +3 -0
- data/lib/searchgasm/helpers/control_types/remote_select.rb +3 -0
- data/lib/searchgasm/helpers/control_types/select.rb +3 -0
- data/lib/searchgasm/helpers/form.rb +11 -4
- data/lib/searchgasm/search/base.rb +26 -46
- data/lib/searchgasm/search/conditions.rb +4 -1
- data/lib/searchgasm/search/pagination.rb +2 -1
- data/lib/searchgasm/search/scoping.rb +0 -0
- data/lib/searchgasm/search.rb +7 -0
- data/lib/searchgasm/shared/searching.rb +25 -0
- data/lib/searchgasm/shared/utilities.rb +32 -0
- data/lib/searchgasm/shared/virtual_classes.rb +39 -0
- data/lib/searchgasm/version.rb +1 -1
- data/lib/searchgasm.rb +6 -2
- data/searchgasm.gemspec +15 -10
- data/test/test_active_record_associations.rb +18 -1
- data/test/test_conditions_base.rb +19 -11
- data/test/test_search_base.rb +8 -8
- metadata +14 -9
- data/benchmarks/benchmark.rb +0 -43
- data/benchmarks/benchmark_helper.rb +0 -52
- data/benchmarks/profile.rb +0 -15
- data/lib/searchgasm/utilities.rb +0 -30
data/CHANGELOG.rdoc
CHANGED
@@ -1,7 +1,17 @@
|
|
1
|
+
== 1.0.3 released 2008-09-18
|
2
|
+
|
3
|
+
* Updated inspect to show the current options for your search. Plays nicer in the console.
|
4
|
+
* Made sure protection state is persistent among relationship conditions.
|
5
|
+
* Fixed bug with backwards compatibility of rails. concat requires a proc in older version.
|
6
|
+
* Defaulted remote control types to use GET requests instead of POST.
|
7
|
+
* Completely reengineered integration with ActiveRecord. Searchgasm is properly using scopes letting you do use serachgasm where scope are implemented. @current_users.orders.new_search, etc. If your search is scoped and you want a search object, that search object will represent a new search in the context of those scopes, meaning the scopes get merged into Searchgasm as options.
|
8
|
+
* Dropped support for Searchgasm functionality when defining relationships: has_many :order, :conditions => {:total_gt => 100}, will not work anymore. It's a chicken and the egg thing. Searchgasm needs AR constants, some models get loaded before others, therefore the Order model may not have been loaded yet, causing an unknown constant error.
|
9
|
+
* Clean up redundant code and moved it into the Searchgasm::Shared namespace.
|
10
|
+
|
1
11
|
== 1.0.2 released 2008-09-12
|
2
12
|
|
3
13
|
* Moved cached searchers out of the global namespace and into the Searchgasm::Cache namespce.
|
4
|
-
* Various changes to improve performance
|
14
|
+
* Various changes to improve performance through profiling / benchmarking. http://pastie.org/271936
|
5
15
|
* Config.per_page works with new_search & new_search! only. Where as before it was only working if the search was protected.
|
6
16
|
|
7
17
|
== 1.0.1 released 2008-09-11
|
@@ -50,7 +60,7 @@
|
|
50
60
|
== 0.9.4 released 2008-09-03
|
51
61
|
|
52
62
|
* Cleaned up search methods
|
53
|
-
* Removed reset!method for both searching and searching by conditions
|
63
|
+
* Removed reset! method for both searching and searching by conditions
|
54
64
|
|
55
65
|
== 0.9.3 released 2008-09-02
|
56
66
|
|
data/Manifest
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
benchmarks/benchmark.rb
|
2
|
-
benchmarks/benchmark_helper.rb
|
3
|
-
benchmarks/profile.rb
|
4
1
|
CHANGELOG.rdoc
|
5
2
|
examples/README.rdoc
|
6
3
|
init.rb
|
@@ -42,7 +39,11 @@ lib/searchgasm/search/conditions.rb
|
|
42
39
|
lib/searchgasm/search/ordering.rb
|
43
40
|
lib/searchgasm/search/pagination.rb
|
44
41
|
lib/searchgasm/search/protection.rb
|
45
|
-
lib/searchgasm/
|
42
|
+
lib/searchgasm/search/scoping.rb
|
43
|
+
lib/searchgasm/search.rb
|
44
|
+
lib/searchgasm/shared/searching.rb
|
45
|
+
lib/searchgasm/shared/utilities.rb
|
46
|
+
lib/searchgasm/shared/virtual_classes.rb
|
46
47
|
lib/searchgasm/version.rb
|
47
48
|
lib/searchgasm.rb
|
48
49
|
Manifest
|
data/README.rdoc
CHANGED
@@ -219,14 +219,23 @@ For tree data structures you get a few nifty methods. Let's assume Users is a tr
|
|
219
219
|
User.all(:conditions => {:inclusive_descendant_of => User.roots.first.id})
|
220
220
|
|
221
221
|
|
222
|
-
==
|
222
|
+
== Scope support
|
223
223
|
|
224
|
-
Not only can you use searchgasm when searching, but you can use it when
|
224
|
+
Not only can you use searchgasm when searching, but you can use it when using scopes.
|
225
225
|
|
226
226
|
class User < ActiveRecord::Base
|
227
|
-
has_many :expensive_pending_orders, :conditions => {:total_greater_than => 1_000_000, :state => :pending}, :per_page => 20
|
228
227
|
named_scope :sexy, :conditions => {:first_name => "Ben", email_ends_with => "binarylogic.com"}, :per_page => 20
|
229
228
|
end
|
229
|
+
|
230
|
+
or
|
231
|
+
|
232
|
+
class User < ActiveRecord::Base
|
233
|
+
def self.find_sexy
|
234
|
+
with_scope(:find => {:conditions => {:first_name => "Ben", email_ends_with => "binarylogic.com"}, :per_page => 20}) do
|
235
|
+
all
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
230
239
|
|
231
240
|
== Always use protection...against SQL injections
|
232
241
|
|
@@ -328,22 +337,11 @@ Pretty nifty, huh? You can create any condition ultimately creating any SQL you
|
|
328
337
|
|
329
338
|
== Under the hood
|
330
339
|
|
331
|
-
I'm a big fan of understanding what I'm using, so here's a quick explanation: The design behind this plugin is pretty simple
|
332
|
-
|
333
|
-
== Performance / Benchmarking
|
334
|
-
|
335
|
-
I ran searchgasm through some performance tests using ruby-prof. After working on it for a little while I improved performance quite a bit. Notice the "2nd instantiation" report. This is implementing caching and skips all dynamic method creation / meta programming. It resulted in code over 50 times faster.
|
340
|
+
I'm a big fan of understanding what I'm using, so here's a quick explanation: The design behind this plugin is pretty simple and I had 1 main rule when developing this:
|
336
341
|
|
337
|
-
|
338
|
-
1st instantiation: 0.000000 0.000000 0.000000 ( 0.005466)
|
339
|
-
2nd instantiation: 0.000000 0.000000 0.000000 ( 0.000108)
|
340
|
-
Local ordering: 0.000000 0.000000 0.000000 ( 0.000265)
|
341
|
-
Advanced ordering: 0.000000 0.000000 0.000000 ( 0.000413)
|
342
|
-
Local conditions: 0.000000 0.000000 0.000000 ( 0.000241)
|
343
|
-
Advanced conditions: 0.000000 0.000000 0.000000 ( 0.000602)
|
344
|
-
Its complicated: 0.000000 0.000000 0.000000 ( 0.001017)
|
342
|
+
ActiveRecord should never know about Searchgasm
|
345
343
|
|
346
|
-
|
344
|
+
What that rule means is that any options you pass when searching get "sanitized" down into options ActiveRecord can understand. Searchgasm serves as a transparent filter between you and ActiveRecord. It doesn't dig into the ActiveRecord internals, it only uses what is publicly available. It jumps in and helps out <em>only</em> when needed, otherwise it sits back and stays completely out of the way. Between that and the extensive tests, this is a solid and fast plugin.
|
347
345
|
|
348
346
|
== Reporting problems / bugs
|
349
347
|
|
data/Rakefile
CHANGED
@@ -8,8 +8,7 @@ Echoe.new 'searchgasm' do |p|
|
|
8
8
|
p.author = "Ben Johnson of Binary Logic"
|
9
9
|
p.email = 'bjohnson@binarylogic.com'
|
10
10
|
p.project = 'searchgasm'
|
11
|
-
p.summary = "
|
12
|
-
p.description = "Makes ActiveRecord searching easier, robust, and powerful. Automatic conditions, pagination support, object based searching, and more."
|
11
|
+
p.summary = "Object based ActiveRecord searching, ordering, pagination, and more!"
|
13
12
|
p.url = "http://github.com/binarylogic/searchgasm"
|
14
13
|
p.dependencies = %w(activerecord activesupport)
|
15
14
|
p.include_rakefile = true
|
@@ -5,68 +5,56 @@ module Searchgasm
|
|
5
5
|
# These methods hook into ActiveRecords association methods and add in searchgasm functionality.
|
6
6
|
module Associations
|
7
7
|
module AssociationCollection
|
8
|
-
# This
|
8
|
+
# This needs to be implemented because AR doesn't leverage scopes with this method like it probably should
|
9
9
|
def find_with_searchgasm(*args)
|
10
10
|
options = args.extract_options!
|
11
11
|
args << sanitize_options_with_searchgasm(options)
|
12
12
|
find_without_searchgasm(*args)
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
# See build_conditions under Searchgasm::ActiveRecord::Base. This is the same thing but for associations.
|
16
16
|
def build_conditions(options = {}, &block)
|
17
|
-
|
18
|
-
conditions.scope = scope(:find)[:conditions]
|
19
|
-
conditions
|
17
|
+
@reflection.klass.send(:with_scope, :find => construct_scope[:find]) { @reflection.klass.build_conditions(options, &block) }
|
20
18
|
end
|
21
|
-
|
19
|
+
|
22
20
|
# See build_conditions! under Searchgasm::ActiveRecord::Base. This is the same thing but for associations.
|
23
21
|
def build_conditions!(options = {}, &block)
|
24
|
-
|
25
|
-
conditions.scope = scope(:find)[:conditions]
|
26
|
-
conditions
|
22
|
+
@reflection.klass.send(:with_scope, :find => construct_scope[:find]) { @reflection.klass.build_conditions!(options, &block) }
|
27
23
|
end
|
28
|
-
|
24
|
+
|
29
25
|
# See build_search under Searchgasm::ActiveRecord::Base. This is the same thing but for associations.
|
30
26
|
def build_search(options = {}, &block)
|
31
|
-
|
32
|
-
conditions.scope = scope(:find)[:conditions]
|
33
|
-
conditions
|
27
|
+
@reflection.klass.send(:with_scope, :find => construct_scope[:find]) { @reflection.klass.build_search(options, &block) }
|
34
28
|
end
|
35
|
-
|
29
|
+
|
36
30
|
# See build_conditions! under Searchgasm::ActiveRecord::Base. This is the same thing but for associations.
|
37
31
|
def build_search!(options = {}, &block)
|
38
|
-
|
39
|
-
conditions.scope = scope(:find)[:conditions]
|
40
|
-
conditions
|
32
|
+
@reflection.klass.send(:with_scope, :find => construct_scope[:find]) { @reflection.klass.build_search!(options, &block) }
|
41
33
|
end
|
42
34
|
end
|
43
|
-
|
44
|
-
module
|
45
|
-
# This is an alias method chain. It hook into ActiveRecord's "calculate" method for has many associations and checks to see if Searchgasm should get involved.
|
35
|
+
|
36
|
+
module Shared
|
46
37
|
def count_with_searchgasm(*args)
|
47
|
-
|
48
|
-
|
38
|
+
options = args.extract_options!
|
39
|
+
args << sanitize_options_with_searchgasm(options)
|
40
|
+
count_without_searchgasm(*args)
|
49
41
|
end
|
50
42
|
end
|
51
43
|
end
|
52
44
|
end
|
53
45
|
end
|
54
46
|
|
55
|
-
ActiveRecord::Associations::AssociationCollection.send(:include, Searchgasm::ActiveRecord::Associations::AssociationCollection)
|
56
|
-
|
57
47
|
module ActiveRecord
|
58
48
|
module Associations
|
59
49
|
class AssociationCollection
|
50
|
+
include Searchgasm::ActiveRecord::Associations::AssociationCollection
|
51
|
+
|
60
52
|
alias_method_chain :find, :searchgasm
|
61
53
|
end
|
62
|
-
|
63
|
-
end
|
64
|
-
|
65
|
-
ActiveRecord::Associations::HasManyAssociation.send(:include, Searchgasm::ActiveRecord::Associations::HasManyAssociation)
|
66
|
-
|
67
|
-
module ActiveRecord
|
68
|
-
module Associations
|
54
|
+
|
69
55
|
class HasManyAssociation
|
56
|
+
include Searchgasm::ActiveRecord::Associations::Shared
|
57
|
+
|
70
58
|
alias_method_chain :count, :searchgasm
|
71
59
|
end
|
72
60
|
end
|
@@ -18,21 +18,29 @@ module Searchgasm
|
|
18
18
|
args << options
|
19
19
|
find_without_searchgasm(*args)
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
# This is an alias method chain. It hooks into ActiveRecord's scopes and checks to see if Searchgasm should get involved. Allowing you to use all of Searchgasms conditions and tools
|
23
23
|
# in scopes as well.
|
24
24
|
#
|
25
25
|
# === Examples
|
26
26
|
#
|
27
|
+
# Named scopes:
|
28
|
+
#
|
27
29
|
# named_scope :top_expensive, :conditions => {:total_gt => 1_000_000}, :per_page => 10
|
30
|
+
# named_scope :top_expensive_ordered, :conditions => {:total_gt => 1_000_000}, :per_page => 10, :order_by => {:user => :first_name}
|
31
|
+
#
|
32
|
+
# Good ole' regular scopes:
|
28
33
|
#
|
29
34
|
# with_scope(:find => {:conditions => {:total_gt => 1_000_000}, :per_page => 10}) do
|
30
35
|
# find(:all)
|
31
36
|
# end
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
37
|
+
#
|
38
|
+
# with_scope(:find => {:conditions => {:total_gt => 1_000_000}, :per_page => 10}) do
|
39
|
+
# build_search
|
40
|
+
# end
|
41
|
+
def with_scope_with_searchgasm(method_scoping = {}, action = :merge, &block)
|
42
|
+
method_scoping[:find] = sanitize_options_with_searchgasm(method_scoping[:find]) if method_scoping[:find]
|
43
|
+
with_scope_without_searchgasm(method_scoping, action, &block)
|
36
44
|
end
|
37
45
|
|
38
46
|
# This is a special method that Searchgasm adds in. It returns a new conditions object on the model. So you can search by conditions *only*.
|
@@ -118,17 +126,40 @@ module Searchgasm
|
|
118
126
|
private
|
119
127
|
def sanitize_options_with_searchgasm(options = {})
|
120
128
|
return options unless Searchgasm::Search::Base.needed?(self, options)
|
121
|
-
search =
|
129
|
+
search = Searchgasm::Search::Base.create_virtual_class(self).new(options) # call explicitly to avoid merging the scopes into the searcher
|
122
130
|
search.acting_as_filter = true
|
123
131
|
search.sanitize
|
124
132
|
end
|
125
133
|
|
126
134
|
def searchgasm_conditions(options = {})
|
127
|
-
Searchgasm::Conditions::Base.create_virtual_class(self).new(options)
|
135
|
+
conditions = Searchgasm::Conditions::Base.create_virtual_class(self).new(options)
|
136
|
+
conditions.conditions = (scope(:find) || {})[:conditions]
|
137
|
+
conditions
|
128
138
|
end
|
129
139
|
|
130
140
|
def searchgasm_searcher(options = {})
|
131
|
-
Searchgasm::Search::Base.create_virtual_class(self).new(options)
|
141
|
+
search = Searchgasm::Search::Base.create_virtual_class(self).new(options)
|
142
|
+
options_from_scope_for_searchgasm(options).each { |option, value| search.send("#{option}=", value) }
|
143
|
+
search
|
144
|
+
end
|
145
|
+
|
146
|
+
def options_from_scope_for_searchgasm(options)
|
147
|
+
# The goal here is to mimic how scope work. Merge what scopes would and don't what they wouldn't.
|
148
|
+
scope = scope(:find) || {}
|
149
|
+
scope_options = {}
|
150
|
+
[:group, :include, :select, :readonly].each { |option| scope_options[option] = scope[option] if !options.has_key?(option) && scope.has_key?(option) }
|
151
|
+
|
152
|
+
if scope[:joins] || options[:joins]
|
153
|
+
scope_options[:joins] = []
|
154
|
+
scope_options[:joins] += scope[:joins].is_a?(Array) ? scope[:joins] : [scope[:joins]] unless scope[:joins].blank?
|
155
|
+
scope_options[:joins] += options[:joins].is_a?(Array) ? options[:joins] : [options[:joins]] unless options[:joins].blank?
|
156
|
+
end
|
157
|
+
|
158
|
+
scope_options[:limit] = scope[:limit] if !options.has_key?(:per_page) && !options.has_key?(:limit) && scope.has_key?(:per_page)
|
159
|
+
scope_options[:offset] = scope[:offset] if !options.has_key?(:page) && !options.has_key?(:offset) && scope.has_key?(:offset)
|
160
|
+
scope_options[:order] = scope[:order] if !options.has_key?(:order_by) && !options.has_key?(:order) && scope.has_key?(:order)
|
161
|
+
scope_options[:conditions] = scope[:conditions] if scope.has_key?(:conditions)
|
162
|
+
scope_options
|
132
163
|
end
|
133
164
|
end
|
134
165
|
end
|
@@ -141,7 +172,7 @@ module ActiveRecord #:nodoc: all
|
|
141
172
|
class << self
|
142
173
|
alias_method_chain :calculate, :searchgasm
|
143
174
|
alias_method_chain :find, :searchgasm
|
144
|
-
alias_method_chain :
|
175
|
+
alias_method_chain :with_scope, :searchgasm
|
145
176
|
alias_method :new_conditions, :build_conditions
|
146
177
|
alias_method :new_conditions!, :build_conditions!
|
147
178
|
alias_method :new_search, :build_search
|
@@ -5,7 +5,7 @@ module Searchgasm
|
|
5
5
|
# The base class for creating a condition. Your custom conditions should extend this class.
|
6
6
|
# See Searchgasm::Conditions::Base.register_condition on how to write your own condition.
|
7
7
|
class Base
|
8
|
-
include Utilities
|
8
|
+
include Shared::Utilities
|
9
9
|
|
10
10
|
attr_accessor :column, :klass
|
11
11
|
attr_reader :value
|
@@ -1,8 +1,6 @@
|
|
1
1
|
module Searchgasm
|
2
2
|
module Condition
|
3
3
|
class SiblingOf < Tree
|
4
|
-
include Searchgasm::Utilities
|
5
|
-
|
6
4
|
def to_conditions(value)
|
7
5
|
parent_association = klass.reflect_on_association(:parent)
|
8
6
|
foreign_key_name = (parent_association && parent_association.options[:foreign_key]) || "parent_id"
|
@@ -5,9 +5,11 @@ module Searchgasm
|
|
5
5
|
# Represents a collection of conditions and performs various tasks on that collection. For information on each condition see Searchgasm::Condition.
|
6
6
|
# Each condition has its own file and class and the source for each condition is pretty self explanatory.
|
7
7
|
class Base
|
8
|
-
include Utilities
|
8
|
+
include Searchgasm::Shared::Utilities
|
9
|
+
include Searchgasm::Shared::Searching
|
10
|
+
include Searchgasm::Shared::VirtualClasses
|
9
11
|
|
10
|
-
attr_accessor :relationship_name, :
|
12
|
+
attr_accessor :relationship_name, :sql
|
11
13
|
|
12
14
|
class << self
|
13
15
|
attr_accessor :added_klass_conditions, :added_column_conditions, :added_associations
|
@@ -64,37 +66,14 @@ module Searchgasm
|
|
64
66
|
|
65
67
|
def needed?(model_class, conditions) # :nodoc:
|
66
68
|
if conditions.is_a?(Hash)
|
69
|
+
column_names = model_class.column_names
|
67
70
|
conditions.stringify_keys.keys.each do |condition|
|
68
|
-
return true unless
|
71
|
+
return true unless column_names.include?(condition)
|
69
72
|
end
|
70
73
|
end
|
71
74
|
|
72
75
|
false
|
73
76
|
end
|
74
|
-
|
75
|
-
# Creates virtual classes for the class passed to it. This is a neccesity for keeping dynamically created method
|
76
|
-
# names specific to models. It provides caching and helps a lot with performance.
|
77
|
-
def create_virtual_class(model_class)
|
78
|
-
class_search_name = "::Searchgasm::Cache::#{model_class.name}Conditions"
|
79
|
-
|
80
|
-
begin
|
81
|
-
eval(class_search_name)
|
82
|
-
rescue NameError
|
83
|
-
eval <<-end_eval
|
84
|
-
class #{class_search_name} < ::Searchgasm::Conditions::Base
|
85
|
-
def self.klass
|
86
|
-
#{model_class.name}
|
87
|
-
end
|
88
|
-
|
89
|
-
def klass
|
90
|
-
#{model_class.name}
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
#{class_search_name}
|
95
|
-
end_eval
|
96
|
-
end
|
97
|
-
end
|
98
77
|
end
|
99
78
|
|
100
79
|
def initialize(init_conditions = {})
|
@@ -125,22 +104,29 @@ module Searchgasm
|
|
125
104
|
i.blank? ? nil : (i.size == 1 ? i.first : i)
|
126
105
|
end
|
127
106
|
|
107
|
+
def inspect
|
108
|
+
conditions_hash = conditions
|
109
|
+
conditions_hash[:sql] = sql if sql
|
110
|
+
conditions_hash[:protected] = true if protected?
|
111
|
+
conditions_hash.inspect
|
112
|
+
end
|
113
|
+
|
128
114
|
# Sanitizes the conditions down into conditions that ActiveRecord::Base.find can understand.
|
129
|
-
def sanitize
|
115
|
+
def sanitize(for_method = nil)
|
130
116
|
conditions = merge_conditions(*objects.collect { |object| object.sanitize })
|
131
|
-
return
|
132
|
-
merge_conditions(conditions,
|
117
|
+
return sql if conditions.blank?
|
118
|
+
merged_conditions = merge_conditions(conditions, sql)
|
119
|
+
for_method.blank? ? merged_conditions : {:conditions => merged_conditions}
|
133
120
|
end
|
134
121
|
|
135
|
-
# Allows you to set the conditions via a hash.
|
136
|
-
# merge it all together at the end.
|
122
|
+
# Allows you to set the conditions via a hash.
|
137
123
|
def conditions=(conditions)
|
138
124
|
case conditions
|
139
125
|
when Hash
|
140
126
|
assert_valid_conditions(conditions)
|
141
127
|
remove_conditions_from_protected_assignement(conditions).each { |condition, value| send("#{condition}=", value) }
|
142
128
|
else
|
143
|
-
self.
|
129
|
+
self.sql = conditions
|
144
130
|
end
|
145
131
|
end
|
146
132
|
|
@@ -171,8 +157,9 @@ module Searchgasm
|
|
171
157
|
self.class.class_eval <<-"end_eval", __FILE__, __LINE__
|
172
158
|
def #{association.name}
|
173
159
|
if @#{association.name}.nil?
|
174
|
-
@#{association.name} = #{association.class_name}.
|
160
|
+
@#{association.name} = Searchgasm::Conditions::Base.create_virtual_class(#{association.class_name}).new
|
175
161
|
@#{association.name}.relationship_name = "#{association.name}"
|
162
|
+
@#{association.name}.protect = protect
|
176
163
|
objects << @#{association.name}
|
177
164
|
end
|
178
165
|
@#{association.name}
|
@@ -6,7 +6,7 @@ module Searchgasm
|
|
6
6
|
module Protection
|
7
7
|
def self.included(klass)
|
8
8
|
klass.class_eval do
|
9
|
-
|
9
|
+
attr_reader :protect
|
10
10
|
alias_method_chain :conditions=, :protection
|
11
11
|
end
|
12
12
|
end
|
@@ -15,16 +15,22 @@ module Searchgasm
|
|
15
15
|
unless conditions.is_a?(Hash)
|
16
16
|
if protect?
|
17
17
|
return if conditions.blank?
|
18
|
-
raise(ArgumentError, "You can not
|
18
|
+
raise(ArgumentError, "You can not pass SQL as conditions while the search is being protected, you can only pass a hash")
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
22
|
self.conditions_without_protection = conditions
|
23
23
|
end
|
24
24
|
|
25
|
+
def protect=(value)
|
26
|
+
associations.each { |association| association.protect = value }
|
27
|
+
@protect = value
|
28
|
+
end
|
29
|
+
|
25
30
|
def protect?
|
26
31
|
protect == true
|
27
32
|
end
|
33
|
+
alias_method :protected?, :protect?
|
28
34
|
end
|
29
35
|
end
|
30
36
|
end
|
@@ -1,6 +1,9 @@
|
|
1
1
|
module Searchgasm
|
2
2
|
module Helpers
|
3
3
|
module ControlTypes
|
4
|
+
# = Links Control Types
|
5
|
+
#
|
6
|
+
# These helpers create a group of links to help navigate through search data.
|
4
7
|
module Links
|
5
8
|
# Creates a group of links that order the data by a column or columns. All that this does is loop through the :choices option and call order_by_link and then glue it all together.
|
6
9
|
#
|
@@ -11,7 +14,7 @@ module Searchgasm
|
|
11
14
|
#
|
12
15
|
# === Options
|
13
16
|
#
|
14
|
-
# Please look at order_by_link. All options there are applicable here and are passed onto each option.
|
17
|
+
# Please look at order_by_link. All options there are applicable here and are passed onto each option. Here are the options specific to this method:
|
15
18
|
#
|
16
19
|
# * <tt>:choices</tt> -- default: the models column names, the choices to loop through when calling order_by_link
|
17
20
|
def order_by_links(options = {})
|
@@ -32,7 +35,7 @@ module Searchgasm
|
|
32
35
|
#
|
33
36
|
# === Options
|
34
37
|
#
|
35
|
-
# Please look at order_as_link. All options there are applicable here and are passed onto each option.
|
38
|
+
# Please look at order_as_link. All options there are applicable here and are passed onto each option. Here are the options specific to this method:
|
36
39
|
#
|
37
40
|
# * <tt>:choices</tt> -- default: ["asc", "desc"], the choices to loop through when calling order_as_link
|
38
41
|
def order_as_links(options = {})
|
@@ -53,7 +56,7 @@ module Searchgasm
|
|
53
56
|
#
|
54
57
|
# === Options
|
55
58
|
#
|
56
|
-
# Please look at per_page_link. All options there are applicable here and are passed onto each option.
|
59
|
+
# Please look at per_page_link. All options there are applicable here and are passed onto each option. Here are the options specific to this method:
|
57
60
|
#
|
58
61
|
# * <tt>:choices</tt> -- default: [10, 25, 50, 100, 150, 200, nil], the choices to loop through when calling per_page_link.
|
59
62
|
def per_page_links(options = {})
|
@@ -88,11 +91,11 @@ module Searchgasm
|
|
88
91
|
#
|
89
92
|
# === Options
|
90
93
|
#
|
91
|
-
# Please look at per_page_link. All options there are applicable here and are passed onto each option.
|
94
|
+
# Please look at per_page_link. All options there are applicable here and are passed onto each option. Here are the options specific to this method:
|
92
95
|
#
|
93
96
|
# * <tt>:spread</tt> -- default: 3, set to nil to show all page, this represents how many choices available on each side of the current page
|
94
|
-
# * <tt>:prev</tt> -- default: < Prev, set to nil to omit. This is an extra link on the left side of the page links that will go to the previous page
|
95
|
-
# * <tt>:next</tt> -- default: Next
|
97
|
+
# * <tt>:prev</tt> -- default: "< Prev", set to nil to omit. This is an extra link on the left side of the page links that will go to the previous page
|
98
|
+
# * <tt>:next</tt> -- default: "Next >", set to nil to omit. This is an extra link on the right side of the page links that will go to the next page
|
96
99
|
# * <tt>:first</tt> -- default: nil, set to nil to omit. This is an extra link on thefar left side of the page links that will go to the first page
|
97
100
|
# * <tt>:last</tt> -- default: nil, set to nil to omit. This is an extra link on the far right side of the page links that will go to the last page
|
98
101
|
def page_links(options = {})
|
@@ -1,6 +1,9 @@
|
|
1
1
|
module Searchgasm
|
2
2
|
module Helpers
|
3
3
|
module ControlTypes
|
4
|
+
# = Remote Links Control Types
|
5
|
+
#
|
6
|
+
# These helpers use rails built in remote_function as links. They are the same thing as the Links control type, but just use rails built in remote helpers.
|
4
7
|
module RemoteLinks
|
5
8
|
# Same as order_by_links, but uses link_to_remote instead of remote.
|
6
9
|
#
|
@@ -1,6 +1,9 @@
|
|
1
1
|
module Searchgasm
|
2
2
|
module Helpers
|
3
3
|
module ControlTypes
|
4
|
+
# = Remote Select Control Types
|
5
|
+
#
|
6
|
+
# These helpers use rails built in remote_function as links. They are the same thing as the Select control type, but just use rails built in remote helpers.
|
4
7
|
module RemoteSelect
|
5
8
|
# Please see order_by_links. All options are the same and applicable here. The only difference is that instead of a group of links, this gets returned as a select form element that will perform the same function when the value is changed.
|
6
9
|
def remote_order_by_select(options = {})
|
@@ -1,6 +1,9 @@
|
|
1
1
|
module Searchgasm
|
2
2
|
module Helpers
|
3
3
|
module ControlTypes
|
4
|
+
# = Select Control Types
|
5
|
+
#
|
6
|
+
# These create <select> tags to help navigate through search data. This is here as an alternative to the Links control types.
|
4
7
|
module Select
|
5
8
|
# Please see order_by_links. All options are the same and applicable here. The only difference is that instead of a group of links, this gets returned as a select form element that will perform the same function when the value is changed.
|
6
9
|
def order_by_select(options = {})
|
@@ -116,13 +116,20 @@ module Searchgasm
|
|
116
116
|
args
|
117
117
|
end
|
118
118
|
|
119
|
-
def insert_searchgasm_fields(args, search_object, search_options)
|
119
|
+
def insert_searchgasm_fields(args, search_object, search_options, &block)
|
120
120
|
return unless search_object.is_a?(Search::Base)
|
121
121
|
name = args.first
|
122
122
|
options = args.extract_options!
|
123
123
|
options
|
124
124
|
search_options[:hidden_fields].each do |field|
|
125
|
-
|
125
|
+
html = hidden_field(name, field, :object => search_object, :id => "#{name}_#{field}_hidden", :value => (field == :order_by ? searchgasm_order_by_value(search_object.order_by) : search_object.send(field)))
|
126
|
+
|
127
|
+
# For edge rails and older version compatibility, passing a binding to concat was deprecated
|
128
|
+
begin
|
129
|
+
concat(html)
|
130
|
+
rescue ArgumentError
|
131
|
+
concat(html, block.binding)
|
132
|
+
end
|
126
133
|
end
|
127
134
|
args << options
|
128
135
|
end
|
@@ -136,7 +143,7 @@ module Searchgasm
|
|
136
143
|
if search_object
|
137
144
|
searchgasm_options = extract_searchgasm_options!(args)
|
138
145
|
new_args = searchgasm_args(args, search_object, searchgasm_options, :fields_for)
|
139
|
-
insert_searchgasm_fields(new_args, search_object, searchgasm_options)
|
146
|
+
insert_searchgasm_fields(new_args, search_object, searchgasm_options, &block)
|
140
147
|
fields_for_without_searchgasm(*new_args, &block)
|
141
148
|
else
|
142
149
|
fields_for_without_searchgasm(*args, &block)
|
@@ -172,7 +179,7 @@ module Searchgasm
|
|
172
179
|
if search_object
|
173
180
|
searchgasm_options = extract_searchgasm_options!(args)
|
174
181
|
new_args = searchgasm_args(args, search_object, searchgasm_options, :fields_for)
|
175
|
-
insert_searchgasm_fields(new_args, search_object, searchgasm_options)
|
182
|
+
insert_searchgasm_fields(new_args, search_object, searchgasm_options, &block)
|
176
183
|
fields_for_without_searchgasm(*new_args, &block)
|
177
184
|
else
|
178
185
|
fields_for_without_searchgasm(*args, &block)
|