ar-extensions 0.5.2 → 0.6.0

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 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
  ------------------------------
@@ -49,6 +49,7 @@ ActiveRecord::Schema.define do
49
49
  t.column :publisher, :string, :null=>false
50
50
  t.column :author_name, :string, :null=>false
51
51
  t.column :created_at, :time
52
+ t.column :topic_id, :integer
52
53
  end
53
54
 
54
55
  create_table :languages, :force=>true do |t|
@@ -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
 
@@ -1,4 +1,4 @@
1
1
  class SchemaInfo < ActiveRecord::Base
2
2
  set_table_name 'schema_info'
3
- VERSION = 5
3
+ VERSION = 6
4
4
  end
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, nil )
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
- if match_data=key.to_s.match( LIKE_RGX )
261
- fieldname = match_data.captures[0]
262
- str = "#{caller.table_name}.#{caller.connection.quote_column_name( fieldname )} LIKE ?"
263
- return Result.new( str, "%#{val}%" )
264
- elsif match_data=key.to_s.match( STARTS_WITH_RGX )
265
- fieldname = match_data.captures[0]
266
- str = "#{caller.table_name}.#{caller.connection.quote_column_name( fieldname )} LIKE ?"
267
- return Result.new( str, "#{val}%" )
268
- elsif match_data=key.to_s.match( ENDS_WITH_RGX )
269
- fieldname = match_data.captures[0]
270
- str = "#{caller.table_name}.#{caller.connection.quote_column_name( fieldname )} LIKE ?"
271
- return Result.new( str, "%#{val}" )
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
- nil
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 ) #if arg.respond_to?( :to_sql )
24
+ arg = sanitize_sql_by_way_of_duck_typing( arg )
25
25
  elsif arg.is_a?( Hash )
26
- arg = sanitize_sql_from_hash( arg ) #if arg.is_a?( Hash )
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
- arg = sanitize_sql_from_string_and_hash( arg ) # if arg.size == 2 and arg.first.is_a?( String ) and arg.last.is_a?( Hash )
28
+ arg = sanitize_sql_from_string_and_hash( arg )
29
29
  end
30
30
  sanitize_sql_orig( arg )
31
31
  end
@@ -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
 
@@ -2,7 +2,7 @@
2
2
  module ActiveRecord # :nodoc:
3
3
  module Extensions # :nodoc:
4
4
  module VERSION
5
- MAJOR, MINOR, REVISION = %W( 0 5 2 )
5
+ MAJOR, MINOR, REVISION = %W( 0 6 0 )
6
6
  STRING = [ MAJOR, MINOR, REVISION ].join( '.' )
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.1
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.5.2
7
- date: 2007-03-15 00:00:00 -04:00
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: