ghazel-ar-extensions 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/ChangeLog +145 -0
- data/README +169 -0
- data/Rakefile +61 -0
- data/config/database.yml +7 -0
- data/config/database.yml.template +7 -0
- data/config/mysql.schema +72 -0
- data/config/postgresql.schema +39 -0
- data/db/migrate/generic_schema.rb +97 -0
- data/db/migrate/mysql_schema.rb +32 -0
- data/db/migrate/oracle_schema.rb +5 -0
- data/db/migrate/version.rb +4 -0
- data/init.rb +31 -0
- data/lib/ar-extensions/adapters/abstract_adapter.rb +146 -0
- data/lib/ar-extensions/adapters/mysql.rb +10 -0
- data/lib/ar-extensions/adapters/oracle.rb +14 -0
- data/lib/ar-extensions/adapters/postgresql.rb +9 -0
- data/lib/ar-extensions/adapters/sqlite.rb +7 -0
- data/lib/ar-extensions/create_and_update/mysql.rb +7 -0
- data/lib/ar-extensions/create_and_update.rb +509 -0
- data/lib/ar-extensions/csv.rb +309 -0
- data/lib/ar-extensions/delete/mysql.rb +3 -0
- data/lib/ar-extensions/delete.rb +143 -0
- data/lib/ar-extensions/extensions.rb +513 -0
- data/lib/ar-extensions/finder_options/mysql.rb +6 -0
- data/lib/ar-extensions/finder_options.rb +275 -0
- data/lib/ar-extensions/finders.rb +94 -0
- data/lib/ar-extensions/foreign_keys.rb +70 -0
- data/lib/ar-extensions/fulltext/mysql.rb +44 -0
- data/lib/ar-extensions/fulltext.rb +62 -0
- data/lib/ar-extensions/import/mysql.rb +50 -0
- data/lib/ar-extensions/import/postgresql.rb +0 -0
- data/lib/ar-extensions/import/sqlite.rb +22 -0
- data/lib/ar-extensions/import.rb +348 -0
- data/lib/ar-extensions/insert_select/mysql.rb +7 -0
- data/lib/ar-extensions/insert_select.rb +178 -0
- data/lib/ar-extensions/synchronize.rb +30 -0
- data/lib/ar-extensions/temporary_table/mysql.rb +3 -0
- data/lib/ar-extensions/temporary_table.rb +131 -0
- data/lib/ar-extensions/union/mysql.rb +6 -0
- data/lib/ar-extensions/union.rb +204 -0
- data/lib/ar-extensions/util/sql_generation.rb +27 -0
- data/lib/ar-extensions/util/support_methods.rb +32 -0
- data/lib/ar-extensions/version.rb +9 -0
- data/lib/ar-extensions.rb +5 -0
- metadata +110 -0
@@ -0,0 +1,131 @@
|
|
1
|
+
module ActiveRecord::Extensions::TemporaryTableSupport # :nodoc:
|
2
|
+
def supports_temporary_tables? #:nodoc:
|
3
|
+
true
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
class ActiveRecord::Base
|
8
|
+
# Returns true if the underlying database connection supports temporary tables
|
9
|
+
def self.supports_temporary_tables?
|
10
|
+
connection.supports_temporary_tables?
|
11
|
+
rescue NoMethodError
|
12
|
+
false
|
13
|
+
end
|
14
|
+
|
15
|
+
######################################################################
|
16
|
+
# Creates a temporary table given the passed in options hash. The
|
17
|
+
# temporary table is created based off from another table the
|
18
|
+
# current model class. This method returns the constant for the new
|
19
|
+
# new model. This can also be used with block form (see below).
|
20
|
+
#
|
21
|
+
# == Parameters
|
22
|
+
# * options - the options hash used to define the temporary table.
|
23
|
+
#
|
24
|
+
# ==== Options
|
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
|
27
|
+
# will be used.
|
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
|
30
|
+
# current model will be used.
|
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.
|
35
|
+
# IE: Account.create_temporary_table creates the TempAccount model class
|
36
|
+
#
|
37
|
+
# ==== Example 1, using defaults
|
38
|
+
#
|
39
|
+
# class Project < ActiveRecord::Base
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# > t = Project.create_temporary_table
|
43
|
+
# > t.class
|
44
|
+
# => "TempProject"
|
45
|
+
# > t.superclass
|
46
|
+
# => Project
|
47
|
+
#
|
48
|
+
# This creates a temporary table named 'temp_projects' and creates a constant
|
49
|
+
# name TempProject. The table structure is copied from the 'projects' table.
|
50
|
+
# TempProject is a subclass of Project as you would expect.
|
51
|
+
#
|
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'
|
55
|
+
#
|
56
|
+
# This creates a temporary table named 'my_projects' and creates a constant named
|
57
|
+
# MyProject. The table structure is copied from the 'projects' table.
|
58
|
+
#
|
59
|
+
# ==== Example 3, using <tt>:like</tt>
|
60
|
+
#
|
61
|
+
# ActiveRecord::Base.create_temporary_table :like => Project
|
62
|
+
#
|
63
|
+
# This is the same as calling Project.create_temporary_table.
|
64
|
+
#
|
65
|
+
# ==== Example 4, using block form
|
66
|
+
#
|
67
|
+
# Project.create_temporary_table do |t|
|
68
|
+
# # ...
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# Using the block form will automatically drop the temporary table
|
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
|
74
|
+
# can be used with all of the available options.
|
75
|
+
#
|
76
|
+
# === See
|
77
|
+
#
|
78
|
+
# * +drop+
|
79
|
+
#
|
80
|
+
######################################################################
|
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])
|
86
|
+
|
87
|
+
if Object.const_defined?(opts[:model_name])
|
88
|
+
raise Exception, "Model #{opts[:model_name]} already exists!"
|
89
|
+
end
|
90
|
+
|
91
|
+
like_table_name = opts[:like].table_name || self.table_name
|
92
|
+
|
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
|
127
|
+
else
|
128
|
+
return model
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,204 @@
|
|
1
|
+
module ActiveRecord::Extensions::Union#:nodoc:
|
2
|
+
module UnionSupport #:nodoc:
|
3
|
+
def supports_union? #:nodoc:
|
4
|
+
true
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class ActiveRecord::Base
|
10
|
+
supports_extension :union
|
11
|
+
|
12
|
+
extend ActiveRecord::Extensions::SqlGeneration
|
13
|
+
class << self
|
14
|
+
# Find a union of two or more queries
|
15
|
+
# === Args
|
16
|
+
# Each argument is a hash map of options sent to <tt>:find :all</tt>
|
17
|
+
# including <tt>:conditions</tt>, <tt>:join</tt>, <tt>:group</tt>,
|
18
|
+
# <tt>:having</tt>, and <tt>:limit</tt>
|
19
|
+
#
|
20
|
+
# In addition the following options are accepted
|
21
|
+
# * <tt>:pre_sql</tt> inserts SQL before the SELECT statement of this protion of the +union+
|
22
|
+
# * <tt>:post_sql</tt> appends additional SQL to the end of the statement
|
23
|
+
# * <tt>:override_select</tt> is used to override the <tt>SELECT</tt> clause of eager loaded associations
|
24
|
+
#
|
25
|
+
# == Examples
|
26
|
+
# Find the union of a San Fran zipcode with a Seattle zipcode
|
27
|
+
# union_args1 = {:conditions => ['zip_id = ?', 94010], :select => :phone_number_id}
|
28
|
+
# union_args2 = {:conditions => ['zip_id = ?', 98102], :select => :phone_number_id}
|
29
|
+
# Contact.find_union(union_args1, union_args2, ...)
|
30
|
+
#
|
31
|
+
# SQL> (SELECT phone_number_id FROM contacts WHERE zip_id = 94010) UNION
|
32
|
+
# (SELECT phone_number_id FROM contacts WHERE zip_id = 98102) UNION ...
|
33
|
+
#
|
34
|
+
# == Global Options
|
35
|
+
# To specify global options that apply to the entire union, specify a hash as the
|
36
|
+
# first parameter with a key <tt>:union_options</tt>. Valid options include
|
37
|
+
# <tt>:group</tt>, <tt>:having</tt>, <tt>:order</tt>, and <tt>:limit</tt>
|
38
|
+
#
|
39
|
+
#
|
40
|
+
# Example:
|
41
|
+
# Contact.find_union(:union_options => {:limit => 10, :order => 'created_on'},
|
42
|
+
# union_args1, union_args2, ...)
|
43
|
+
#
|
44
|
+
# SQL> ((select phone_number_id from contacts ...) UNION (select phone_number_id from contacts ...)) order by created_on limit 10
|
45
|
+
#
|
46
|
+
def find_union(*args)
|
47
|
+
supports_union!
|
48
|
+
find_by_sql(find_union_sql(*args))
|
49
|
+
end
|
50
|
+
|
51
|
+
# Count across a union of two or more queries
|
52
|
+
# === Args
|
53
|
+
# * +column_name+ - The column to count. Defaults to all ('*')
|
54
|
+
# * <tt>*args</tt> - Each additional argument is a hash map of options used by <tt>:find :all</tt>
|
55
|
+
# including <tt>:conditions</tt>, <tt>:join</tt>, <tt>:group</tt>,
|
56
|
+
# <tt>:having</tt>, and <tt>:limit</tt>
|
57
|
+
#
|
58
|
+
# In addition the following options are accepted
|
59
|
+
# * <tt>:pre_sql</tt> inserts SQL before the SELECT statement of this protion of the +union+
|
60
|
+
# * <tt>:post_sql</tt> appends additional SQL to the end of the statement
|
61
|
+
# * <tt>:override_select</tt> is used to override the <tt>SELECT</tt> clause of eager loaded associations
|
62
|
+
#
|
63
|
+
# Note that distinct is implied so a record that matches more than one
|
64
|
+
# portion of the union is counted only once.
|
65
|
+
#
|
66
|
+
# == Global Options
|
67
|
+
# To specify global options that apply to the entire union, specify a hash as the
|
68
|
+
# first parameter with a key <tt>:union_options</tt>. Valid options include
|
69
|
+
# <tt>:group</tt>, <tt>:having</tt>, <tt>:order</tt>, and <tt>:limit</tt>
|
70
|
+
#
|
71
|
+
# == Examples
|
72
|
+
# Count the number of people who live in Seattle and San Francisco
|
73
|
+
# Contact.count_union(:phone_number_id,
|
74
|
+
# {:conditions => ['zip_id = ?, 94010]'},
|
75
|
+
# {:conditions => ['zip_id = ?', 98102]})
|
76
|
+
# SQL> select count(*) from ((select phone_number_id from contacts ...) UNION (select phone_number_id from contacts ...)) as counter_tbl;
|
77
|
+
def count_union(column_name, *args)
|
78
|
+
supports_union!
|
79
|
+
count_val = calculate_union(:count, column_name, *args)
|
80
|
+
(args.length == 1 && args.first[:limit] && args.first[:limit].to_i < count_val) ? args.first[:limit].to_i : count_val
|
81
|
+
end
|
82
|
+
|
83
|
+
protected
|
84
|
+
|
85
|
+
#do a union of specified calculation. Only for simple calculations
|
86
|
+
def calculate_union(operation, column_name, *args)#:nodoc:
|
87
|
+
union_options = remove_union_options(args)
|
88
|
+
|
89
|
+
|
90
|
+
if args.length == 1
|
91
|
+
column_name = '*' if column_name == :all
|
92
|
+
calculate(operation, column_name, args.first.update(union_options))
|
93
|
+
|
94
|
+
# For more than one map of options, count off the subquery of all the column_name fields unioned together
|
95
|
+
# For example, if column_name is phone_number_id the generated query is
|
96
|
+
# Contact.calculate_union(:count, :phone_number_id, args)
|
97
|
+
# SQL> select count(*) from
|
98
|
+
# ((select phone_number_id from contacts ...)
|
99
|
+
# UNION
|
100
|
+
# (select phone_number_id from contacts ...)) as counter_tbl
|
101
|
+
else
|
102
|
+
column_name = primary_key if column_name == :all
|
103
|
+
column = column_for column_name
|
104
|
+
column_name = "#{table_name}.#{column_name}" unless column_name.to_s.include?('.')
|
105
|
+
|
106
|
+
group_by = union_options.delete(:group)
|
107
|
+
having = union_options.delete(:having)
|
108
|
+
query_alias = union_options.delete(:query_alias)||"#{operation}_giraffe"
|
109
|
+
|
110
|
+
|
111
|
+
#aggregate_alias should be table_name_id
|
112
|
+
aggregate_alias = column_alias_for('', column_name)
|
113
|
+
#main alias is operation_table_name_id
|
114
|
+
main_aggregate_alias = column_alias_for(operation, column_name)
|
115
|
+
|
116
|
+
sql = "SELECT "
|
117
|
+
sql << (group_by ? "#{group_by}, #{operation}(#{aggregate_alias})" : "#{operation}(*)")
|
118
|
+
sql << " AS #{main_aggregate_alias}"
|
119
|
+
sql << " FROM ("
|
120
|
+
|
121
|
+
#by nature of the union the results will always be distinct, so remove distinct column here
|
122
|
+
sql << args.inject([]){|l, a|
|
123
|
+
calc = "(#{construct_calculation_sql_with_extension('', column_name, a)})"
|
124
|
+
#for group by we need to select the group by column also
|
125
|
+
calc.gsub!(" AS #{aggregate_alias}", " AS #{aggregate_alias}, #{group_by} ") if group_by
|
126
|
+
l << calc
|
127
|
+
}.join(" UNION ")
|
128
|
+
|
129
|
+
add_union_options!(sql, union_options)
|
130
|
+
|
131
|
+
sql << ") as #{query_alias}"
|
132
|
+
|
133
|
+
if group_by
|
134
|
+
#add groupings
|
135
|
+
sql << " GROUP BY #{group_by}"
|
136
|
+
sql << " HAVING #{having}" if having
|
137
|
+
|
138
|
+
calculated_data = connection.select_all(sql)
|
139
|
+
|
140
|
+
calculated_data.inject(ActiveSupport::OrderedHash.new) do |all, row|
|
141
|
+
key = type_cast_calculated_value(row[group_by], column_for(group_by.to_s))
|
142
|
+
value = row[main_aggregate_alias]
|
143
|
+
all << [key, type_cast_calculated_value(value, column_for(column), operation)]
|
144
|
+
end
|
145
|
+
|
146
|
+
else
|
147
|
+
count_by_sql(sql)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
#Add Global Union options
|
154
|
+
def add_union_options!(sql, options)#:nodoc:
|
155
|
+
sql << " GROUP BY #{options[:group]} " if options[:group]
|
156
|
+
|
157
|
+
if options[:order] || options[:limit]
|
158
|
+
scope = scope(:find)
|
159
|
+
add_order!(sql, options[:order], scope)
|
160
|
+
add_limit!(sql, options, scope)
|
161
|
+
end
|
162
|
+
sql
|
163
|
+
end
|
164
|
+
|
165
|
+
#Remove the global union options
|
166
|
+
def remove_union_options(args)#:nodoc:
|
167
|
+
args.first.is_a?(Hash) && args.first.has_key?(:union_options) ? (args.shift)[:union_options] : {}
|
168
|
+
end
|
169
|
+
|
170
|
+
def construct_calculation_sql_with_extension(operation, column_name, options)
|
171
|
+
construct_ar_extension_sql(options.merge(:command => '', :keywords => nil, :distinct => nil)) {|sql, o|
|
172
|
+
calc_sql = construct_calculation_sql(operation, column_name, options)
|
173
|
+
|
174
|
+
#this is really gross but prevents us from rewriting construct_calculation_sql
|
175
|
+
calc_sql.gsub!(/^SELECT\s/, "SELECT #{options[:keywords]} ") if options[:keywords]
|
176
|
+
|
177
|
+
sql << calc_sql
|
178
|
+
}
|
179
|
+
end
|
180
|
+
|
181
|
+
# Return the sql for union of the query options specified on the command line
|
182
|
+
# If the first parameter is a map containing :union_options, use these
|
183
|
+
def find_union_sql(*args)#:nodoc:
|
184
|
+
options = remove_union_options(args)
|
185
|
+
|
186
|
+
if args.length == 1
|
187
|
+
return finder_sql_to_string(args.first.update(options))
|
188
|
+
end
|
189
|
+
|
190
|
+
sql = args.inject([]) do |sql_list, union_args|
|
191
|
+
part = union_args.merge(:force_eager_load => true,
|
192
|
+
:override_select => union_args[:select]||"#{quoted_table_name}.*",
|
193
|
+
:select => nil)
|
194
|
+
sql_list << "(#{finder_sql_to_string(part)})"
|
195
|
+
sql_list
|
196
|
+
end.join(" UNION ")
|
197
|
+
|
198
|
+
|
199
|
+
add_union_options!(sql, options)
|
200
|
+
sql
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
#Extend this module on ActiveRecord to access global functions
|
3
|
+
module ActiveRecord
|
4
|
+
module Extensions
|
5
|
+
module SqlGeneration#:nodoc:
|
6
|
+
|
7
|
+
protected
|
8
|
+
|
9
|
+
def post_sql_statements(options)#:nodoc:
|
10
|
+
connection.post_sql_statements(quoted_table_name, options).join(' ')
|
11
|
+
end
|
12
|
+
|
13
|
+
def pre_sql_statements(options)#:nodoc:
|
14
|
+
connection.pre_sql_statements({:command => 'SELECT'}.merge(options)).join(' ').strip + " "
|
15
|
+
end
|
16
|
+
|
17
|
+
def construct_ar_extension_sql(options={}, valid_options = [], &block)#:nodoc:
|
18
|
+
options.assert_valid_keys(valid_options)if valid_options.any?
|
19
|
+
|
20
|
+
sql = pre_sql_statements(options)
|
21
|
+
yield sql, options
|
22
|
+
sql << post_sql_statements(options)
|
23
|
+
sql
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#Extend this module on ActiveRecord to access global functions
|
2
|
+
class ExtensionNotSupported < Exception; end;
|
3
|
+
|
4
|
+
module ActiveRecord
|
5
|
+
module Extensions
|
6
|
+
module SupportMethods#:nodoc:
|
7
|
+
def supports_extension(name)
|
8
|
+
class_eval(<<-EOS, __FILE__, __LINE__)
|
9
|
+
def self.supports_#{name}?#:nodoc:
|
10
|
+
connection.supports_#{name}?
|
11
|
+
rescue NoMethodError
|
12
|
+
false
|
13
|
+
end
|
14
|
+
|
15
|
+
def supports_#{name}?#:nodoc:
|
16
|
+
self.class.supports_#{name}?
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.supports_#{name}!#:nodoc:
|
20
|
+
supports_#{name}? or raise ExtensionNotSupported.new("#{name} extension is not supported. Please require the adapter file.")
|
21
|
+
end
|
22
|
+
|
23
|
+
def supports_#{name}!#:nodoc:
|
24
|
+
self.class.supports_#{name}!
|
25
|
+
end
|
26
|
+
EOS
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
ActiveRecord::Base.send :extend, ActiveRecord::Extensions::SupportMethods
|
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ghazel-ar-extensions
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Zach Dennis
|
8
|
+
- Mark Van Holstyn
|
9
|
+
- Blythe Dunham
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
|
14
|
+
date: 2010-10-28 00:00:00 -07:00
|
15
|
+
default_executable:
|
16
|
+
dependencies:
|
17
|
+
- !ruby/object:Gem::Dependency
|
18
|
+
name: activerecord
|
19
|
+
type: :runtime
|
20
|
+
version_requirement:
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - ~>
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: "2.1"
|
26
|
+
version:
|
27
|
+
description: Extends ActiveRecord functionality by adding better finder/query support, as well as supporting mass data import, foreign key, CSV and temporary tables
|
28
|
+
email: zach.dennis@gmail.com
|
29
|
+
executables: []
|
30
|
+
|
31
|
+
extensions: []
|
32
|
+
|
33
|
+
extra_rdoc_files:
|
34
|
+
- README
|
35
|
+
files:
|
36
|
+
- init.rb
|
37
|
+
- db/migrate/generic_schema.rb
|
38
|
+
- db/migrate/mysql_schema.rb
|
39
|
+
- db/migrate/oracle_schema.rb
|
40
|
+
- db/migrate/version.rb
|
41
|
+
- Rakefile
|
42
|
+
- ChangeLog
|
43
|
+
- README
|
44
|
+
- config/database.yml
|
45
|
+
- config/database.yml.template
|
46
|
+
- config/mysql.schema
|
47
|
+
- config/postgresql.schema
|
48
|
+
- lib/ar-extensions/adapters/abstract_adapter.rb
|
49
|
+
- lib/ar-extensions/adapters/mysql.rb
|
50
|
+
- lib/ar-extensions/adapters/oracle.rb
|
51
|
+
- lib/ar-extensions/adapters/postgresql.rb
|
52
|
+
- lib/ar-extensions/adapters/sqlite.rb
|
53
|
+
- lib/ar-extensions/create_and_update/mysql.rb
|
54
|
+
- lib/ar-extensions/create_and_update.rb
|
55
|
+
- lib/ar-extensions/csv.rb
|
56
|
+
- lib/ar-extensions/delete/mysql.rb
|
57
|
+
- lib/ar-extensions/delete.rb
|
58
|
+
- lib/ar-extensions/extensions.rb
|
59
|
+
- lib/ar-extensions/finders.rb
|
60
|
+
- lib/ar-extensions/finder_options/mysql.rb
|
61
|
+
- lib/ar-extensions/finder_options.rb
|
62
|
+
- lib/ar-extensions/foreign_keys.rb
|
63
|
+
- lib/ar-extensions/fulltext/mysql.rb
|
64
|
+
- lib/ar-extensions/fulltext.rb
|
65
|
+
- lib/ar-extensions/import/mysql.rb
|
66
|
+
- lib/ar-extensions/import/postgresql.rb
|
67
|
+
- lib/ar-extensions/import/sqlite.rb
|
68
|
+
- lib/ar-extensions/import.rb
|
69
|
+
- lib/ar-extensions/insert_select/mysql.rb
|
70
|
+
- lib/ar-extensions/insert_select.rb
|
71
|
+
- lib/ar-extensions/synchronize.rb
|
72
|
+
- lib/ar-extensions/temporary_table/mysql.rb
|
73
|
+
- lib/ar-extensions/temporary_table.rb
|
74
|
+
- lib/ar-extensions/union/mysql.rb
|
75
|
+
- lib/ar-extensions/union.rb
|
76
|
+
- lib/ar-extensions/util/sql_generation.rb
|
77
|
+
- lib/ar-extensions/util/support_methods.rb
|
78
|
+
- lib/ar-extensions/version.rb
|
79
|
+
- lib/ar-extensions.rb
|
80
|
+
has_rdoc: true
|
81
|
+
homepage: http://www.continuousthinking.com/tags/arext
|
82
|
+
licenses: []
|
83
|
+
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options:
|
86
|
+
- --main
|
87
|
+
- README
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: "0"
|
95
|
+
version:
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: "0"
|
101
|
+
version:
|
102
|
+
requirements: []
|
103
|
+
|
104
|
+
rubyforge_project: arext
|
105
|
+
rubygems_version: 1.3.5
|
106
|
+
signing_key:
|
107
|
+
specification_version: 3
|
108
|
+
summary: Extends ActiveRecord functionality.
|
109
|
+
test_files: []
|
110
|
+
|