ar-extensions 0.9.2 → 0.9.3
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/Rakefile +45 -63
- data/db/migrate/generic_schema.rb +1 -0
- data/db/migrate/mysql_schema.rb +1 -0
- data/db/migrate/version.rb +1 -1
- data/lib/ar-extensions/extensions.rb +1 -1
- data/lib/ar-extensions/temporary_table.rb +74 -67
- metadata +31 -13
data/Rakefile
CHANGED
@@ -1,79 +1,61 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "pathname"
|
2
|
+
require "rubygems"
|
3
|
+
require "rake"
|
4
|
+
require "rake/testtask"
|
4
5
|
|
5
|
-
DIR
|
6
|
+
DIR = Pathname.new(File.dirname(__FILE__))
|
7
|
+
ADAPTERS = %w(mysql postgresql sqlite sqlite3 oracle)
|
6
8
|
|
7
|
-
task :default => [
|
9
|
+
task :default => ["test:mysql"]
|
8
10
|
|
9
11
|
task :boot do
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require File.expand_path( File.join( DIR, 'db/migrate/version' ) )
|
12
|
+
require DIR.join("lib", "ar-extensions").expand_path
|
13
|
+
require DIR.join("db", "migrate", "version").expand_path
|
13
14
|
end
|
14
15
|
|
15
|
-
ADAPTERS
|
16
|
-
|
17
|
-
namespace :
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
desc "builds test database for #{adapter}"
|
22
|
-
task "prepare_#{adapter}" do |t|
|
23
|
-
file2run = File.join( DIR, 'tests/prepare.rb' )
|
24
|
-
system( "ruby #{file2run} #{adapter}" )
|
16
|
+
ADAPTERS.each do |adapter|
|
17
|
+
namespace :db do
|
18
|
+
namespace :test do
|
19
|
+
desc "Builds test database for #{adapter}"
|
20
|
+
task "prepare_#{adapter}" do
|
21
|
+
ruby "#{DIR.join('tests', 'prepare.rb')} #{adapter}"
|
25
22
|
end
|
26
23
|
end
|
27
24
|
end
|
28
25
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
task adapter do |t|
|
36
|
-
ENV['ARE_DB'] = adapter
|
37
|
-
|
38
|
-
task = Rake::Task[ "db:test:prepare_#{adapter}" ]
|
39
|
-
begin
|
40
|
-
task = false if SchemaInfo::VERSION == SchemaInfo.find( :first ).version
|
41
|
-
rescue Exception => ex
|
42
|
-
end
|
43
|
-
task.invoke if task
|
44
|
-
|
45
|
-
system "ruby #{File.join( DIR, 'tests/run.rb ' )} #{adapter}"
|
26
|
+
namespace :test do
|
27
|
+
desc "Test base extensions for #{adapter}"
|
28
|
+
task(adapter) do
|
29
|
+
ENV["ARE_DB"] = adapter
|
30
|
+
Rake::Task["db:test:prepare_#{adapter}"].invoke
|
31
|
+
ruby "#{DIR.join('tests', 'run.rb')} #{adapter}"
|
46
32
|
end
|
47
33
|
end
|
48
34
|
|
49
35
|
namespace :activerecord do
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
STDERR.puts "ERROR: Pass in the path to ActiveRecord. Eg: /home/zdennis/rails_trunk/activerecord"
|
57
|
-
exit
|
58
|
-
end
|
59
|
-
|
60
|
-
old_dir, old_env = Dir.pwd, ENV['RUBYOPT']
|
61
|
-
Dir.chdir( activerecord_dir )
|
62
|
-
ENV['RUBYOPT'] = "-r#{File.join(old_dir,'init.rb')}"
|
63
|
-
|
64
|
-
load "Rakefile"
|
65
|
-
Rake::Task[ "test_#{adapter}" ].invoke
|
66
|
-
Dir.chdir( old_dir )
|
67
|
-
ENV['RUBYOPT'] = old_env
|
68
|
-
end
|
69
|
-
|
70
|
-
desc "runs ActiveRecord unit tests for #{adapter} with ActiveRecord::Extensions with ALL available #{adapter} functionality"
|
71
|
-
task "#{adapter}_all" do |t|
|
72
|
-
ENV['LOAD_ADAPTER_EXTENSIONS'] = adapter.to_s
|
73
|
-
Rake::Task["test:activerecord:#{adapter}"].invoke
|
36
|
+
desc "Runs ActiveRecord unit tests for #{adapter} with ActiveRecord::Extensions"
|
37
|
+
task(adapter) do
|
38
|
+
activerecord_dir = ARGV[1]
|
39
|
+
if activerecord_dir.nil? || !File.directory?(activerecord_dir)
|
40
|
+
puts "ERROR: Pass in the path to ActiveRecord. Eg: /home/zdennis/rails_trunk/activerecord"
|
41
|
+
exit
|
74
42
|
end
|
75
|
-
|
76
|
-
|
43
|
+
|
44
|
+
old_dir, old_env = Dir.pwd, ENV["RUBYOPT"]
|
45
|
+
Dir.chdir(activerecord_dir)
|
46
|
+
ENV["RUBYOPT"] = "-r#{File.join(old_dir,'init.rb')}"
|
47
|
+
|
48
|
+
load "Rakefile"
|
49
|
+
|
50
|
+
Rake::Task["test_#{adapter}"].invoke
|
51
|
+
Dir.chdir(old_dir)
|
52
|
+
ENV["RUBYOPT"] = old_env
|
53
|
+
end
|
54
|
+
|
55
|
+
desc "Runs ActiveRecord unit tests for #{adapter} with ActiveRecord::Extensions with ALL available #{adapter} functionality"
|
56
|
+
task "#{adapter}_all" do
|
57
|
+
ENV["LOAD_ADAPTER_EXTENSIONS"] = adapter
|
58
|
+
Rake::Task["test:activerecord:#{adapter}"].invoke
|
59
|
+
end
|
77
60
|
end
|
78
|
-
|
79
|
-
end
|
61
|
+
end
|
data/db/migrate/mysql_schema.rb
CHANGED
data/db/migrate/version.rb
CHANGED
@@ -206,7 +206,7 @@ module ActiveRecord::Extensions
|
|
206
206
|
class Comparison
|
207
207
|
|
208
208
|
SUFFIX_MAP = { 'eq'=>'=', 'lt'=>'<', 'lte'=>'<=', 'gt'=>'>', 'gte'=>'>=', 'ne'=>'!=', 'not'=>'!=' }
|
209
|
-
ACCEPTABLE_COMPARISONS = [ String, Numeric, Time, DateTime ]
|
209
|
+
ACCEPTABLE_COMPARISONS = [ String, Numeric, Time, DateTime, Date ]
|
210
210
|
|
211
211
|
def self.process( key, val, caller )
|
212
212
|
process_without_suffix( key, val, caller ) || process_with_suffix( key, val, caller )
|
@@ -1,14 +1,10 @@
|
|
1
|
-
|
2
1
|
module ActiveRecord::Extensions::TemporaryTableSupport # :nodoc:
|
3
2
|
def supports_temporary_tables? #:nodoc:
|
4
3
|
true
|
5
4
|
end
|
6
5
|
end
|
7
6
|
|
8
|
-
|
9
7
|
class ActiveRecord::Base
|
10
|
-
@@temporary_table_hsh ||= {}
|
11
|
-
|
12
8
|
# Returns true if the underlying database connection supports temporary tables
|
13
9
|
def self.supports_temporary_tables?
|
14
10
|
connection.supports_temporary_tables?
|
@@ -26,99 +22,110 @@ class ActiveRecord::Base
|
|
26
22
|
# * options - the options hash used to define the temporary table.
|
27
23
|
#
|
28
24
|
# ==== Options
|
29
|
-
#
|
30
|
-
# then a name of "temp_" + the current table_name of the current model
|
25
|
+
# <tt>:table_name</tt>::the desired name of the temporary table. If not supplied
|
26
|
+
# then a name of "temp_" + the current table_name of the current model
|
31
27
|
# will be used.
|
32
|
-
#
|
33
|
-
# structure off from. If this is not supplied then the table_name of the
|
28
|
+
# <tt>:like</tt>:: the table model you want to base the temporary tables
|
29
|
+
# structure off from. If this is not supplied then the table_name of the
|
34
30
|
# current model will be used.
|
35
|
-
#
|
36
|
-
# table. This must be compliant with Ruby's naming conventions for
|
37
|
-
# constants. If this is not supplied a rails-generated table name will
|
38
|
-
# be created which is based off from the table_name of the temporary table.
|
31
|
+
# <tt>:model_name</tt>:: the name of the model you want to use for the temporary
|
32
|
+
# table. This must be compliant with Ruby's naming conventions for
|
33
|
+
# constants. If this is not supplied a rails-generated table name will
|
34
|
+
# be created which is based off from the table_name of the temporary table.
|
39
35
|
# IE: Account.create_temporary_table creates the TempAccount model class
|
40
36
|
#
|
41
37
|
# ==== Example 1, using defaults
|
42
|
-
# class Project < ActiveRecord::Base ; end
|
43
38
|
#
|
44
|
-
# Project
|
39
|
+
# class Project < ActiveRecord::Base
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# > t = Project.create_temporary_table
|
43
|
+
# > t.class
|
44
|
+
# => "TempProject"
|
45
|
+
# > t.superclass
|
46
|
+
# => Project
|
45
47
|
#
|
46
48
|
# This creates a temporary table named 'temp_projects' and creates a constant
|
47
|
-
# name TempProject. The table structure is copied from the
|
49
|
+
# name TempProject. The table structure is copied from the 'projects' table.
|
50
|
+
# TempProject is a subclass of Project as you would expect.
|
48
51
|
#
|
49
|
-
# ==== Example 2, using
|
50
|
-
#
|
52
|
+
# ==== Example 2, using <tt>:table_name</tt> and <tt>:model options</tt>
|
53
|
+
#
|
54
|
+
# Project.create_temporary_table :table_name => 'my_projects', :model => 'MyProject'
|
51
55
|
#
|
52
56
|
# This creates a temporary table named 'my_projects' and creates a constant named
|
53
|
-
# MyProject. The table structure is copied from the
|
57
|
+
# MyProject. The table structure is copied from the 'projects' table.
|
58
|
+
#
|
59
|
+
# ==== Example 3, using <tt>:like</tt>
|
54
60
|
#
|
55
|
-
#
|
56
|
-
# ActiveRecord::Base.create_temporary_table :like=>Project
|
61
|
+
# ActiveRecord::Base.create_temporary_table :like => Project
|
57
62
|
#
|
58
63
|
# This is the same as calling Project.create_temporary_table.
|
59
64
|
#
|
60
65
|
# ==== Example 4, using block form
|
66
|
+
#
|
61
67
|
# Project.create_temporary_table do |t|
|
62
68
|
# # ...
|
63
69
|
# end
|
64
70
|
#
|
65
71
|
# Using the block form will automatically drop the temporary table
|
66
|
-
# when the block exits.
|
67
|
-
# table class. In the above example
|
72
|
+
# when the block exits. +t+ which is passed into the block is the temporary
|
73
|
+
# table class. In the above example +t+ equals TempProject. The block form
|
68
74
|
# can be used with all of the available options.
|
69
75
|
#
|
70
76
|
# === See
|
71
|
-
#
|
77
|
+
#
|
78
|
+
# * +drop+
|
79
|
+
#
|
72
80
|
######################################################################
|
73
|
-
def self.create_temporary_table(
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
model_name = options[:model_name] || ActiveSupport::Inflector.classify( table_name )
|
79
|
-
raise Exception.new( "Model #{model_name} already exists! \n" ) if Object.const_defined? model_name
|
80
|
-
|
81
|
-
like_table_name = options[:like].table_name || self.table_name
|
82
|
-
sql = "CREATE #{options[:temporary] ? 'TEMPORARY' : ''} TABLE #{table_name} LIKE #{like_table_name}"
|
83
|
-
connection.execute( sql )
|
84
|
-
|
85
|
-
eval "class ::#{model_name} < #{ActiveRecord::TemporaryTable.name}
|
86
|
-
set_table_name :#{table_name}
|
87
|
-
end"
|
81
|
+
def self.create_temporary_table(opts={})
|
82
|
+
opts[:temporary] ||= !opts[:permanent]
|
83
|
+
opts[:like] ||= self
|
84
|
+
opts[:table_name] ||= "temp_#{self.table_name}"
|
85
|
+
opts[:model_name] ||= ActiveSupport::Inflector.classify(opts[:table_name])
|
88
86
|
|
89
|
-
|
90
|
-
|
91
|
-
yield model
|
92
|
-
model.drop
|
93
|
-
nil
|
94
|
-
else
|
95
|
-
model
|
87
|
+
if Object.const_defined?(opts[:model_name])
|
88
|
+
raise Exception, "Model #{opts[:model_name]} already exists!"
|
96
89
|
end
|
97
|
-
end
|
98
90
|
|
99
|
-
|
91
|
+
like_table_name = opts[:like].table_name || self.table_name
|
100
92
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
93
|
+
connection.execute <<-SQL
|
94
|
+
CREATE #{opts[:temporary] ? 'TEMPORARY' : ''} TABLE #{opts[:table_name]}
|
95
|
+
LIKE #{like_table_name}
|
96
|
+
SQL
|
97
|
+
|
98
|
+
# Sample evaluation:
|
99
|
+
#
|
100
|
+
# class ::TempFood < Food
|
101
|
+
# set_table_name :temp_food
|
102
|
+
#
|
103
|
+
# def self.drop
|
104
|
+
# connection.execute "DROP TABLE temp_foo"
|
105
|
+
# Object.send(:remove_const, self.name.to_sym)
|
106
|
+
# end
|
107
|
+
# end
|
108
|
+
class_eval(<<-RUBY, __FILE__, __LINE__)
|
109
|
+
class ::#{opts[:model_name]} < #{self.name}
|
110
|
+
set_table_name :#{opts[:table_name]}
|
111
|
+
|
112
|
+
def self.drop
|
113
|
+
connection.execute "DROP TABLE #{opts[:table_name]};"
|
114
|
+
Object.send(:remove_const, self.name.to_sym)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
RUBY
|
118
|
+
|
119
|
+
model = Object.const_get(opts[:model_name])
|
120
|
+
|
121
|
+
if block_given?
|
122
|
+
begin
|
123
|
+
yield(model)
|
124
|
+
ensure
|
125
|
+
model.drop
|
126
|
+
end
|
118
127
|
else
|
119
|
-
|
128
|
+
return model
|
120
129
|
end
|
121
130
|
end
|
122
|
-
|
123
131
|
end
|
124
|
-
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ar-extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 61
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 9
|
9
|
+
- 3
|
10
|
+
version: 0.9.3
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Zach Dennis
|
@@ -11,19 +17,24 @@ autorequire:
|
|
11
17
|
bindir: bin
|
12
18
|
cert_chain: []
|
13
19
|
|
14
|
-
date:
|
20
|
+
date: 2010-10-28 00:00:00 -04:00
|
15
21
|
default_executable:
|
16
22
|
dependencies:
|
17
23
|
- !ruby/object:Gem::Dependency
|
18
24
|
name: activerecord
|
19
|
-
|
20
|
-
|
21
|
-
|
25
|
+
prerelease: false
|
26
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
27
|
+
none: false
|
22
28
|
requirements:
|
23
|
-
- -
|
29
|
+
- - ~>
|
24
30
|
- !ruby/object:Gem::Version
|
25
|
-
|
26
|
-
|
31
|
+
hash: 1
|
32
|
+
segments:
|
33
|
+
- 2
|
34
|
+
- 1
|
35
|
+
version: "2.1"
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id001
|
27
38
|
description: Extends ActiveRecord functionality by adding better finder/query support, as well as supporting mass data import, foreign key, CSV and temporary tables
|
28
39
|
email: zach.dennis@gmail.com
|
29
40
|
executables: []
|
@@ -34,7 +45,6 @@ extra_rdoc_files:
|
|
34
45
|
- README
|
35
46
|
files:
|
36
47
|
- init.rb
|
37
|
-
- db/migrate
|
38
48
|
- db/migrate/generic_schema.rb
|
39
49
|
- db/migrate/mysql_schema.rb
|
40
50
|
- db/migrate/oracle_schema.rb
|
@@ -80,6 +90,8 @@ files:
|
|
80
90
|
- lib/ar-extensions.rb
|
81
91
|
has_rdoc: true
|
82
92
|
homepage: http://www.continuousthinking.com/tags/arext
|
93
|
+
licenses: []
|
94
|
+
|
83
95
|
post_install_message:
|
84
96
|
rdoc_options:
|
85
97
|
- --main
|
@@ -87,23 +99,29 @@ rdoc_options:
|
|
87
99
|
require_paths:
|
88
100
|
- lib
|
89
101
|
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
+
none: false
|
90
103
|
requirements:
|
91
104
|
- - ">="
|
92
105
|
- !ruby/object:Gem::Version
|
106
|
+
hash: 3
|
107
|
+
segments:
|
108
|
+
- 0
|
93
109
|
version: "0"
|
94
|
-
version:
|
95
110
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
none: false
|
96
112
|
requirements:
|
97
113
|
- - ">="
|
98
114
|
- !ruby/object:Gem::Version
|
115
|
+
hash: 3
|
116
|
+
segments:
|
117
|
+
- 0
|
99
118
|
version: "0"
|
100
|
-
version:
|
101
119
|
requirements: []
|
102
120
|
|
103
121
|
rubyforge_project: arext
|
104
|
-
rubygems_version: 1.3.
|
122
|
+
rubygems_version: 1.3.7
|
105
123
|
signing_key:
|
106
|
-
specification_version:
|
124
|
+
specification_version: 3
|
107
125
|
summary: Extends ActiveRecord functionality.
|
108
126
|
test_files: []
|
109
127
|
|