rquerypad 0.1.11

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,48 @@
1
+ Changes in version 0.1.11 (2008-04-29)
2
+ -------------------------------------
3
+ fix bugs about invalid cache for options
4
+ Changes in version 0.1.10 (2008-03-26)
5
+ -------------------------------------
6
+ make alias_method name with 4rqp(for rquerypad) suffix to avoid confliction with the 3rd plugins
7
+
8
+ Changes in version 0.1.9 (2008-03-26)
9
+ -------------------------------------
10
+ use deep copy to fix bug about options in cache is changed by later operation
11
+
12
+ Changes in version 0.1.8 (2008-03-26)
13
+ -------------------------------------
14
+ use deep copy to fix bug about options in cache is changed by later operation
15
+
16
+ Changes in version 0.1.7 (2008-03-26)
17
+ -------------------------------------
18
+ fix option value nil problem due to some 3rd plugins
19
+
20
+ Changes in version 0.1.6 (2008-03-25)
21
+ -------------------------------------
22
+ fix bug about cache key not bind to class
23
+
24
+ Changes in version 0.1.5 (2008-03-21)
25
+ -------------------------------------
26
+ fix bug when field is a id with single table which has belongs_to association, such as "parent.id"
27
+
28
+ Changes in version 0.1.4 (2008-03-20)
29
+ -------------------------------------
30
+ support calculations call, such as count/avg...
31
+
32
+ Changes in version 0.1.3 (2008-03-20)
33
+ -------------------------------------
34
+ fix about rails 1.2.6 support
35
+
36
+ Changes in version 0.1.2 (2008-03-19)
37
+ -------------------------------------
38
+ fix inner join bug
39
+
40
+ Changes in version 0.1.1 (2008-03-19)
41
+ -------------------------------------
42
+ put initialized code in rquerypad's init.rb, instead of project configuration
43
+ support to rails 1.2.6
44
+
45
+
46
+ Changes in version 0.1.0 (2008-03-18)
47
+ -------------------------------------
48
+ fix bug about table_name.field as parameter
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 [name of plugin creator]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,66 @@
1
+ Rquerypad, release 0.1.11 (Apr. 2008)
2
+ =========
3
+ Simplify query options with association automation and improve inner join for activerecord of rails
4
+
5
+ Feature
6
+ =======
7
+ 1. single name string decribe associations
8
+ 2. support to mix inner join and outer join with any order
9
+ 3. auto remove duplicated joins from other association in different depth
10
+ 4. support :conditions, :order, :group
11
+ 5. auto merge to original :include, :joins
12
+
13
+ Install
14
+ =======
15
+ ruby script/plugin install http://rquerypad.rubyforge.org/svn/trunk/rquerypad
16
+ or
17
+ ruby script/plugin install http://rquerypad.googlecode.com/svn/trunk/rquerypad
18
+
19
+ Example
20
+ =======
21
+ suppose the asscociations of User <-> Thread <-> Reply is 1:N:N
22
+
23
+ @users = User.find(:all, :group => ["threads.created_at", "name"])
24
+ generate:
25
+ [:all, {:group=>"threads.created_at, users.name", :include=>[:threads]}]
26
+
27
+ @users = User.find(:all, :conditions => ["threads_.replies.title = ?", "rquerypad"])
28
+ generate:
29
+ [:all, {:inner_joins=>["threads"], :conditions=>["replies.title = ?", "rquerypad"], :include=>[{:threads=>:replies}]}]
30
+ #note: the :inner_joints is processed by rquerypad before sending sql to database
31
+
32
+ @users = User.find(:all, :conditions => ["threads.replies.title = ? and threads.id = ?", "rquerypad", 1])
33
+ generate:
34
+ [:all, {:conditions=>["replies.title = ? and threads.id = ?", "rquerypad", 1], :include=>[{:threads=>:replies}]}]
35
+ #note: single "threads" was removed from includes
36
+
37
+ Setup
38
+ =======
39
+ #to set debug model, in rails initialized script
40
+ $RQUERYPAD_DEBUG = true
41
+
42
+ Test
43
+ =======
44
+ Note: current migrate script works only in rails 2.0
45
+
46
+ 1.Prepare
47
+
48
+ the test depends on sqlite3 database, the following code should be add into your database.yml and place rquerypad.rb(copy from test.rb) in config/environment
49
+
50
+ rquerypad:
51
+ adapter: sqlite3
52
+ database: vendor/plugins/rquerypad/test/db.rquerypad
53
+ timeout: 5000
54
+
55
+ 2.database migrate
56
+
57
+ execute the following script
58
+
59
+ rake migrate
60
+
61
+ 3.start test
62
+
63
+ execute the following script
64
+ rake
65
+
66
+ Copyright (c) 2008 Leon Li, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ PKG_NAME = "rquerypad"
4
+ PKG_VERSION = "0.1.11"
5
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
6
+ PKG_FILES = FileList[
7
+ '[A-Za-z]*',
8
+ 'lib/**/*',
9
+ 'test/**/*',
10
+ 'tasks/**/*',
11
+ ]
12
+ spec = Gem::Specification.new do |s|
13
+ s.platform = Gem::Platform::RUBY
14
+ s.summary = "Simplify query options with association automation and improve inner join for activerecord of rails"
15
+ s.name = PKG_NAME
16
+ s.version = PKG_VERSION
17
+ s.requirements << 'none'
18
+ s.require_path = 'lib'
19
+ s.rubyforge_project = 'rquerypad'
20
+ #s.executables = ['gem-sample']
21
+ #s.default_executable = 'gem-sample'
22
+ s.authors = ["Leon Li"]
23
+ s.email = "scorpio_leon@hotmail.com"
24
+ s.files = PKG_FILES
25
+ s.description = <<-EOF
26
+ Simplify query options with association automation and improve inner join for activerecord of rails
27
+ EOF
28
+ end
29
+ Rake::GemPackageTask.new(spec) do |pkg|
30
+ pkg.need_zip = true
31
+ pkg.need_tar = true
32
+ end
data/lib/rquerypad.rb ADDED
@@ -0,0 +1,318 @@
1
+ =begin Rquerypad
2
+ author: Leon Li(scorpio_leon@hotmail.com)
3
+ =end
4
+ require 'md5'
5
+ class Rquerypad
6
+ #todo scope support
7
+ class << self
8
+
9
+ def prepare_with_debug
10
+ prepare(true)
11
+ end
12
+ def prepare(debug = $RQUERYPAD_DEBUG)
13
+ return nil unless @prepared.nil?
14
+ @prepared = true
15
+ ActiveRecord::Base.class_eval %{
16
+ require "rquerypad"
17
+
18
+ class << self
19
+ @@rquerypad_cache = {}
20
+ alias_method(:old_find_4rqp, :find) unless method_defined?(:old_find_4rqp)
21
+ alias_method(:old_cfswia_4rqp, :construct_finder_sql_with_included_associations) unless method_defined?(:old_cfswia_4rqp)
22
+ VALID_FIND_OPTIONS << :inner_joins
23
+ def find(*args)
24
+ options = #{if [].respond_to?(:extract_options!) then "args.extract_options!" else "extract_options_from_args!(args)" end}
25
+ if !options.empty? && (options.include?(:conditions) || options.include?(:group) || options.include?(:order))
26
+ # if (!options.empty? && (!options[:conditions].nil? || !options[:group].nil? || !options[:order].nil?))
27
+ #{"p 'original options:', options" if debug}
28
+ cache_key = Rquerypad.options_key(options)
29
+ #p "cache_key: #\{cache_key\}"
30
+ #p "rquerypad_cache[cache_key]: #\{rquerypad_cache[cache_key]\}"
31
+ if rquerypad_cache[cache_key].nil?
32
+ #{"p 'process for:', options" if debug}
33
+ Rquerypad.new(self).improve_options!(options)
34
+ rquerypad_cache[cache_key] = Marshal.dump(options)
35
+ #p "rquerypad_cache[cache_key]: #\{rquerypad_cache[cache_key]\}"
36
+ else
37
+ options = Marshal.load(rquerypad_cache[cache_key])
38
+ end
39
+ #{"p 'new options:', options" if debug}
40
+ end
41
+ args += [options] unless options.empty?
42
+ old_find_4rqp *args
43
+ end
44
+ def construct_finder_sql_with_included_associations(options, join_dependency)
45
+ sql = old_cfswia_4rqp(options, join_dependency)
46
+ #{"p('original sql', sql) unless options[:inner_joins].nil?" if debug}
47
+ sql = Rquerypad.process_inner_join(sql, options[:inner_joins]) unless options[:inner_joins].nil?
48
+ #{"p('new sql with inner join', sql) unless options[:inner_joins].nil?" if debug}
49
+ sql
50
+ end
51
+ def rquerypad_cache
52
+ @@rquerypad_cache
53
+ end
54
+ end
55
+ }
56
+
57
+ ActiveRecord::Calculations.class_eval %{
58
+ require "rquerypad"
59
+ module ClassMethods
60
+ @@rquerypad_cache = {}
61
+ alias_method(:old_construct_calculation_sql_4rqp, :construct_calculation_sql) unless method_defined?(:old_construct_calculation_sql_4rqp)
62
+ CALCULATIONS_OPTIONS << :inner_joins
63
+ def construct_calculation_sql(operation, column_name, options)
64
+ if !options.empty? && (options.include?(:conditions) || options.include?(:group) || options.include?(:order))
65
+ #{"p 'original options:', options" if debug}
66
+ cache_key = Rquerypad.options_key(options)
67
+ if rquerypad_cache[cache_key].nil?
68
+ #{"p 'process for:', options" if debug}
69
+ Rquerypad.new(self).improve_options!(options)
70
+ rquerypad_cache[cache_key] = Marshal.load(Marshal.dump(options))
71
+ else
72
+ options = rquerypad_cache[cache_key]
73
+ end
74
+ #{"p 'new options:', options" if debug}
75
+ end
76
+ sql = old_construct_calculation_sql_4rqp(operation, column_name, options)
77
+ #{"p('original sql', sql) unless options[:inner_joins].nil?" if debug}
78
+ sql = Rquerypad.process_inner_join(sql, options[:inner_joins]) unless options[:inner_joins].nil?
79
+ #{"p('new sql with inner join', sql) unless options[:inner_joins].nil?" if debug}
80
+ sql
81
+ end
82
+ def rquerypad_cache
83
+ @@rquerypad_cache
84
+ end
85
+ end
86
+ }
87
+
88
+ Hash.class_eval do
89
+ def single_lt?(other)
90
+ return false if self == other
91
+ return true if self.size == 0
92
+ return false unless other.is_a?(Hash)
93
+ return false if other.nil? || other.size < self.size
94
+ return false if self.size != other.size || self.size > 1
95
+ a = self.to_a[0]
96
+ o = other.to_a[0]
97
+ return false if a[0] != o[0]
98
+ return true unless a[1].is_a?(Hash)
99
+ a[1].single_lt?(o[1])
100
+ end
101
+ def single_gt?(other)
102
+ return false if self == other
103
+ return !(single_lt?(other))
104
+ end
105
+ end
106
+ end
107
+
108
+ def process_inner_join(sql, inner_joins)
109
+ inner_joins.each {|i| sql.gsub!(/LEFT OUTER JOIN [`]?#{i}[`]?/, "INNER JOIN #{i}")} unless inner_joins.empty?
110
+ sql
111
+ end
112
+
113
+ def options_key(options)
114
+ key = options.to_a.to_s
115
+ key = MD5.hexdigest(key) if key.length > 100
116
+ key
117
+ end
118
+ end
119
+ def initialize(obj)
120
+ @owner = obj
121
+ @class_name = obj.to_s.scan(/(\w*::)*([^\(]*)/)[0][1]
122
+ @table_name = @class_name.pluralize.underscore
123
+ @tnwithdot = @table_name + "."
124
+ @new_include = []
125
+ @old_include = nil
126
+ @inner_joins = []
127
+ end
128
+
129
+ def improve_options!(option_hash)
130
+
131
+ option_hash.each do |key, value|
132
+ next if value.blank?
133
+ if key.to_s == "conditions"
134
+ option_hash[key] = improve_conditions(value)
135
+ elsif (key.to_s == "order" || key.to_s == "group" || key.to_s == "group_field")
136
+ option_hash[key] = improve_ordergroup(value).join(", ")
137
+ elsif (key.to_s == "include")
138
+ @old_include = value
139
+ end
140
+ end
141
+ return nil if @new_include.empty?
142
+ #generate new include
143
+
144
+ remove_dup_includes
145
+ unless @new_include.nil?
146
+ option_hash[:include] = [] if @old_include.nil?
147
+ @new_include += @old_include unless @old_include.nil?
148
+ option_hash.each do |key, value|
149
+ if key.to_s == "include"
150
+ option_hash[key] = @new_include
151
+ end
152
+ end
153
+ end
154
+ option_hash[:inner_joins] = @inner_joins unless @inner_joins.empty?
155
+ end
156
+
157
+ def remove_dup_includes
158
+ final_includes = []
159
+ @new_include.each do |ni|
160
+ next if final_includes.include?(ni)
161
+ if final_includes.size > 0
162
+ final_includes.each_index do |i|
163
+ if ni.is_a?(Hash)
164
+ if final_includes[i].is_a?(Hash)
165
+ if final_includes[i].single_lt?(ni)
166
+ final_includes[i] = ni
167
+ elsif final_includes[i].single_gt?(ni)
168
+ else
169
+ final_includes << ni
170
+ end
171
+ elsif ni.entries[0][0].to_s == final_includes[i].to_s
172
+ final_includes[i] = ni
173
+ else
174
+ final_includes << ni
175
+ end
176
+ else
177
+ if final_includes[i].is_a?(Hash)
178
+ final_includes << ni if final_includes[i].entries[0][0].to_s != ni.to_s
179
+ else
180
+ final_includes << ni if final_includes[i].to_s != ni.to_s
181
+ end
182
+ end
183
+ end
184
+ else
185
+ final_includes << ni
186
+ end
187
+ end
188
+ @new_include = final_includes
189
+ end
190
+
191
+ def improve_conditions(options)
192
+ if options.is_a?(Array)
193
+ str = options[0]
194
+ temp = str.scan(/'.*?'/)
195
+ #replace string in quote to avoid unecessary processing
196
+ str.gsub!(/'.*?'/, "'[??]'") unless temp.empty?
197
+ str.gsub!(/(([\w\(\)]+\.)+\w+)[ !><=]/) do |n|
198
+ #cut last char and abstract association for include
199
+ abstract_association(n[0..-2]) + n[-1, 1]
200
+ end
201
+ #add @table_name on single field
202
+ str.gsub!(/[\.]?\w+[\.]?/) {|x| x[-1, 1] == "." || ["and", "or", "is", "null", "not"].include?(x.downcase) ? x : @tnwithdot + x}
203
+ str.gsub!(/\.#{@table_name}\./, ".")
204
+ #recover string in quote
205
+ unless temp.empty?
206
+ i = -1
207
+ str.gsub!(/\'\[\?\?\]\'/) do
208
+ i += 1
209
+ temp[i]
210
+ end
211
+ end
212
+ options[0] = str
213
+ end
214
+ if options.is_a?(Hash)
215
+ #work around frozen issue
216
+ new_options = {}
217
+ until options.empty?
218
+ key, value = options.shift
219
+ key = key.to_s.dup
220
+ new_options[process_single!(key)] = value
221
+ end
222
+ options.merge!(new_options)
223
+ end
224
+ options
225
+ end
226
+
227
+ def process_single!(key)
228
+ if key.include?(".")
229
+ if /^(.+)[ ]/ =~ key
230
+ key.sub!("#$1", abstract_association("#$1"))
231
+ else
232
+ key.sub!(/^.+$/, abstract_association(key))
233
+ end
234
+ else
235
+ key.sub!(/^.+$/, @tnwithdot + key)
236
+ end
237
+ end
238
+
239
+ def improve_ordergroup(fields)
240
+ fields = [fields] if fields.is_a?(String)
241
+ fields.each {|field| process_single!(field)}
242
+ fields
243
+ end
244
+
245
+ def abstract_association(str)
246
+ result = nil
247
+ owner = @owner
248
+ names = str.split(".")
249
+ return str if names.size == 2 && names[0] == @table_name
250
+ #seperate assocations/tables and field
251
+ tables, field = names[0..-2], names[-1]
252
+ owners = []
253
+ #get relevant owner for each table
254
+ tables.each_index do |i|
255
+ if i == 0
256
+ owners[i] = owner
257
+ else
258
+ tname = cut_end_underscore(tables[i-1])
259
+ r = owners[i-1].reflections[tname.to_sym].options
260
+ owners[i] = r[:class_name].nil? ? eval(owners[i-1].to_s.gsub(/\w*$/, "")+tname.singularize.camelize) : Util::Common.str2class(r[:class_name])
261
+ end
262
+ end
263
+ owners.reverse!
264
+ tables.reverse!
265
+ tables.each_index do |i|
266
+ if tables[i][-1, 1] == "_"
267
+ tables[i].reverse!.sub!("_", "").reverse!
268
+ @inner_joins << transfer_table_name(tables[i], owners[i])
269
+ end
270
+ end
271
+ #process special id field in a belongs_to association
272
+ if field == "id"
273
+ if owners[0].reflections[tables[0].to_sym].macro.to_s == "belongs_to"
274
+ result = transfer_table_id(tables[0], owners[0])
275
+ @inner_joins.delete(tables[0]) if @inner_joins.include?(tables[0])
276
+ unless owners[1].nil?
277
+ result = transfer_table_name(tables[1], owners[1]) + "." + result
278
+ end
279
+ tables.delete_at(0)
280
+ owners.delete_at(0)
281
+ return result if tables.empty?
282
+ end
283
+ end
284
+
285
+ #get include
286
+ if tables.length == 1 && tables[0] != @table_name
287
+ @new_include << tables[0].to_sym unless @new_include.include?(tables[0].to_sym)
288
+ else
289
+ tables_clone = tables[0..-1]
290
+ value = tables_clone.shift.to_sym
291
+ until tables_clone.empty?
292
+ hashes = {}
293
+ hashes[tables_clone.shift.to_sym] = value
294
+ value = hashes
295
+ end
296
+ @new_include << hashes unless hashes.nil? || @new_include.include?(hashes)
297
+ end
298
+ result ||= transfer_table_name(tables[0], owners[0]) + "." + field
299
+
300
+ end
301
+
302
+ def transfer_table_name(name, owner = @owner)
303
+ owner.reflections[name.to_sym].class_name.gsub(/([\w]+::)*/, "").pluralize.underscore
304
+ end
305
+
306
+ def transfer_table_id(name, owner = @owner)
307
+ owner.reflections[name.to_sym].class_name.gsub(/([\w]+::)*/, "").underscore + "_id"
308
+ end
309
+
310
+ def cut_end_underscore(str)
311
+ str = str.reverse.sub("_", "").reverse if str[-1, 1] == "_"
312
+ str
313
+ end
314
+
315
+ def cut_end_underscore!(str)
316
+ str.reverse!.sub!("_", "").reverse! if str[-1, 1] == "_"
317
+ end
318
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :rquerypad do
3
+ # # Task goes here
4
+ # end
data/test/db.rquerypad ADDED
Binary file
@@ -0,0 +1,25 @@
1
+ reply_one:
2
+ id: 1
3
+ title: "rquerypad"
4
+ thread_id: 1
5
+ user_id: 1
6
+
7
+ reply_two:
8
+ id: 2
9
+ title: "thank you"
10
+ thread_id: 2
11
+ user_id: 2
12
+
13
+ reply_three:
14
+ id: 3
15
+ title: "thank you-1"
16
+ thread_id: 2
17
+ parent_id: 2
18
+ user_id: 2
19
+
20
+ reply_four:
21
+ id: 4
22
+ title: "thank you-2"
23
+ thread_id: 2
24
+ parent_id: 2
25
+ user_id: 2
@@ -0,0 +1,17 @@
1
+ thread_one:
2
+ id: 1
3
+ title: "welcome"
4
+ user_id: 1
5
+ created_at: "2008-03-16 00:00:00"
6
+
7
+ thread_two:
8
+ id: 2
9
+ title: "join us"
10
+ user_id: 2
11
+ created_at: "2008-03-17 00:00:00"
12
+
13
+ thread_three:
14
+ id: 3
15
+ title: "hello"
16
+ user_id: 2
17
+ created_at: "2008-03-16 20:00:00"
@@ -0,0 +1,7 @@
1
+ user_one:
2
+ id: 1
3
+ name: leon
4
+
5
+ user_two:
6
+ id: 2
7
+ name: carrol
@@ -0,0 +1,13 @@
1
+ class CreateUsers < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :users do |t|
4
+ t.string "name"
5
+ t.datetime "created_at"
6
+ t.datetime "updated_at"
7
+ end
8
+ end
9
+
10
+ def self.down
11
+ drop_table :users
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ class CreateThreads < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :threads do |t|
4
+ t.string "title"
5
+ t.string "content"
6
+ t.integer "user_id"
7
+ t.datetime "created_at"
8
+ t.datetime "updated_at"
9
+ end
10
+ end
11
+
12
+ def self.down
13
+ drop_table :threads
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ class CreateReplies < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :replies do |t|
4
+ t.string "title"
5
+ t.string "content"
6
+ t.integer "user_id"
7
+ t.integer "thread_id"
8
+ t.integer "parent_id"
9
+ t.datetime "created_at"
10
+ t.datetime "updated_at"
11
+ end
12
+ end
13
+
14
+ def self.down
15
+ drop_table :replies
16
+ end
17
+ end
data/test/model.rb ADDED
@@ -0,0 +1,17 @@
1
+ module Model
2
+ class User < ActiveRecord::Base
3
+ has_many :threads
4
+ has_many :replies
5
+ end
6
+ class Thread < ActiveRecord::Base
7
+ has_many :replies
8
+ belongs_to :user
9
+ end
10
+ class Reply < ActiveRecord::Base
11
+ belongs_to :thread
12
+ has_many :replies
13
+ belongs_to :reply, :foreign_key => "parent_id"
14
+ belongs_to :user
15
+ acts_as_tree
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+
4
+ require 'rquerypad'
5
+ require 'test/model'
6
+ class RquerypadTest < Test::Unit::TestCase
7
+ # Replace this with your real tests.
8
+ include Model
9
+ def test_this_plugin
10
+ @fixture_path = 'vendor/plugins/rquerypad/test/fixtures'
11
+
12
+ @users = User.find(:all, :group => ["threads.created_at", "name"])
13
+ assert_equal @users.size, 2
14
+
15
+ c = User.count(:conditions => ["threads_.replies.title = ?", "rquerypad"])
16
+ assert_equal c, 1
17
+
18
+ @users = User.find(:all, :conditions => ["threads.replies.title = ? and threads.id = ?", "rquerypad", 1])
19
+ assert_equal @users.size, 1
20
+
21
+ @replies = Reply.find(:all, :conditions => ["thread.id = ?", 2])
22
+ assert_equal @replies.size, 3
23
+
24
+ end
25
+ end
@@ -0,0 +1,43 @@
1
+ require 'rubygems'
2
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
3
+
4
+ require 'rquerypad'
5
+
6
+ ENV["RAILS_ENV"] = "rquerypad"
7
+ #require File.expand_path(File.dirname(__FILE__) + "/../../../../config/environment")
8
+ require 'test_help'
9
+ Test::Unit::TestCase.fixture_path = File.expand_path(File.dirname(__FILE__) + "/fixtures/")
10
+ class Test::Unit::TestCase
11
+ # Transactional fixtures accelerate your tests by wrapping each test method
12
+ # in a transaction that's rolled back on completion. This ensures that the
13
+ # test database remains unchanged so your fixtures don't have to be reloaded
14
+ # between every test method. Fewer database queries means faster tests.
15
+ #
16
+ # Read Mike Clark's excellent walkthrough at
17
+ # http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting
18
+ #
19
+ # Every Active Record database supports transactions except MyISAM tables
20
+ # in MySQL. Turn off transactional fixtures in this case; however, if you
21
+ # don't care one way or the other, switching from MyISAM to InnoDB tables
22
+ # is recommended.
23
+ #
24
+ # The only drawback to using transactional fixtures is when you actually
25
+ # need to test transactions. Since your test is bracketed by a transaction,
26
+ # any transactions started in your code will be automatically rolled back.
27
+ self.use_transactional_fixtures = true
28
+
29
+ # Instantiated fixtures are slow, but give you @david where otherwise you
30
+ # would need people(:david). If you don't want to migrate your existing
31
+ # test cases which use the @david style and don't mind the speed hit (each
32
+ # instantiated fixtures translates to a database query per test method),
33
+ # then set this back to true.
34
+ self.use_instantiated_fixtures = false
35
+
36
+ # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
37
+ #
38
+ # Note: You'll currently still have to declare fixtures explicitly in integration tests
39
+ # -- they do not yet inherit this setting
40
+ fixtures :all
41
+
42
+ # Add more helper methods to be used by all tests here...
43
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rquerypad
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.11
5
+ platform: ruby
6
+ authors:
7
+ - Leon Li
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-05-04 00:00:00 +08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Simplify query options with association automation and improve inner join for activerecord of rails
17
+ email: scorpio_leon@hotmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - CHANGELOG
26
+ - lib
27
+ - MIT-LICENSE
28
+ - pkg
29
+ - Rakefile
30
+ - README
31
+ - tasks
32
+ - test
33
+ - lib/rquerypad.rb
34
+ - test/db.rquerypad
35
+ - test/fixtures
36
+ - test/fixtures/replies.yml
37
+ - test/fixtures/threads.yml
38
+ - test/fixtures/users.yml
39
+ - test/migrate
40
+ - test/migrate/001_create_users.rb
41
+ - test/migrate/002_create_threads.rb
42
+ - test/migrate/003_create_replies.rb
43
+ - test/model.rb
44
+ - test/rquerypad_test.rb
45
+ - test/test_helper.rb
46
+ - tasks/rquerypad_tasks.rake
47
+ has_rdoc: false
48
+ homepage:
49
+ post_install_message:
50
+ rdoc_options: []
51
+
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ requirements:
67
+ - none
68
+ rubyforge_project: rquerypad
69
+ rubygems_version: 1.0.1
70
+ signing_key:
71
+ specification_version: 2
72
+ summary: Simplify query options with association automation and improve inner join for activerecord of rails
73
+ test_files: []
74
+