searchgasm 1.1.0 → 1.1.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.rdoc +8 -0
- data/lib/searchgasm/active_record/associations.rb +2 -2
- data/lib/searchgasm/active_record/base.rb +19 -12
- data/lib/searchgasm/conditions/base.rb +4 -1
- data/lib/searchgasm/config.rb +5 -5
- data/lib/searchgasm/search/base.rb +15 -8
- data/lib/searchgasm/search/conditions.rb +2 -2
- data/lib/searchgasm/search/ordering.rb +7 -5
- data/lib/searchgasm/search/protection.rb +9 -4
- data/lib/searchgasm/shared/searching.rb +3 -5
- data/lib/searchgasm/version.rb +1 -1
- data/searchgasm.gemspec +3 -3
- data/test/test_active_record_base.rb +2 -1
- data/test/test_conditions_base.rb +9 -0
- data/test/test_conditions_protection.rb +3 -0
- data/test/test_helper.rb +2 -0
- data/test/test_search_base.rb +16 -1
- data/test/test_search_pagination.rb +1 -1
- data/test/test_search_protection.rb +4 -4
- metadata +2 -2
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
== 1.1.1 released 2008-09-19
|
2
|
+
|
3
|
+
* Fixed typo in "next page" button.
|
4
|
+
* Updated valid options for searching and performing calculations, fixed some bugs when searching and performing calculations with advanced options.
|
5
|
+
* Fixed bug in ordering where table name was assumed by the hash. Now assumed by the reflection.
|
6
|
+
* Added default for per_page, so pagination comes implemented by default
|
7
|
+
* On mass assignments blank strings for *any* conditions are ignored. Sometimes blank strings are meaningful for "equals" and "does not equal", those only takes effect if you explicitly call these conditions: search.conditions.name = "". User.new_search(:conditions => {:name => ""}) will be ignored. Also, Searchgasm should never change how ActiveRecord behaves by default. So User.all(:conditions => {:name => ""}) will NOT be ignored.
|
8
|
+
|
1
9
|
== 1.1.0 released 2008-09-18
|
2
10
|
|
3
11
|
* Added the options :inner_spread and :outer_spread to the page_links helper. Also added various config options for setting page_links defaults.
|
@@ -8,7 +8,7 @@ module Searchgasm
|
|
8
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
|
-
args <<
|
11
|
+
args << filter_options_with_searchgasm(options)
|
12
12
|
find_without_searchgasm(*args)
|
13
13
|
end
|
14
14
|
|
@@ -36,7 +36,7 @@ module Searchgasm
|
|
36
36
|
module Shared
|
37
37
|
def count_with_searchgasm(*args)
|
38
38
|
options = args.extract_options!
|
39
|
-
args <<
|
39
|
+
args << filter_options_with_searchgasm(options)
|
40
40
|
count_without_searchgasm(*args)
|
41
41
|
end
|
42
42
|
end
|
@@ -6,21 +6,15 @@ module Searchgasm
|
|
6
6
|
# This is an alias method chain. It hook into ActiveRecord's "calculate" method and checks to see if Searchgasm should get involved.
|
7
7
|
def calculate_with_searchgasm(*args)
|
8
8
|
options = args.extract_options!
|
9
|
-
options =
|
9
|
+
options = filter_options_with_searchgasm(options)
|
10
10
|
args << options
|
11
11
|
calculate_without_searchgasm(*args)
|
12
12
|
end
|
13
13
|
|
14
|
-
def total(*args)
|
15
|
-
options = args.extract_options!
|
16
|
-
searcher = searchgasm_searcher(options)
|
17
|
-
searcher.total
|
18
|
-
end
|
19
|
-
|
20
14
|
# This is an alias method chain. It hooks into ActiveRecord's "find" method and checks to see if Searchgasm should get involved.
|
21
15
|
def find_with_searchgasm(*args)
|
22
16
|
options = args.extract_options!
|
23
|
-
options =
|
17
|
+
options = filter_options_with_searchgasm(options)
|
24
18
|
args << options
|
25
19
|
find_without_searchgasm(*args)
|
26
20
|
end
|
@@ -45,7 +39,7 @@ module Searchgasm
|
|
45
39
|
# build_search
|
46
40
|
# end
|
47
41
|
def with_scope_with_searchgasm(method_scoping = {}, action = :merge, &block)
|
48
|
-
method_scoping[:find] =
|
42
|
+
method_scoping[:find] = filter_options_with_searchgasm(method_scoping[:find]) if method_scoping[:find]
|
49
43
|
with_scope_without_searchgasm(method_scoping, action, &block)
|
50
44
|
end
|
51
45
|
|
@@ -130,10 +124,19 @@ module Searchgasm
|
|
130
124
|
end
|
131
125
|
|
132
126
|
private
|
133
|
-
def
|
127
|
+
def filter_options_with_searchgasm(options = {})
|
134
128
|
return options unless Searchgasm::Search::Base.needed?(self, options)
|
135
129
|
search = Searchgasm::Search::Base.create_virtual_class(self).new # call explicitly to avoid merging the scopes into the searcher
|
136
130
|
search.acting_as_filter = true
|
131
|
+
conditions = options.delete(:conditions) || options.delete("conditions") || {}
|
132
|
+
if conditions
|
133
|
+
case conditions
|
134
|
+
when Hash
|
135
|
+
conditions.each { |condition, value| search.conditions.send("#{condition}=", value) } # explicitly call to enforce blanks
|
136
|
+
else
|
137
|
+
search.conditions = conditions
|
138
|
+
end
|
139
|
+
end
|
137
140
|
search.options = options
|
138
141
|
search.sanitize
|
139
142
|
end
|
@@ -181,8 +184,12 @@ module ActiveRecord #:nodoc: all
|
|
181
184
|
alias_method :new_search!, :build_search!
|
182
185
|
|
183
186
|
def valid_find_options
|
184
|
-
|
185
|
-
|
187
|
+
VALID_FIND_OPTIONS
|
188
|
+
end
|
189
|
+
|
190
|
+
def valid_calculations_options
|
191
|
+
Calculations::CALCULATIONS_OPTIONS
|
192
|
+
end
|
186
193
|
end
|
187
194
|
end
|
188
195
|
end
|
@@ -135,7 +135,10 @@ module Searchgasm
|
|
135
135
|
case conditions
|
136
136
|
when Hash
|
137
137
|
assert_valid_conditions(conditions)
|
138
|
-
remove_conditions_from_protected_assignement(conditions).each
|
138
|
+
remove_conditions_from_protected_assignement(conditions).each do |condition, value|
|
139
|
+
next if value.blank? # ignore blanks on mass assignments
|
140
|
+
send("#{condition}=", value)
|
141
|
+
end
|
139
142
|
else
|
140
143
|
self.sql = conditions
|
141
144
|
end
|
data/lib/searchgasm/config.rb
CHANGED
@@ -92,12 +92,12 @@ module Searchgasm
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def page_links_next # :nodoc:
|
95
|
-
@page_links_next ||= "
|
95
|
+
@page_links_next ||= "Next >"
|
96
96
|
end
|
97
97
|
|
98
98
|
# The default for the :next option for the page_links helper.
|
99
99
|
#
|
100
|
-
# * <tt>Default:</tt> "
|
100
|
+
# * <tt>Default:</tt> "Next >"
|
101
101
|
# * <tt>Accepts:</tt> Anything you want, text, html, etc. nil to disable
|
102
102
|
def page_links_next=(value)
|
103
103
|
@page_links_next = value
|
@@ -116,14 +116,14 @@ module Searchgasm
|
|
116
116
|
end
|
117
117
|
|
118
118
|
def per_page # :nodoc:
|
119
|
-
@per_page
|
119
|
+
@per_page ||= per_page_choices[2]
|
120
120
|
end
|
121
121
|
|
122
122
|
# The default for per page. This is only applicaple for protected searches. Meaning you start the search with new_search or new_conditions.
|
123
123
|
# The reason for this not to disturb regular queries such as Whatever.find(:all). You would not expect that to be limited.
|
124
124
|
#
|
125
|
-
# * <tt>Default:</tt>
|
126
|
-
# * <tt>Accepts:</tt> Any value in your per_page choices
|
125
|
+
# * <tt>Default:</tt> The 3rd option in your per_page_choices, default of 50
|
126
|
+
# * <tt>Accepts:</tt> Any value in your per_page choices, nil means "show all"
|
127
127
|
def per_page=(value)
|
128
128
|
@per_page = value
|
129
129
|
end
|
@@ -9,13 +9,21 @@ module Searchgasm #:nodoc:
|
|
9
9
|
include Searchgasm::Shared::Searching
|
10
10
|
include Searchgasm::Shared::VirtualClasses
|
11
11
|
|
12
|
+
# Options ActiveRecord allows when searching
|
13
|
+
AR_FIND_OPTIONS = ::ActiveRecord::Base.valid_find_options
|
14
|
+
|
15
|
+
# Options ActiveRecord allows when performing calculations
|
16
|
+
AR_CALCULATIONS_OPTIONS = ::ActiveRecord::Base.valid_calculations_options
|
17
|
+
|
18
|
+
AR_OPTIONS = (AR_FIND_OPTIONS + AR_CALCULATIONS_OPTIONS).uniq
|
19
|
+
|
12
20
|
# Options that ActiveRecord doesn't suppport, but Searchgasm does
|
13
21
|
SPECIAL_FIND_OPTIONS = [:order_by, :order_as, :page, :per_page]
|
14
22
|
|
15
23
|
# Valid options you can use when searching
|
16
|
-
|
24
|
+
OPTIONS = SPECIAL_FIND_OPTIONS + AR_OPTIONS # the order is very important, these options get set in this order
|
17
25
|
|
18
|
-
attr_accessor
|
26
|
+
attr_accessor *AR_OPTIONS
|
19
27
|
|
20
28
|
class << self
|
21
29
|
# Used in the ActiveRecord methods to determine if Searchgasm should get involved or not.
|
@@ -47,7 +55,7 @@ module Searchgasm #:nodoc:
|
|
47
55
|
# Makes using searchgasm in the console less annoying and keeps the output meaningful and useful
|
48
56
|
def inspect
|
49
57
|
current_find_options = {}
|
50
|
-
|
58
|
+
AR_OPTIONS.each do |option|
|
51
59
|
value = send(option)
|
52
60
|
next if value.nil?
|
53
61
|
current_find_options[option] = value
|
@@ -72,10 +80,9 @@ module Searchgasm #:nodoc:
|
|
72
80
|
|
73
81
|
def options=(values)
|
74
82
|
return unless values.is_a?(Hash)
|
75
|
-
values.symbolize_keys.fast_assert_valid_keys(
|
83
|
+
values.symbolize_keys.fast_assert_valid_keys(OPTIONS)
|
76
84
|
|
77
|
-
|
78
|
-
VALID_FIND_OPTIONS.each do |option|
|
85
|
+
OPTIONS.each do |option|
|
79
86
|
next unless values.has_key?(option)
|
80
87
|
send("#{option}=", values[option])
|
81
88
|
end
|
@@ -84,9 +91,9 @@ module Searchgasm #:nodoc:
|
|
84
91
|
end
|
85
92
|
|
86
93
|
# Sanitizes everything down into options ActiveRecord::Base.find can understand
|
87
|
-
def sanitize
|
94
|
+
def sanitize(searching = true)
|
88
95
|
find_options = {}
|
89
|
-
|
96
|
+
(searching ? AR_FIND_OPTIONS : AR_CALCULATIONS_OPTIONS).each do |find_option|
|
90
97
|
value = send(find_option)
|
91
98
|
next if value.blank?
|
92
99
|
find_options[find_option] = value
|
@@ -51,8 +51,8 @@ module Searchgasm
|
|
51
51
|
includes.blank? ? nil : (includes.size == 1 ? includes.first : includes)
|
52
52
|
end
|
53
53
|
|
54
|
-
def sanitize_with_conditions # :nodoc:
|
55
|
-
find_options = sanitize_without_conditions
|
54
|
+
def sanitize_with_conditions(searching = true) # :nodoc:
|
55
|
+
find_options = sanitize_without_conditions(searching)
|
56
56
|
if conditions_obj = find_options.delete(:conditions)
|
57
57
|
new_conditions = conditions_obj.sanitize
|
58
58
|
find_options[:conditions] = new_conditions unless new_conditions.blank?
|
@@ -115,7 +115,8 @@ module Searchgasm
|
|
115
115
|
|
116
116
|
private
|
117
117
|
def order_by_to_order(order_by, order_as, alt_klass = nil, new_includes = [])
|
118
|
-
|
118
|
+
k = alt_klass || klass
|
119
|
+
table_name = k.table_name
|
119
120
|
sql_parts = []
|
120
121
|
|
121
122
|
case order_by
|
@@ -123,10 +124,11 @@ module Searchgasm
|
|
123
124
|
order_by.each { |part| sql_parts << order_by_to_order(part, order_as) }
|
124
125
|
when Hash
|
125
126
|
raise(ArgumentError, "when passing a hash to order_by you must only have 1 key: {:user_group => :name} not {:user_group => :name, :user_group => :id}. The latter should be [{:user_group => :name}, {:user_group => :id}]") if order_by.keys.size != 1
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
127
|
+
key = order_by.keys.first
|
128
|
+
reflection = k.reflect_on_association(key.to_sym)
|
129
|
+
value = order_by.values.first
|
130
|
+
new_includes << key.to_sym
|
131
|
+
sql_parts << order_by_to_order(value, order_as, reflection.klass, new_includes) # using eval, better performance, protection makes sure nothing fishy goes on here
|
130
132
|
when Symbol, String
|
131
133
|
new_include = build_order_by_includes(new_includes)
|
132
134
|
self.order_by_includes << new_include if new_include
|
@@ -24,8 +24,12 @@ module Searchgasm
|
|
24
24
|
# Options that are allowed when protecting against SQL injections (still checked though)
|
25
25
|
SAFE_OPTIONS = Base::SPECIAL_FIND_OPTIONS + [:conditions, :limit, :offset]
|
26
26
|
|
27
|
+
VULNERABLE_FIND_OPTIONS = Base::AR_FIND_OPTIONS - SAFE_OPTIONS
|
28
|
+
|
29
|
+
VULNERABLE_CALCULATIONS_OPTIONS = Base::AR_CALCULATIONS_OPTIONS - SAFE_OPTIONS
|
30
|
+
|
27
31
|
# Options that are not allowed, at all, when protecting against SQL injections
|
28
|
-
VULNERABLE_OPTIONS = Base::
|
32
|
+
VULNERABLE_OPTIONS = Base::OPTIONS - SAFE_OPTIONS
|
29
33
|
|
30
34
|
def self.included(klass)
|
31
35
|
klass.class_eval do
|
@@ -59,12 +63,13 @@ module Searchgasm
|
|
59
63
|
|
60
64
|
k = alt_klass || klass
|
61
65
|
column_names = k.column_names
|
62
|
-
|
66
|
+
|
63
67
|
[order_by].flatten.each do |column|
|
64
68
|
case column
|
65
69
|
when Hash
|
66
|
-
|
67
|
-
return false unless
|
70
|
+
reflection = k.reflect_on_association(column.keys.first.to_sym)
|
71
|
+
return false unless reflection
|
72
|
+
return false unless order_by_safe?(column.values.first, reflection.klass)
|
68
73
|
when Array
|
69
74
|
return false unless order_by_safe?(column)
|
70
75
|
else
|
@@ -21,17 +21,15 @@ module Searchgasm
|
|
21
21
|
end
|
22
22
|
end_eval
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
# Setup methods for calculating
|
26
26
|
CALCULATION_METHODS.each do |method|
|
27
27
|
class_eval <<-"end_eval", __FILE__, __LINE__
|
28
28
|
def #{method}(*args)
|
29
29
|
options = args.extract_options!
|
30
30
|
klass.send(:with_scope, :find => options) do
|
31
|
-
find_options = (self.class < Searchgasm::Conditions::Base ? {:conditions => sanitize} : sanitize)
|
32
|
-
find_options.delete(
|
33
|
-
find_options.delete(:limit)
|
34
|
-
find_options.delete(:offset)
|
31
|
+
find_options = (self.class < Searchgasm::Conditions::Base ? {:conditions => sanitize} : sanitize(false))
|
32
|
+
[:select, :limit, :offset].each { |option| find_options.delete(option) }
|
35
33
|
args << find_options
|
36
34
|
klass.#{method}(*args)
|
37
35
|
end
|
data/lib/searchgasm/version.rb
CHANGED
data/searchgasm.gemspec
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
|
2
|
-
# Gem::Specification for Searchgasm-1.1.
|
2
|
+
# Gem::Specification for Searchgasm-1.1.1
|
3
3
|
# Originally generated by Echoe
|
4
4
|
|
5
5
|
--- !ruby/object:Gem::Specification
|
6
6
|
name: searchgasm
|
7
7
|
version: !ruby/object:Gem::Version
|
8
|
-
version: 1.1.
|
8
|
+
version: 1.1.1
|
9
9
|
platform: ruby
|
10
10
|
authors:
|
11
11
|
- Ben Johnson of Binary Logic
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
|
15
|
-
date: 2008-09-
|
15
|
+
date: 2008-09-19 00:00:00 -04:00
|
16
16
|
default_executable:
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
@@ -28,8 +28,9 @@ class TestActiveRecordBase < Test::Unit::TestCase
|
|
28
28
|
assert_nothing_raised { Account.sum("id", {}) }
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
31
|
+
def test_ar_options
|
32
32
|
assert_equal [ :conditions, :include, :joins, :limit, :offset, :order, :select, :readonly, :group, :from, :lock ], ActiveRecord::Base.valid_find_options
|
33
|
+
assert_equal [:conditions, :joins, :order, :select, :group, :having, :distinct, :limit, :offset, :include, :from], ActiveRecord::Base.valid_calculations_options
|
33
34
|
end
|
34
35
|
|
35
36
|
def test_build_search
|
@@ -185,4 +185,13 @@ class TestConditionsBase < Test::Unit::TestCase
|
|
185
185
|
conditions.any = false
|
186
186
|
assert_equal [Account.find(1)], conditions.all
|
187
187
|
end
|
188
|
+
|
189
|
+
def test_ignoring_blanks
|
190
|
+
conditions = Account.new_conditions(:name => "", :created_after => nil)
|
191
|
+
assert_equal({}, conditions.conditions)
|
192
|
+
conditions.name = ""
|
193
|
+
assert_equal({:name_equals => ""}, conditions.conditions)
|
194
|
+
conditions.created_after = ""
|
195
|
+
assert_equal({:name_equals => ""}, conditions.conditions)
|
196
|
+
end
|
188
197
|
end
|
@@ -20,5 +20,8 @@ class TestConditionsProtection < Test::Unit::TestCase
|
|
20
20
|
|
21
21
|
assert_raise(ArgumentError) { account.users.build_conditions("(DELETE FROM users)") }
|
22
22
|
assert_nothing_raised { account.users.build_conditions!("(DELETE FROM users)") }
|
23
|
+
|
24
|
+
#search = Account.new_search
|
25
|
+
#assert_nothing_raised { search.conditions = "(DELETE FROM users)" }
|
23
26
|
end
|
24
27
|
end
|
data/test/test_helper.rb
CHANGED
@@ -9,6 +9,7 @@ require File.dirname(__FILE__) + '/../lib/searchgasm'
|
|
9
9
|
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")
|
10
10
|
|
11
11
|
class Account < ActiveRecord::Base
|
12
|
+
has_one :admin, :class_name => "User", :conditions => {:first_name => "Ben"}
|
12
13
|
has_many :users, :dependent => :destroy
|
13
14
|
has_many :orders, :through => :users
|
14
15
|
end
|
@@ -17,6 +18,7 @@ class User < ActiveRecord::Base
|
|
17
18
|
acts_as_tree
|
18
19
|
belongs_to :account
|
19
20
|
has_many :orders, :dependent => :destroy
|
21
|
+
has_one :cool_order, :class_name => "Order", :conditions => {:total => 100}
|
20
22
|
end
|
21
23
|
|
22
24
|
class Order < ActiveRecord::Base
|
data/test/test_search_base.rb
CHANGED
@@ -39,7 +39,19 @@ class TestSearchBase < Test::Unit::TestCase
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def test_setting_first_level_options
|
42
|
-
search = Account.new_search
|
42
|
+
search = Account.new_search!(:include => :users, :joins => :test, :offset => 5, :limit => 20, :order => "name ASC", :select => "name", :readonly => true, :group => "name", :from => "accounts", :lock => true)
|
43
|
+
assert_equal :users, search.include
|
44
|
+
assert_equal :test, search.joins
|
45
|
+
assert_equal 5, search.offset
|
46
|
+
assert_equal 20, search.limit
|
47
|
+
assert_equal "name ASC", search.order
|
48
|
+
assert_equal "name", search.select
|
49
|
+
assert_equal true, search.readonly
|
50
|
+
assert_equal "name", search.group
|
51
|
+
assert_equal "accounts", search.from
|
52
|
+
assert_equal true, search.lock
|
53
|
+
|
54
|
+
search = Account.new_search(:per_page => nil)
|
43
55
|
|
44
56
|
search.include = :users
|
45
57
|
assert_equal :users, search.include
|
@@ -190,6 +202,9 @@ class TestSearchBase < Test::Unit::TestCase
|
|
190
202
|
assert_equal 3, search.maximum('id')
|
191
203
|
assert_equal 1, search.minimum('id')
|
192
204
|
assert_equal 4, search.sum('id')
|
205
|
+
|
206
|
+
search.readonly = true
|
207
|
+
assert_equal 4, search.sum('id')
|
193
208
|
end
|
194
209
|
|
195
210
|
def test_method_creation_in_scope
|
@@ -14,18 +14,18 @@ class TestSearchProtection < Test::Unit::TestCase
|
|
14
14
|
|
15
15
|
def test_protection
|
16
16
|
assert_raise(ArgumentError) { Account.build_search(:conditions => "(DELETE FROM users)", :page => 2, :per_page => 15) }
|
17
|
-
Searchgasm::Search::Base::
|
17
|
+
Searchgasm::Search::Base::VULNERABLE_FIND_OPTIONS.each { |option| assert_raise(ArgumentError) { Account.build_search(option => "(DELETE FROM users)") } }
|
18
18
|
|
19
19
|
assert_nothing_raised { Account.build_search!(:conditions => "(DELETE FROM users)", :page => 2, :per_page => 15) }
|
20
|
-
Searchgasm::Search::Base::
|
20
|
+
Searchgasm::Search::Base::VULNERABLE_FIND_OPTIONS.each { |option| assert_nothing_raised { Account.build_search!(option => "(DELETE FROM users)") } }
|
21
21
|
|
22
22
|
account = Account.first
|
23
23
|
|
24
24
|
assert_raise(ArgumentError) { account.users.build_search(:conditions => "(DELETE FROM users)", :page => 2, :per_page => 15) }
|
25
|
-
Searchgasm::Search::Base::
|
25
|
+
Searchgasm::Search::Base::VULNERABLE_FIND_OPTIONS.each { |option| assert_raise(ArgumentError) { account.users.build_search(option => "(DELETE FROM users)") } }
|
26
26
|
|
27
27
|
assert_nothing_raised { account.users.build_search!(:conditions => "(DELETE FROM users)", :page => 2, :per_page => 15) }
|
28
|
-
Searchgasm::Search::Base::
|
28
|
+
Searchgasm::Search::Base::VULNERABLE_FIND_OPTIONS.each { |option| assert_nothing_raised { account.users.build_search!(option => "(DELETE FROM users)") } }
|
29
29
|
|
30
30
|
assert_raise(ArgumentError) { Account.build_search(:order_by => "unknown_column") }
|
31
31
|
assert_nothing_raised { Account.build_search!(:order_by => "unknown_column") }
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: searchgasm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Johnson of Binary Logic
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-09-
|
12
|
+
date: 2008-09-19 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|