ar-extensions 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +8 -0
- data/README +7 -0
- data/db/migrate/generic_schema.rb +1 -0
- data/db/migrate/mysql_schema.rb +1 -0
- data/db/migrate/version.rb +1 -1
- data/init.rb +2 -0
- data/lib/ar-extensions/adapters/abstract_adapter.rb +6 -0
- data/lib/ar-extensions/extensions.rb +24 -18
- data/lib/ar-extensions/finders.rb +3 -3
- data/lib/ar-extensions/import.rb +18 -1
- data/lib/ar-extensions/import/mysql.rb +3 -3
- data/lib/ar-extensions/synchronize.rb +30 -0
- data/lib/ar-extensions/temporary_table.rb +1 -1
- data/lib/ar-extensions/version.rb +1 -1
- metadata +12 -11
data/ChangeLog
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
2007-05-05 zdennis <zdennis@elijah.local>
|
2
|
+
|
3
|
+
* Added ActiveRecord::Base::AbstractAdapter#synchronize method which allows a mass re-synchronization of ActiveRecord instances. This is similar to ActiveRecord::Base#reload except that it works on multiple instances at a time rather then one. This sends one query for all instances rather then 1 per instance reloaded.
|
4
|
+
|
5
|
+
* Fixed bug with URI encoded strings with a workaround in the Comparison extension. ActiveRecord needs to be fixed to not use the String#% method so strings that do contains percentage signs will not fail
|
6
|
+
|
7
|
+
* Applied patch from Grant Goodale to allow the Like extension to support arrays when using the '_contains' suffix
|
8
|
+
|
1
9
|
2007-03-14 zdennis <zdennis@elijah.xrite.com>
|
2
10
|
|
3
11
|
* Fixed a bug by renaming the alias for the ActiveRecord::Base#quote method in finders.rb. See rubyforge bug #8996
|
data/README
CHANGED
@@ -9,6 +9,13 @@ Email: zach.dennis@gmail.com
|
|
9
9
|
- For How-To information see http://www.continuousthinking.com/tags/arext
|
10
10
|
- For project information and feedback please consult http://rubyforge.org/projects/arext/
|
11
11
|
- For release information please see below
|
12
|
+
|
13
|
+
ActiveRecord::Extensions 0.6.0
|
14
|
+
------------------------------
|
15
|
+
May 5th, 2007
|
16
|
+
- Fixed bug with URI escaped strings and the Comparison better finder extension
|
17
|
+
- Added support for arrays with the Like better finder extension when using the '_contains' suffix
|
18
|
+
- Added 'synchronize' support for ActiveRecord::Base instances when using Import functionality
|
12
19
|
|
13
20
|
ActiveRecord::Extensions 0.5.2
|
14
21
|
------------------------------
|
data/db/migrate/mysql_schema.rb
CHANGED
@@ -20,6 +20,7 @@ ActiveRecord::Schema.define do
|
|
20
20
|
t.column :publisher, :string, :null=>false
|
21
21
|
t.column :author_name, :string, :null=>false
|
22
22
|
t.column :created_at, :datetime
|
23
|
+
t.column :topic_id, :integer
|
23
24
|
end
|
24
25
|
execute "ALTER TABLE books ADD FULLTEXT( `title`, `publisher`, `author_name` )"
|
25
26
|
|
data/db/migrate/version.rb
CHANGED
data/init.rb
CHANGED
@@ -24,6 +24,8 @@ require File.expand_path( File.join( dir, 'lib/ar-extensions', 'import', 'postg
|
|
24
24
|
|
25
25
|
require File.expand_path( File.join( dir, 'lib/ar-extensions', 'finders' ) )
|
26
26
|
|
27
|
+
require File.expand_path( File.join( dir, 'lib/ar-extensions', 'synchronize' ) )
|
28
|
+
|
27
29
|
require File.expand_path( File.join( dir, 'lib/ar-extensions', 'temporary_table' ) )
|
28
30
|
require File.expand_path( File.join( dir, 'lib/ar-extensions', 'temporary_table', 'mysql' ) )
|
29
31
|
|
@@ -44,6 +44,12 @@ module ActiveRecord # :nodoc:
|
|
44
44
|
|
45
45
|
number_of_inserts
|
46
46
|
end
|
47
|
+
|
48
|
+
# Synchronizes the passed in ActiveRecord instances with the records in
|
49
|
+
# the database by calling +reload+ on each instance.
|
50
|
+
def after_import_synchronize( instances )
|
51
|
+
instances.each { |e| e.reload }
|
52
|
+
end
|
47
53
|
|
48
54
|
# Returns the sum of the sizes of the passed in objects. This should
|
49
55
|
# probably be moved outside this class, but to where?
|
@@ -216,10 +216,9 @@ module ActiveRecord::Extensions
|
|
216
216
|
if val.nil?
|
217
217
|
str = "#{caller.table_name}.#{caller.connection.quote_column_name( key )} IS NULL"
|
218
218
|
else
|
219
|
-
str = "#{caller.table_name}.#{caller.connection.quote_column_name( key )}
|
220
|
-
"#{caller.connection.quote( val, caller.columns_hash[ key ] )} "
|
219
|
+
str = "#{caller.table_name}.#{caller.connection.quote_column_name( key )}=?"
|
221
220
|
end
|
222
|
-
Result.new( str,
|
221
|
+
Result.new( str, val )
|
223
222
|
end
|
224
223
|
|
225
224
|
def self.process_with_suffix( key, val, caller )
|
@@ -257,22 +256,29 @@ module ActiveRecord::Extensions
|
|
257
256
|
ENDS_WITH_RGX = /(.+)_ends_with$/
|
258
257
|
|
259
258
|
def self.process( key, val, caller )
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
259
|
+
values = [*val]
|
260
|
+
case key.to_s
|
261
|
+
when LIKE_RGX
|
262
|
+
str = values.collect do |v|
|
263
|
+
"#{caller.table_name}.#{caller.connection.quote_column_name( $1 )} LIKE " +
|
264
|
+
"#{caller.connection.quote( '%%' + v + '%%', caller.columns_hash[ $1 ] )} "
|
265
|
+
end
|
266
|
+
when STARTS_WITH_RGX
|
267
|
+
str = values.collect do |v|
|
268
|
+
"#{caller.table_name}.#{caller.connection.quote_column_name( $1 )} LIKE " +
|
269
|
+
"#{caller.connection.quote( v + '%%', caller.columns_hash[ $1 ] )} "
|
270
|
+
end
|
271
|
+
when ENDS_WITH_RGX
|
272
|
+
str = values.collect do |v|
|
273
|
+
"#{caller.table_name}.#{caller.connection.quote_column_name( $1 )} LIKE " +
|
274
|
+
"#{caller.connection.quote( '%%' + v, caller.columns_hash[ $1 ] )} "
|
275
|
+
end
|
276
|
+
else
|
277
|
+
return nil
|
272
278
|
end
|
273
|
-
|
279
|
+
|
280
|
+
return Result.new( str.join(' OR '), nil)
|
274
281
|
end
|
275
|
-
|
276
282
|
end
|
277
283
|
|
278
284
|
|
@@ -461,8 +467,8 @@ end
|
|
461
467
|
|
462
468
|
|
463
469
|
register Comparison, :adapters=>:all
|
464
|
-
register Like, :adapters=>:all
|
465
470
|
register ArrayExt, :adapters=>:all
|
471
|
+
register Like, :adapters=>:all
|
466
472
|
register RangeExt, :adapters=>:all
|
467
473
|
register MySQLRegexp, :adapters=>[ :mysql ]
|
468
474
|
register PostgreSQLRegexp, :adapters=>[ :postgresql ]
|
@@ -21,11 +21,11 @@ class ActiveRecord::Base
|
|
21
21
|
def sanitize_sql( arg ) # :nodoc:
|
22
22
|
return sanitize_sql_orig( arg ) if arg.nil?
|
23
23
|
if arg.respond_to?( :to_sql )
|
24
|
-
arg = sanitize_sql_by_way_of_duck_typing( arg )
|
24
|
+
arg = sanitize_sql_by_way_of_duck_typing( arg )
|
25
25
|
elsif arg.is_a?( Hash )
|
26
|
-
arg = sanitize_sql_from_hash( arg )
|
26
|
+
arg = sanitize_sql_from_hash( arg )
|
27
27
|
elsif arg.size == 2 and arg.first.is_a?( String ) and arg.last.is_a?( Hash )
|
28
|
-
|
28
|
+
arg = sanitize_sql_from_string_and_hash( arg )
|
29
29
|
end
|
30
30
|
sanitize_sql_orig( arg )
|
31
31
|
end
|
data/lib/ar-extensions/import.rb
CHANGED
@@ -80,6 +80,9 @@ class ActiveRecord::Base
|
|
80
80
|
# * +on_duplicate_key_update+ - an Array or Hash, tells import to \
|
81
81
|
# use MySQL's ON DUPLICATE KEY UPDATE ability. See On Duplicate\
|
82
82
|
# Key Update below.
|
83
|
+
# * +synchronize+ - an array of ActiveRecord instances for the model
|
84
|
+
# that you are currently importing data into. This synchronizes
|
85
|
+
# existing model instances in memory with updates from the import.
|
83
86
|
#
|
84
87
|
# == Examples
|
85
88
|
# class BlogPost < ActiveRecord::Base ; end
|
@@ -100,6 +103,14 @@ class ActiveRecord::Base
|
|
100
103
|
# values = [ [ 'zdennis', 'test post' ], [ 'jdoe', 'another test post' ] ]
|
101
104
|
# BlogPost.import( columns, values, :validate => false )
|
102
105
|
#
|
106
|
+
# # Example synchronizing existing instances in memory
|
107
|
+
# post = BlogPost.find_by_author_name( 'zdennis' )
|
108
|
+
# puts post.author_name # => 'zdennis'
|
109
|
+
# columns = [ :author_name, :title ]
|
110
|
+
# values = [ [ 'yoda', 'test post' ] ]
|
111
|
+
# BlogPost.import posts, :synchronize=>[ post ]
|
112
|
+
# puts post.author_name # => 'yoda'
|
113
|
+
#
|
103
114
|
# == On Duplicate Key Update (MySQL only)
|
104
115
|
#
|
105
116
|
# The :on_duplicate_key_update option can be either an Array or a Hash.
|
@@ -154,11 +165,17 @@ class ActiveRecord::Base
|
|
154
165
|
|
155
166
|
# dup the passed in array so we don't modify it unintentionally
|
156
167
|
array_of_attributes = array_of_attributes.dup
|
157
|
-
if is_validating
|
168
|
+
number_of_inserts = if is_validating
|
158
169
|
import_with_validations( column_names, array_of_attributes, options )
|
159
170
|
else
|
160
171
|
import_without_validations_or_callbacks( column_names, array_of_attributes, options )
|
161
172
|
end
|
173
|
+
|
174
|
+
if options[:synchronize]
|
175
|
+
synchronize( options[:synchronize] )
|
176
|
+
end
|
177
|
+
|
178
|
+
number_of_inserts
|
162
179
|
end
|
163
180
|
|
164
181
|
# TODO import_from_table needs to be implemented.
|
@@ -12,8 +12,8 @@ module ActiveRecord::Extensions::ConnectionAdapters::MysqlAdapter # :nodoc:
|
|
12
12
|
post_sql_statements
|
13
13
|
end
|
14
14
|
|
15
|
-
def multiple_value_sets_insert_sql( table_name, column_names, options ) # :nodoc:
|
16
|
-
"INSERT #{options[:ignore]?'IGNORE ':''}INTO #{table_name} (#{column_names.join(',')}) VALUES "
|
15
|
+
def multiple_value_sets_insert_sql( table_name, column_names, options ) # :nodoc:
|
16
|
+
"INSERT #{options[:ignore] ? 'IGNORE ':''} INTO #{table_name} (#{column_names.join(',')}) VALUES "
|
17
17
|
end
|
18
18
|
|
19
19
|
# Returns a generated ON DUPLICATE KEY UPDATE statement given the passed
|
@@ -64,7 +64,7 @@ module ActiveRecord::Extensions::ConnectionAdapters::MysqlAdapter # :nodoc:
|
|
64
64
|
end
|
65
65
|
values_arr = values.map{ |arr| '(' + arr.join( ',' ) + ')' }
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
68
|
end
|
69
69
|
|
70
70
|
ActiveRecord::ConnectionAdapters::MysqlAdapter.send( 'include', ActiveRecord::Extensions::ConnectionAdapters::MysqlAdapter )
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module ActiveRecord # :nodoc:
|
2
|
+
class Base # :nodoc:
|
3
|
+
|
4
|
+
# Synchronizes the passed in ActiveRecord instances with data
|
5
|
+
# from the database. This is like calling reload
|
6
|
+
# on an individual ActiveRecord instance but it is intended for use on
|
7
|
+
# multiple instances.
|
8
|
+
#
|
9
|
+
# This uses one query for all instance updates and then updates existing
|
10
|
+
# instances rather sending one query for each instance
|
11
|
+
def self.synchronize(instances, key=ActiveRecord::Base.primary_key)
|
12
|
+
return if instances.empty?
|
13
|
+
|
14
|
+
keys = instances.map(&"#{key}".to_sym)
|
15
|
+
klass = instances.first.class
|
16
|
+
fresh_instances = klass.find( :all, :conditions=>{ key=>keys }, :order=>"#{key} ASC" )
|
17
|
+
|
18
|
+
instances.each_with_index do |instance, index|
|
19
|
+
instance.clear_aggregation_cache
|
20
|
+
instance.clear_association_cache
|
21
|
+
instance.instance_variable_set '@attributes', fresh_instances[index].attributes
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# See ActiveRecord::ConnectionAdapters::AbstractAdapter.synchronize
|
26
|
+
def synchronize(instances, key=ActiveRecord::Base.primary_key)
|
27
|
+
self.class.synchronize(instances, key)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -117,7 +117,7 @@ class ActiveRecord::TemporaryTable < ActiveRecord::Base
|
|
117
117
|
Object.send( :remove_const, self.name.to_sym )
|
118
118
|
@@temporary_table_hsh.delete( self )
|
119
119
|
else
|
120
|
-
raise StandardError.new "Trying to drop nonexistance temporary table: #{self.name}"
|
120
|
+
raise StandardError.new( "Trying to drop nonexistance temporary table: #{self.name}" )
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.
|
2
|
+
rubygems_version: 0.9.2
|
3
3
|
specification_version: 1
|
4
4
|
name: ar-extensions
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-
|
6
|
+
version: 0.6.0
|
7
|
+
date: 2007-05-05 00:00:00 -04:00
|
8
8
|
summary: Extends ActiveRecord functionality.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -42,22 +42,23 @@ files:
|
|
42
42
|
- config/database.yml.template
|
43
43
|
- config/mysql.schema
|
44
44
|
- config/postgresql.schema
|
45
|
-
- lib/ar-extensions.rb
|
45
|
+
- lib/ar-extensions/adapters/abstract_adapter.rb
|
46
|
+
- lib/ar-extensions/adapters/mysql_adapter.rb
|
47
|
+
- lib/ar-extensions/adapters/postgresql.rb
|
46
48
|
- lib/ar-extensions/csv.rb
|
47
49
|
- lib/ar-extensions/extensions.rb
|
48
50
|
- lib/ar-extensions/finders.rb
|
49
51
|
- lib/ar-extensions/foreign_keys.rb
|
50
|
-
- lib/ar-extensions/fulltext.rb
|
51
|
-
- lib/ar-extensions/import.rb
|
52
|
-
- lib/ar-extensions/temporary_table.rb
|
53
|
-
- lib/ar-extensions/version.rb
|
54
|
-
- lib/ar-extensions/adapters/abstract_adapter.rb
|
55
|
-
- lib/ar-extensions/adapters/mysql_adapter.rb
|
56
|
-
- lib/ar-extensions/adapters/postgresql.rb
|
57
52
|
- lib/ar-extensions/fulltext/mysql.rb
|
53
|
+
- lib/ar-extensions/fulltext.rb
|
58
54
|
- lib/ar-extensions/import/mysql.rb
|
59
55
|
- lib/ar-extensions/import/postgresql.rb
|
56
|
+
- lib/ar-extensions/import.rb
|
57
|
+
- lib/ar-extensions/synchronize.rb
|
60
58
|
- lib/ar-extensions/temporary_table/mysql.rb
|
59
|
+
- lib/ar-extensions/temporary_table.rb
|
60
|
+
- lib/ar-extensions/version.rb
|
61
|
+
- lib/ar-extensions.rb
|
61
62
|
test_files: []
|
62
63
|
|
63
64
|
rdoc_options:
|