ar_oo_select 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/LICENSE +20 -0
- data/README.md +57 -0
- data/Rakefile +63 -0
- data/ar_oo_select.gemspec +77 -0
- data/lib/mcmire/ar_oo_select.rb +26 -0
- data/lib/mcmire/ar_oo_select/ar_ext.rb +73 -0
- data/lib/mcmire/ar_oo_select/version.rb +5 -0
- data/lib/mcmire/ar_oo_select/will_paginate_ext.rb +26 -0
- data/rails/init.rb +8 -0
- data/test/ar_oo_select_test.rb +190 -0
- data/test/helper.rb +49 -0
- metadata +147 -0
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Elliot Winkler
|
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.md
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# ar_oo_select
|
2
|
+
|
3
|
+
## Summary
|
4
|
+
|
5
|
+
A little gem that lets you execute lower-level ActiveRecord queries and access the resulting rows like you would by calling `find_by_sql`.
|
6
|
+
|
7
|
+
## Rationale
|
8
|
+
|
9
|
+
Let's face it, ActiveRecord is slow. Sometimes you need a way to bypass ActiveRecord but still enjoy the typecasting and object-oriented goodness it provides. `ar_oo_select` allows you to do just that.
|
10
|
+
|
11
|
+
As you may or may not know, ActiveRecord gives you four methods to perform a low-level SQL query through the connection object itself:
|
12
|
+
|
13
|
+
* `connection.select_all`
|
14
|
+
* `connection.select_rows`
|
15
|
+
* `connection.select_one`
|
16
|
+
* `connection.select_value`
|
17
|
+
|
18
|
+
Likewise, `ar_oo_select` gives you four methods that are simply a wrapper for their builtin counterparts:
|
19
|
+
|
20
|
+
* `oo_select_all` (aliased to `oo_select` since this is most common)
|
21
|
+
* `oo_select_rows`
|
22
|
+
* `oo_select_one`
|
23
|
+
* `oo_select_value`
|
24
|
+
|
25
|
+
The difference is that 1) your query goes through AR's `sanitize_sql` method before reaching the connection methods and 2) the values in the result set are typecasted depending on what they look like (date, time, integer, float, or boolean). In the case of `oo_select_all`, the hashes that come from the result set are converted to special hashes whose values you can access using an object-oriented syntax (or openhashes for short), so it still feels like ActiveRecord. This is done using one of four libraries you may have installed, in this order:
|
26
|
+
|
27
|
+
* [Mash](http://github.com/mbleigh/mash/)
|
28
|
+
* [OpenObject](http://facets.rubyforge.org/doc/api/more/classes/OpenObject.html), provided by Ruby Facets
|
29
|
+
* [OpenHash](http://github.com/mcmire/openhash), a library I've written
|
30
|
+
* [OpenStruct](http://apidock.com/ruby/OpenStruct), included in the Ruby standard library
|
31
|
+
|
32
|
+
## Usage
|
33
|
+
|
34
|
+
All four methods receive the same arguments as `find_by_sql`: either a statement, or statement + bind variables. In addition, you can pass a second argument to specify whether the generated SQL should be sanitized. Taking `oo_select_all` as an example:
|
35
|
+
|
36
|
+
oo_select_all(query)
|
37
|
+
oo_select_all([query, vars])
|
38
|
+
oo_select_all(query, false) # don't sanitize sql
|
39
|
+
oo_select_all([query, vars], false) # don't sanitize sql
|
40
|
+
|
41
|
+
## Installation
|
42
|
+
|
43
|
+
1. Run `gem install ar_oo_select` (probably as root)
|
44
|
+
2. Add `config.gem 'ar_oo_select'` to environment.rb
|
45
|
+
3. Optionally run `rake gems:unpack`
|
46
|
+
|
47
|
+
## Support
|
48
|
+
|
49
|
+
If you find any bugs with this plugin, feel free to:
|
50
|
+
|
51
|
+
* file a bug report in the [Issues area on Github](http://github.com/mcmire/ar_oo_select/issues)
|
52
|
+
* fork the [project on Github](http://github.com/mcmire/ar_oo_select) and send me a pull request
|
53
|
+
* email me (_firstname_ dot _lastname_ at gmail dot com)
|
54
|
+
|
55
|
+
## Author/License
|
56
|
+
|
57
|
+
(c) 2009-2010 Elliot Winkler. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
require File.dirname(__FILE__) + "/lib/mcmire/ar_oo_select/version"
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'jeweler'
|
8
|
+
Jeweler::Tasks.new do |gem|
|
9
|
+
gem.version = Mcmire::ArOoSelect::VERSION
|
10
|
+
gem.name = "ar_oo_select"
|
11
|
+
gem.summary = %Q{A little gem that lets you execute lower-level ActiveRecord queries and access the resulting rows like you would by calling `find_by_sql`}
|
12
|
+
gem.description = %Q{A little gem that lets you execute lower-level ActiveRecord queries and access the resulting rows like you would by calling `find_by_sql`}
|
13
|
+
gem.email = "elliot.winkler@gmail.com"
|
14
|
+
gem.homepage = "http://github.com/mcmire/ar_oo_select"
|
15
|
+
gem.authors = ["Elliot Winkler"]
|
16
|
+
gem.add_dependency "activerecord", "< 3.0"
|
17
|
+
gem.add_development_dependency "mcmire-protest", "~> 0.2.4"
|
18
|
+
gem.add_development_dependency "mcmire-matchy", "~> 0.4.1"
|
19
|
+
gem.add_development_dependency "mcmire-mocha", "~> 0.9.8"
|
20
|
+
gem.add_development_dependency "mocha-protest-integration"
|
21
|
+
gem.add_development_dependency "mash"
|
22
|
+
gem.add_development_dependency "mcmire-openhash"
|
23
|
+
gem.add_development_dependency "facets"
|
24
|
+
#gem.add_development_dependency "yard", ">= 0"
|
25
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
26
|
+
end
|
27
|
+
Jeweler::GemcutterTasks.new
|
28
|
+
rescue LoadError
|
29
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
30
|
+
end
|
31
|
+
|
32
|
+
require 'rake/testtask'
|
33
|
+
Rake::TestTask.new(:test) do |test|
|
34
|
+
test.libs << 'lib' << 'test'
|
35
|
+
test.pattern = 'test/**/*_test.rb'
|
36
|
+
test.verbose = true
|
37
|
+
end
|
38
|
+
|
39
|
+
begin
|
40
|
+
require 'rcov/rcovtask'
|
41
|
+
Rcov::RcovTask.new do |test|
|
42
|
+
test.libs << 'test'
|
43
|
+
test.pattern = 'test/**/*_test.rb'
|
44
|
+
test.verbose = true
|
45
|
+
end
|
46
|
+
rescue LoadError
|
47
|
+
task :rcov do
|
48
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
task :test => :check_dependencies
|
53
|
+
|
54
|
+
task :default => :test
|
55
|
+
|
56
|
+
begin
|
57
|
+
require 'yard'
|
58
|
+
YARD::Rake::YardocTask.new
|
59
|
+
rescue LoadError
|
60
|
+
task :yardoc do
|
61
|
+
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{ar_oo_select}
|
8
|
+
s.version = "0.5.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Elliot Winkler"]
|
12
|
+
s.date = %q{2010-01-14}
|
13
|
+
s.description = %q{A little gem that lets you execute lower-level ActiveRecord queries and access the resulting rows like you would by calling `find_by_sql`}
|
14
|
+
s.email = %q{elliot.winkler@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".gitignore",
|
21
|
+
"LICENSE",
|
22
|
+
"README.md",
|
23
|
+
"Rakefile",
|
24
|
+
"ar_oo_select.gemspec",
|
25
|
+
"lib/mcmire/ar_oo_select.rb",
|
26
|
+
"lib/mcmire/ar_oo_select/ar_ext.rb",
|
27
|
+
"lib/mcmire/ar_oo_select/version.rb",
|
28
|
+
"lib/mcmire/ar_oo_select/will_paginate_ext.rb",
|
29
|
+
"rails/init.rb",
|
30
|
+
"test/ar_oo_select_test.rb",
|
31
|
+
"test/helper.rb"
|
32
|
+
]
|
33
|
+
s.homepage = %q{http://github.com/mcmire/ar_oo_select}
|
34
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
35
|
+
s.require_paths = ["lib"]
|
36
|
+
s.rubygems_version = %q{1.3.5}
|
37
|
+
s.summary = %q{A little gem that lets you execute lower-level ActiveRecord queries and access the resulting rows like you would by calling `find_by_sql`}
|
38
|
+
s.test_files = [
|
39
|
+
"test/ar_oo_select_test.rb",
|
40
|
+
"test/helper.rb"
|
41
|
+
]
|
42
|
+
|
43
|
+
if s.respond_to? :specification_version then
|
44
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
45
|
+
s.specification_version = 3
|
46
|
+
|
47
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
48
|
+
s.add_runtime_dependency(%q<activerecord>, ["< 3.0"])
|
49
|
+
s.add_development_dependency(%q<mcmire-protest>, ["~> 0.2.4"])
|
50
|
+
s.add_development_dependency(%q<mcmire-matchy>, ["~> 0.4.1"])
|
51
|
+
s.add_development_dependency(%q<mcmire-mocha>, ["~> 0.9.8"])
|
52
|
+
s.add_development_dependency(%q<mocha-protest-integration>, [">= 0"])
|
53
|
+
s.add_development_dependency(%q<mash>, [">= 0"])
|
54
|
+
s.add_development_dependency(%q<mcmire-openhash>, [">= 0"])
|
55
|
+
s.add_development_dependency(%q<facets>, [">= 0"])
|
56
|
+
else
|
57
|
+
s.add_dependency(%q<activerecord>, ["< 3.0"])
|
58
|
+
s.add_dependency(%q<mcmire-protest>, ["~> 0.2.4"])
|
59
|
+
s.add_dependency(%q<mcmire-matchy>, ["~> 0.4.1"])
|
60
|
+
s.add_dependency(%q<mcmire-mocha>, ["~> 0.9.8"])
|
61
|
+
s.add_dependency(%q<mocha-protest-integration>, [">= 0"])
|
62
|
+
s.add_dependency(%q<mash>, [">= 0"])
|
63
|
+
s.add_dependency(%q<mcmire-openhash>, [">= 0"])
|
64
|
+
s.add_dependency(%q<facets>, [">= 0"])
|
65
|
+
end
|
66
|
+
else
|
67
|
+
s.add_dependency(%q<activerecord>, ["< 3.0"])
|
68
|
+
s.add_dependency(%q<mcmire-protest>, ["~> 0.2.4"])
|
69
|
+
s.add_dependency(%q<mcmire-matchy>, ["~> 0.4.1"])
|
70
|
+
s.add_dependency(%q<mcmire-mocha>, ["~> 0.9.8"])
|
71
|
+
s.add_dependency(%q<mocha-protest-integration>, [">= 0"])
|
72
|
+
s.add_dependency(%q<mash>, [">= 0"])
|
73
|
+
s.add_dependency(%q<mcmire-openhash>, [">= 0"])
|
74
|
+
s.add_dependency(%q<facets>, [">= 0"])
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Mcmire
|
2
|
+
module ArOoSelect
|
3
|
+
def self.open_hash
|
4
|
+
@open_hash ||= try_loading(
|
5
|
+
['mash', :Mash],
|
6
|
+
['facets/openobject', :OpenObject],
|
7
|
+
['openhash', :OpenHash],
|
8
|
+
['ostruct' => :OpenStruct]
|
9
|
+
)
|
10
|
+
end
|
11
|
+
def self.try_loading(*libs)
|
12
|
+
klass = nil
|
13
|
+
libs.each do |path, sym|
|
14
|
+
begin
|
15
|
+
require path
|
16
|
+
klass = Object.const_get(sym)
|
17
|
+
break
|
18
|
+
rescue LoadError
|
19
|
+
end
|
20
|
+
end
|
21
|
+
klass
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'mcmire/ar_oo_select/ar_ext'
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Mcmire
|
2
|
+
module ArOoSelect
|
3
|
+
module ArExt
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
alias_method :oo_select, :oo_select_all
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# Executes the query and returns an array of openhashes.
|
11
|
+
def oo_select_all(query, options={})
|
12
|
+
options.reverse_merge!(:sanitize => true, :type_cast => true)
|
13
|
+
query = sanitize_sql(query) if options[:sanitize]
|
14
|
+
rows = connection.select_all(query)
|
15
|
+
if options[:type_cast]
|
16
|
+
rows.map! do |row|
|
17
|
+
oh = ArOoSelect.open_hash.new
|
18
|
+
row.each {|k, v| oh.send("#{k}=", oo_select_type_cast(v)) }
|
19
|
+
oh
|
20
|
+
end
|
21
|
+
end
|
22
|
+
rows
|
23
|
+
end
|
24
|
+
|
25
|
+
# Executes the query and returns the first row as an openhash.
|
26
|
+
def oo_select_one(query, options={})
|
27
|
+
oo_select_all(query, options).first
|
28
|
+
end
|
29
|
+
|
30
|
+
# Executes the query and returns the value of the first column in the first row.
|
31
|
+
def oo_select_value(query, options={})
|
32
|
+
options.reverse_merge!(:sanitize => true, :type_cast => true)
|
33
|
+
query = sanitize_sql(query) if options[:sanitize]
|
34
|
+
value = connection.select_value(query)
|
35
|
+
value = oo_select_type_cast(value) if options[:type_cast]
|
36
|
+
value
|
37
|
+
end
|
38
|
+
|
39
|
+
# Executes the query and returns an array of rows.
|
40
|
+
def oo_select_rows(query, options={})
|
41
|
+
options.reverse_merge!(:sanitize => true, :type_cast => true)
|
42
|
+
query = sanitize_sql(query) if options[:sanitize]
|
43
|
+
rows = connection.select_rows(query)
|
44
|
+
if options[:type_cast]
|
45
|
+
rows.map! do |row|
|
46
|
+
row.map {|v| oo_select_type_cast(v) }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
rows
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
def oo_select_type_cast(v)
|
54
|
+
return unless v
|
55
|
+
if md = v.match(/^(\d{4})-(\d{2})-(\d{2})$/)
|
56
|
+
Date.new(*md.captures.map(&:to_i)) rescue v
|
57
|
+
elsif md = v.match(/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/)
|
58
|
+
Time.local(*md.captures.map(&:to_i)) rescue v
|
59
|
+
elsif v =~ /^(?:-|\+)?\d+$/
|
60
|
+
v.to_i
|
61
|
+
elsif v =~ /^(?:-|\+)?\d+(?:\.\d+)+$/
|
62
|
+
v.to_f
|
63
|
+
elsif v == "true"
|
64
|
+
true
|
65
|
+
elsif v == "false"
|
66
|
+
false
|
67
|
+
else
|
68
|
+
v
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ArOoSelect
|
2
|
+
module WillPaginateExt
|
3
|
+
# Patch to use our oo_select_all instead of connection.select_all
|
4
|
+
def oo_select_paginate(sql, options)
|
5
|
+
WillPaginate::Collection.create(*wp_parse_options(options)) do |pager|
|
6
|
+
query = sanitize_sql(sql)
|
7
|
+
original_query = query.dup
|
8
|
+
# add limit, offset
|
9
|
+
add_limit! query, :offset => pager.offset, :limit => pager.per_page
|
10
|
+
# perform the find
|
11
|
+
pager.replace oo_select_all(query)
|
12
|
+
|
13
|
+
unless pager.total_entries
|
14
|
+
count_query = original_query.sub /\bORDER\s+BY\s+[\w`,\s]+$/mi, ''
|
15
|
+
count_query = "SELECT COUNT(*) FROM (#{count_query})"
|
16
|
+
|
17
|
+
unless ['oracle', 'oci'].include?(self.connection.adapter_name.downcase)
|
18
|
+
count_query << ' AS count_table'
|
19
|
+
end
|
20
|
+
# perform the count query
|
21
|
+
pager.total_entries = count_by_sql(count_query)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/rails/init.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
require 'mcmire/ar_oo_select'
|
2
|
+
ActiveRecord::Base.extend(Mcmire::ArOoSelect::ArExt)
|
3
|
+
|
4
|
+
# I'm not sure if this should be here?
|
5
|
+
#if defined?(WillPaginate)
|
6
|
+
# require 'mcmire/ar_oo_select/will_paginate_ext'
|
7
|
+
# ActiveRecord::Base.extend(ArOoSelect::WillPaginateExt)
|
8
|
+
#end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
$shared_tests = lambda do
|
4
|
+
context "oo_select_all" do
|
5
|
+
before do
|
6
|
+
ActiveRecord::Base.stubs(:sanitize_sql).returns("sanitized query")
|
7
|
+
ActiveRecord::Base.connection.stubs(:select_all).returns([ {"foo" => "1"} ])
|
8
|
+
end
|
9
|
+
test "sanitized and type casted" do
|
10
|
+
results = ActiveRecord::Base.oo_select_all(["query", "some", "args"])
|
11
|
+
p :results => results
|
12
|
+
ActiveRecord::Base.should have_received(:sanitize_sql).with(["query", "some", "args"])
|
13
|
+
ActiveRecord::Base.connection.should have_received(:select_all).with("sanitized query")
|
14
|
+
results[0].foo.should == 1
|
15
|
+
end
|
16
|
+
test "not sanitized, just type casted" do
|
17
|
+
results = ActiveRecord::Base.oo_select_all("query", :sanitize => false)
|
18
|
+
ActiveRecord::Base.should have_received(:sanitize_sql).never
|
19
|
+
ActiveRecord::Base.connection.should have_received(:select_all).with("query")
|
20
|
+
results[0].foo.should == 1
|
21
|
+
end
|
22
|
+
test "not type casted, just sanitized" do
|
23
|
+
results = ActiveRecord::Base.oo_select_all(["query", "some", "args"], :type_cast => false)
|
24
|
+
ActiveRecord::Base.should have_received(:sanitize_sql).with(["query", "some", "args"])
|
25
|
+
ActiveRecord::Base.connection.should have_received(:select_all).with("sanitized query")
|
26
|
+
results[0]["foo"].should == "1"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
context "oo_select_one" do
|
30
|
+
before do
|
31
|
+
ActiveRecord::Base.stubs(:sanitize_sql).returns("sanitized query")
|
32
|
+
ActiveRecord::Base.connection.stubs(:select_all).returns([ {"foo" => "1"} ])
|
33
|
+
end
|
34
|
+
test "sanitized and type casted" do
|
35
|
+
result = ActiveRecord::Base.oo_select_one(["query", "some", "args"])
|
36
|
+
ActiveRecord::Base.should have_received(:sanitize_sql).with(["query", "some", "args"])
|
37
|
+
ActiveRecord::Base.connection.should have_received(:select_all).with("sanitized query")
|
38
|
+
result.foo.should == 1
|
39
|
+
end
|
40
|
+
test "not sanitized, just type casted" do
|
41
|
+
result = ActiveRecord::Base.oo_select_one("query", :sanitize => false)
|
42
|
+
ActiveRecord::Base.should have_received(:sanitize_sql).never
|
43
|
+
ActiveRecord::Base.connection.should have_received(:select_all).with("query")
|
44
|
+
result.foo.should == 1
|
45
|
+
end
|
46
|
+
test "not type casted, just sanitized" do
|
47
|
+
result = ActiveRecord::Base.oo_select_one(["query", "some", "args"], :type_cast => false)
|
48
|
+
ActiveRecord::Base.should have_received(:sanitize_sql).with(["query", "some", "args"])
|
49
|
+
ActiveRecord::Base.connection.should have_received(:select_all).with("sanitized query")
|
50
|
+
result["foo"].should == "1"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
context "oo_select_value" do
|
54
|
+
before do
|
55
|
+
ActiveRecord::Base.stubs(:sanitize_sql).returns("sanitized query")
|
56
|
+
ActiveRecord::Base.connection.stubs(:select_value).returns("1")
|
57
|
+
end
|
58
|
+
test "sanitized and type casted" do
|
59
|
+
result = ActiveRecord::Base.oo_select_value(["query", "some", "args"])
|
60
|
+
ActiveRecord::Base.should have_received(:sanitize_sql).with(["query", "some", "args"])
|
61
|
+
ActiveRecord::Base.connection.should have_received(:select_value).with("sanitized query")
|
62
|
+
result.should == 1
|
63
|
+
end
|
64
|
+
test "not sanitized, just type casted" do
|
65
|
+
result = ActiveRecord::Base.oo_select_value("query", :sanitize => false)
|
66
|
+
ActiveRecord::Base.should have_received(:sanitize_sql).never
|
67
|
+
ActiveRecord::Base.connection.should have_received(:select_value).with("query")
|
68
|
+
result.should == 1
|
69
|
+
end
|
70
|
+
test "not type casted, just sanitized" do
|
71
|
+
result = ActiveRecord::Base.oo_select_value(["query", "some", "args"], :type_cast => false)
|
72
|
+
ActiveRecord::Base.should have_received(:sanitize_sql).with(["query", "some", "args"])
|
73
|
+
ActiveRecord::Base.connection.should have_received(:select_value).with("sanitized query")
|
74
|
+
result.should == "1"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
context "oo_select_rows" do
|
78
|
+
before do
|
79
|
+
ActiveRecord::Base.stubs(:sanitize_sql).returns("sanitized query")
|
80
|
+
ActiveRecord::Base.connection.stubs(:select_rows).returns([ ["foo", "1"] ])
|
81
|
+
end
|
82
|
+
test "sanitized and type casted" do
|
83
|
+
results = ActiveRecord::Base.oo_select_rows(["query", "some", "args"])
|
84
|
+
ActiveRecord::Base.should have_received(:sanitize_sql).with(["query", "some", "args"])
|
85
|
+
ActiveRecord::Base.connection.should have_received(:select_rows).with("sanitized query")
|
86
|
+
results[0].should == ["foo", 1]
|
87
|
+
end
|
88
|
+
test "not sanitized, just type casted" do
|
89
|
+
results = ActiveRecord::Base.oo_select_rows("query", :sanitize => false)
|
90
|
+
ActiveRecord::Base.should have_received(:sanitize_sql).never
|
91
|
+
ActiveRecord::Base.connection.should have_received(:select_rows).with("query")
|
92
|
+
results[0].should == ["foo", 1]
|
93
|
+
end
|
94
|
+
test "not type casted, just sanitized" do
|
95
|
+
results = ActiveRecord::Base.oo_select_rows(["query", "some", "args"], :type_cast => false)
|
96
|
+
ActiveRecord::Base.should have_received(:sanitize_sql).with(["query", "some", "args"])
|
97
|
+
ActiveRecord::Base.connection.should have_received(:select_rows).with("sanitized query")
|
98
|
+
results[0].should == ["foo", "1"]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def stub_query(sym)
|
104
|
+
ActiveRecord::Base.connection.stubs(sym).returns([
|
105
|
+
{
|
106
|
+
"created_at" => "2009-01-02 11:22:33",
|
107
|
+
"created_on" => "2009-01-02",
|
108
|
+
"loss" => "-3",
|
109
|
+
"gain" => "11",
|
110
|
+
"money_loss" => "-3.34",
|
111
|
+
"money_gain" => "9.24",
|
112
|
+
"zaxbied" => "true",
|
113
|
+
"yazzled" => "false",
|
114
|
+
"text" => "yellow"
|
115
|
+
}
|
116
|
+
])
|
117
|
+
end
|
118
|
+
|
119
|
+
Protest.context "ar_oo_select" do
|
120
|
+
context "using mash" do
|
121
|
+
global_setup do
|
122
|
+
require 'mash'
|
123
|
+
end
|
124
|
+
#global_teardown do
|
125
|
+
# Object.remove_class(Mash)
|
126
|
+
# Object.const_defined?(:Mash) and raise "Tried to remove Mash, but it's still defined!"
|
127
|
+
#end
|
128
|
+
setup do
|
129
|
+
Mcmire::ArOoSelect.stubs(:open_hash).returns(Mash)
|
130
|
+
end
|
131
|
+
instance_eval(&$shared_tests)
|
132
|
+
end
|
133
|
+
|
134
|
+
context "using my openhash" do
|
135
|
+
global_setup do
|
136
|
+
require 'openhash'
|
137
|
+
end
|
138
|
+
#global_teardown do
|
139
|
+
# Object.remove_class(OpenHash)
|
140
|
+
# Object.const_defined?(:OpenHash) and raise "Tried to remove OpenHash, but it's still defined!"
|
141
|
+
#end
|
142
|
+
setup do
|
143
|
+
Mcmire::ArOoSelect.stubs(:open_hash).returns(OpenHash)
|
144
|
+
end
|
145
|
+
instance_eval(&$shared_tests)
|
146
|
+
end
|
147
|
+
|
148
|
+
# XXX: I can't get this to work for some reason?!
|
149
|
+
#context "using facets' openhash" do
|
150
|
+
# global_setup do
|
151
|
+
# require 'facets/openhash'
|
152
|
+
# end
|
153
|
+
# global_teardown do
|
154
|
+
# Object.remove_class(OpenHash)
|
155
|
+
# Object.const_defined?(:OpenHash) and raise "Tried to remove OpenHash, but it's still defined!"
|
156
|
+
# end
|
157
|
+
# setup do
|
158
|
+
# Mcmire::ArOoSelect.stubs(:open_hash).returns(OpenHash)
|
159
|
+
# end
|
160
|
+
# instance_eval(&$shared_tests)
|
161
|
+
#end
|
162
|
+
|
163
|
+
context "using facets' openobject" do
|
164
|
+
global_setup do
|
165
|
+
require 'facets/openobject'
|
166
|
+
end
|
167
|
+
#global_teardown do
|
168
|
+
# Object.remove_class(OpenObject)
|
169
|
+
# Object.const_defined?(:OpenObject) and raise "Tried to remove OpenObject, but it's still defined!"
|
170
|
+
#end
|
171
|
+
setup do
|
172
|
+
Mcmire::ArOoSelect.stubs(:open_hash).returns(OpenObject)
|
173
|
+
end
|
174
|
+
instance_eval(&$shared_tests)
|
175
|
+
end
|
176
|
+
|
177
|
+
context "using ruby built-in ostruct" do
|
178
|
+
global_setup do
|
179
|
+
require 'ostruct'
|
180
|
+
end
|
181
|
+
#global_teardown do
|
182
|
+
# Object.remove_class(OpenStruct)
|
183
|
+
# Object.const_defined?(:OpenStruct) and raise "Tried to remove OpenStruct, but it's still defined!"
|
184
|
+
#end
|
185
|
+
setup do
|
186
|
+
Mcmire::ArOoSelect.stubs(:open_hash).returns(OpenStruct)
|
187
|
+
end
|
188
|
+
instance_eval(&$shared_tests)
|
189
|
+
end
|
190
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
require 'activerecord'
|
4
|
+
|
5
|
+
gem 'mcmire-protest'
|
6
|
+
require 'protest'
|
7
|
+
gem 'mcmire-matchy'
|
8
|
+
require 'matchy'
|
9
|
+
gem 'mcmire-mocha'
|
10
|
+
require 'mocha'
|
11
|
+
require 'mocha-protest-integration'
|
12
|
+
|
13
|
+
Protest.report_with :documentation
|
14
|
+
|
15
|
+
Protest::Utils::BacktraceFilter::ESCAPE_PATHS << %r|test/unit| << %r|matchy| << %r|mocha-protest-integration|
|
16
|
+
|
17
|
+
# soon to be mocha-matchy-integration
|
18
|
+
class Protest::TestCase
|
19
|
+
custom_matcher :have_received do |receiver, matcher, args|
|
20
|
+
receiver = receiver.respond_to?(:mocha) ? receiver.mocha : receiver
|
21
|
+
expected_method_name = args[0]
|
22
|
+
|
23
|
+
expectation = Mocha::Expectation.new(receiver, expected_method_name)
|
24
|
+
|
25
|
+
matcher.chained_messages.each do |message|
|
26
|
+
expectation.send(message.name, *message.args, &message.block)
|
27
|
+
end
|
28
|
+
invocations = Mocha::Mockery.instance.invocations.select do |invocation|
|
29
|
+
invocation.mock.equal?(receiver)
|
30
|
+
end
|
31
|
+
matching_invocations = invocations.select do |invocation|
|
32
|
+
expectation.match?(invocation.method_name, *invocation.arguments)
|
33
|
+
end
|
34
|
+
expectation.invocation_count = matching_invocations.size
|
35
|
+
ret = expectation.verified?
|
36
|
+
|
37
|
+
matcher.positive_failure_message = expectation.mocha_inspect
|
38
|
+
matcher.negative_failure_message = "You should never get this error message. You're probably saying .should_not have_received(...). Try using .should have_received(...).never instead."
|
39
|
+
|
40
|
+
ret
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
ActiveRecord::Base.establish_connection(
|
45
|
+
"adapter" => "sqlite3",
|
46
|
+
"database" => ":memory:"
|
47
|
+
)
|
48
|
+
|
49
|
+
require 'rails/init'
|
metadata
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ar_oo_select
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Elliot Winkler
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-01-14 00:00:00 -06:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activerecord
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - <
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "3.0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: mcmire-protest
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.2.4
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: mcmire-matchy
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.4.1
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: mcmire-mocha
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.9.8
|
54
|
+
version:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mocha-protest-integration
|
57
|
+
type: :development
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: "0"
|
64
|
+
version:
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: mash
|
67
|
+
type: :development
|
68
|
+
version_requirement:
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: "0"
|
74
|
+
version:
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: mcmire-openhash
|
77
|
+
type: :development
|
78
|
+
version_requirement:
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: "0"
|
84
|
+
version:
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: facets
|
87
|
+
type: :development
|
88
|
+
version_requirement:
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: "0"
|
94
|
+
version:
|
95
|
+
description: A little gem that lets you execute lower-level ActiveRecord queries and access the resulting rows like you would by calling `find_by_sql`
|
96
|
+
email: elliot.winkler@gmail.com
|
97
|
+
executables: []
|
98
|
+
|
99
|
+
extensions: []
|
100
|
+
|
101
|
+
extra_rdoc_files:
|
102
|
+
- LICENSE
|
103
|
+
- README.md
|
104
|
+
files:
|
105
|
+
- .gitignore
|
106
|
+
- LICENSE
|
107
|
+
- README.md
|
108
|
+
- Rakefile
|
109
|
+
- ar_oo_select.gemspec
|
110
|
+
- lib/mcmire/ar_oo_select.rb
|
111
|
+
- lib/mcmire/ar_oo_select/ar_ext.rb
|
112
|
+
- lib/mcmire/ar_oo_select/version.rb
|
113
|
+
- lib/mcmire/ar_oo_select/will_paginate_ext.rb
|
114
|
+
- rails/init.rb
|
115
|
+
- test/ar_oo_select_test.rb
|
116
|
+
- test/helper.rb
|
117
|
+
has_rdoc: true
|
118
|
+
homepage: http://github.com/mcmire/ar_oo_select
|
119
|
+
licenses: []
|
120
|
+
|
121
|
+
post_install_message:
|
122
|
+
rdoc_options:
|
123
|
+
- --charset=UTF-8
|
124
|
+
require_paths:
|
125
|
+
- lib
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: "0"
|
131
|
+
version:
|
132
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: "0"
|
137
|
+
version:
|
138
|
+
requirements: []
|
139
|
+
|
140
|
+
rubyforge_project:
|
141
|
+
rubygems_version: 1.3.5
|
142
|
+
signing_key:
|
143
|
+
specification_version: 3
|
144
|
+
summary: A little gem that lets you execute lower-level ActiveRecord queries and access the resulting rows like you would by calling `find_by_sql`
|
145
|
+
test_files:
|
146
|
+
- test/ar_oo_select_test.rb
|
147
|
+
- test/helper.rb
|