searchgasm 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/CHANGELOG.rdoc +12 -2
  2. data/Manifest +5 -4
  3. data/README.rdoc +15 -17
  4. data/Rakefile +1 -2
  5. data/lib/searchgasm/active_record/associations.rb +19 -31
  6. data/lib/searchgasm/active_record/base.rb +40 -9
  7. data/lib/searchgasm/condition/base.rb +1 -1
  8. data/lib/searchgasm/condition/inclusive_descendant_of.rb +0 -2
  9. data/lib/searchgasm/condition/sibling_of.rb +0 -2
  10. data/lib/searchgasm/conditions/base.rb +21 -34
  11. data/lib/searchgasm/conditions/protection.rb +8 -2
  12. data/lib/searchgasm/helpers/control_types/links.rb +9 -6
  13. data/lib/searchgasm/helpers/control_types/remote_link.rb +1 -0
  14. data/lib/searchgasm/helpers/control_types/remote_links.rb +3 -0
  15. data/lib/searchgasm/helpers/control_types/remote_select.rb +3 -0
  16. data/lib/searchgasm/helpers/control_types/select.rb +3 -0
  17. data/lib/searchgasm/helpers/form.rb +11 -4
  18. data/lib/searchgasm/search/base.rb +26 -46
  19. data/lib/searchgasm/search/conditions.rb +4 -1
  20. data/lib/searchgasm/search/pagination.rb +2 -1
  21. data/lib/searchgasm/search/scoping.rb +0 -0
  22. data/lib/searchgasm/search.rb +7 -0
  23. data/lib/searchgasm/shared/searching.rb +25 -0
  24. data/lib/searchgasm/shared/utilities.rb +32 -0
  25. data/lib/searchgasm/shared/virtual_classes.rb +39 -0
  26. data/lib/searchgasm/version.rb +1 -1
  27. data/lib/searchgasm.rb +6 -2
  28. data/searchgasm.gemspec +15 -10
  29. data/test/test_active_record_associations.rb +18 -1
  30. data/test/test_conditions_base.rb +19 -11
  31. data/test/test_search_base.rb +8 -8
  32. metadata +14 -9
  33. data/benchmarks/benchmark.rb +0 -43
  34. data/benchmarks/benchmark_helper.rb +0 -52
  35. data/benchmarks/profile.rb +0 -15
  36. 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. Added in benchmark reports in readme as well as a benchmarks directory.
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/utilities.rb
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
- == Available anywhere (relationships & scopes)
222
+ == Scope support
223
223
 
224
- Not only can you use searchgasm when searching, but you can use it when setting up relationships or scopes. Anywhere you specify conditions in ActiveRecord.
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. The search object "sanitizes" down into the options passed into ActiveRecord::Base.find(). It serves as a transparent filter between you and ActiveRecord::Base.find(). This filter provides "enhancements" that get translated into options that ActiveRecord::Base.find() can understand. 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 lets ActiveRecord do all of the work. Between that and the extensive tests, this is a solid and fast plugin.
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
- user system total real
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
- I also included the benchmarking file in benchmarks/benchmark.rb to see for yourself.
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 = "Orgasmic ActiveRecord searching"
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 is an alias method chain. It hook into ActiveRecord's "find" method for associations and checks to see if Searchgasm should get involved.
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
- conditions = @reflection.klass.build_conditions(options, &block)
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
- conditions = @reflection.klass.build_conditions!(options, &block)
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
- conditions = @reflection.klass.build_search(options, &block)
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
- conditions = @reflection.klass.build_search!(options, &block)
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 HasManyAssociation
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
- column_name, options = @reflection.klass.send(:construct_count_options_from_args, *args)
48
- count_without_searchgasm(column_name, sanitize_options_with_searchgasm(options))
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
- end
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
- def scope_with_searchgasm(method, key = nil)
33
- scope = scope_without_searchgasm(method, key)
34
- return sanitize_options_with_searchgasm(scope) if key.nil? && method == :find && !scope.blank?
35
- scope
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 = searchgasm_searcher(options)
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 :scope, :searchgasm
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 InclusiveDescendantOf < Tree
4
- include Searchgasm::Utilities
5
-
6
4
  def to_conditions(value)
7
5
  condition = DescendantOf.new(klass, column)
8
6
  condition.value = 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, :scope
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 model_class.column_names.include?(condition)
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 scope if conditions.blank?
132
- merge_conditions(conditions, scope)
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. If you do not pass a hash it will set scope instead, so that you can continue to add conditions and ultimately
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.scope = conditions
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}.new_conditions
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
- attr_accessor :protect
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 set a scope or pass SQL while the search is being protected")
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 >, 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
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 = {})
@@ -76,6 +76,7 @@ module Searchgasm
76
76
  private
77
77
  def add_remote_defaults!(options)
78
78
  options[:remote] ||= {}
79
+ options[:remote][:method] ||= :get
79
80
  options[:is_remote] = true
80
81
  end
81
82
  end
@@ -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
- concat(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))))
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)