activerecord 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

@@ -15,12 +15,10 @@ module ActiveRecord
15
15
  # The third approach, count using options, accepts an option hash as the only parameter. The options are:
16
16
  #
17
17
  # * <tt>:conditions</tt>: An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro.
18
- # * <tt>:joins</tt>: Either an SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id". (Rarely needed).
19
- # or names associations in the same form used for the :include option.
18
+ # * <tt>:joins</tt>: Either an SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id" (rarely needed)
19
+ # or named associations in the same form used for the :include option, which will perform an INNER JOIN on the associated table(s).
20
20
  # If the value is a string, then the records will be returned read-only since they will have attributes that do not correspond to the table's columns.
21
21
  # Pass :readonly => false to override.
22
- # See adding joins for associations under Associations.
23
- #
24
22
  # * <tt>:include</tt>: Named associations that should be loaded alongside using LEFT OUTER JOINs. The symbols named refer
25
23
  # to already defined associations. When using named associations, count returns the number of DISTINCT items for the model you're counting.
26
24
  # See eager loading under Associations.
@@ -9,7 +9,12 @@ module YAML #:nodoc:
9
9
  end
10
10
  end
11
11
 
12
- class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
12
+ if defined? ActiveRecord
13
+ class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
14
+ end
15
+ else
16
+ class FixtureClassNotFound < StandardError #:nodoc:
17
+ end
13
18
  end
14
19
 
15
20
  # Fixtures are a way of organizing data that you want to test against; in short, sample data. They come in 3 flavors:
@@ -911,6 +916,8 @@ module Test #:nodoc:
911
916
  end
912
917
 
913
918
  def setup_with_fixtures
919
+ return if @fixtures_setup
920
+ @fixtures_setup = true
914
921
  return unless defined?(ActiveRecord::Base) && !ActiveRecord::Base.configurations.blank?
915
922
 
916
923
  if pre_loaded_fixtures && !use_transactional_fixtures
@@ -942,6 +949,8 @@ module Test #:nodoc:
942
949
  alias_method :setup, :setup_with_fixtures
943
950
 
944
951
  def teardown_with_fixtures
952
+ return if @fixtures_teardown
953
+ @fixtures_teardown = true
945
954
  return unless defined?(ActiveRecord::Base) && !ActiveRecord::Base.configurations.blank?
946
955
 
947
956
  unless use_transactional_fixtures?
@@ -958,24 +967,31 @@ module Test #:nodoc:
958
967
  alias_method :teardown, :teardown_with_fixtures
959
968
 
960
969
  def self.method_added(method)
970
+ return if @__disable_method_added__
971
+ @__disable_method_added__ = true
972
+
961
973
  case method.to_s
962
974
  when 'setup'
963
975
  unless method_defined?(:setup_without_fixtures)
964
976
  alias_method :setup_without_fixtures, :setup
965
- define_method(:setup) do
977
+ define_method(:full_setup) do
966
978
  setup_with_fixtures
967
979
  setup_without_fixtures
968
980
  end
969
981
  end
982
+ alias_method :setup, :full_setup
970
983
  when 'teardown'
971
984
  unless method_defined?(:teardown_without_fixtures)
972
985
  alias_method :teardown_without_fixtures, :teardown
973
- define_method(:teardown) do
986
+ define_method(:full_teardown) do
974
987
  teardown_without_fixtures
975
988
  teardown_with_fixtures
976
989
  end
977
990
  end
991
+ alias_method :teardown, :full_teardown
978
992
  end
993
+
994
+ @__disable_method_added__ = false
979
995
  end
980
996
 
981
997
  private
@@ -70,7 +70,7 @@ module ActiveRecord
70
70
  return update_without_lock unless locking_enabled?
71
71
 
72
72
  lock_col = self.class.locking_column
73
- previous_value = send(lock_col)
73
+ previous_value = send(lock_col).to_i
74
74
  send(lock_col + '=', previous_value + 1)
75
75
 
76
76
  begin
@@ -297,7 +297,33 @@ module ActiveRecord
297
297
  :equal_to => '==', :less_than => '<', :less_than_or_equal_to => '<=',
298
298
  :odd => 'odd?', :even => 'even?' }.freeze
299
299
 
300
-
300
+ # Adds a validation method or block to the class. This is useful when
301
+ # overriding the #validate instance method becomes too unwieldly and
302
+ # you're looking for more descriptive declaration of your validations.
303
+ #
304
+ # This can be done with a symbol pointing to a method:
305
+ #
306
+ # class Comment < ActiveRecord::Base
307
+ # validate :must_be_friends
308
+ #
309
+ # def must_be_friends
310
+ # errors.add_to_base("Must be friends to leave a comment") unless commenter.friend_of?(commentee)
311
+ # end
312
+ # end
313
+ #
314
+ # Or with a block which is passed the current record to be validated:
315
+ #
316
+ # class Comment < ActiveRecord::Base
317
+ # validate do |comment|
318
+ # comment.must_be_friends
319
+ # end
320
+ #
321
+ # def must_be_friends
322
+ # errors.add_to_base("Must be friends to leave a comment") unless commenter.friend_of?(commentee)
323
+ # end
324
+ # end
325
+ #
326
+ # This usage applies to #validate_on_create and #validate_on_update as well.
301
327
  def validate(*methods, &block)
302
328
  methods << block if block_given?
303
329
  write_inheritable_set(:validate, methods)
@@ -403,7 +429,7 @@ module ActiveRecord
403
429
  configuration = { :message => ActiveRecord::Errors.default_error_messages[:confirmation], :on => :save }
404
430
  configuration.update(attr_names.extract_options!)
405
431
 
406
- attr_accessor *(attr_names.map { |n| "#{n}_confirmation" })
432
+ attr_accessor(*(attr_names.map { |n| "#{n}_confirmation" }))
407
433
 
408
434
  validates_each(attr_names, configuration) do |record, attr_name, value|
409
435
  record.errors.add(attr_name, configuration[:message]) unless record.send("#{attr_name}_confirmation").nil? or value == record.send("#{attr_name}_confirmation")
@@ -425,7 +451,8 @@ module ActiveRecord
425
451
  # * <tt>on</tt> - Specifies when this validation is active (default is :save, other options :create, :update)
426
452
  # * <tt>allow_nil</tt> - Skip validation if attribute is nil. (default is true)
427
453
  # * <tt>accept</tt> - Specifies value that is considered accepted. The default value is a string "1", which
428
- # makes it easy to relate to an HTML checkbox.
454
+ # makes it easy to relate to an HTML checkbox. This should be set to 'true' if you are validating a database
455
+ # column, since the attribute is typecast from "1" to <tt>true</tt> before validation.
429
456
  # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should
430
457
  # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The
431
458
  # method, proc or string should return or evaluate to a true or false value.
@@ -436,7 +463,13 @@ module ActiveRecord
436
463
  configuration = { :message => ActiveRecord::Errors.default_error_messages[:accepted], :on => :save, :allow_nil => true, :accept => "1" }
437
464
  configuration.update(attr_names.extract_options!)
438
465
 
439
- attr_accessor *attr_names.reject { |name| column_names.include? name.to_s }
466
+ db_cols = begin
467
+ column_names
468
+ rescue ActiveRecord::StatementInvalid
469
+ []
470
+ end
471
+ names = attr_names.reject { |name| db_cols.include?(name.to_s) }
472
+ attr_accessor(*names)
440
473
 
441
474
  validates_each(attr_names,configuration) do |record, attr_name, value|
442
475
  record.errors.add(attr_name, configuration[:message]) unless value == configuration[:accept]
@@ -2,7 +2,7 @@ module ActiveRecord
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 2
4
4
  MINOR = 0
5
- TINY = 1
5
+ TINY = 2
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -33,12 +33,12 @@ class AAACreateTablesTest < Test::Unit::TestCase
33
33
  private
34
34
  def use_migrations?
35
35
  unittest_sql_filename = ActiveRecord::Base.connection.adapter_name.downcase + ".sql"
36
- not File.exists? "#{@base_path}/#{unittest_sql_filename}"
36
+ not File.exist? "#{@base_path}/#{unittest_sql_filename}"
37
37
  end
38
38
 
39
39
  def use_migrations_for_courses?
40
40
  unittest2_sql_filename = ActiveRecord::Base.connection.adapter_name.downcase + "2.sql"
41
- not File.exists? "#{@base_path}/#{unittest2_sql_filename}"
41
+ not File.exist? "#{@base_path}/#{unittest2_sql_filename}"
42
42
  end
43
43
 
44
44
  def recreate(base, suffix = nil)
@@ -539,6 +539,12 @@ class AssociationsJoinModelTest < Test::Unit::TestCase
539
539
  def test_has_many_through_has_many_with_sti
540
540
  assert_equal [comments(:does_it_hurt)], authors(:david).special_post_comments
541
541
  end
542
+
543
+ def test_uniq_has_many_through_should_retain_order
544
+ comment_ids = authors(:david).comments.map(&:id)
545
+ assert_equal comment_ids.sort, authors(:david).ordered_uniq_comments.map(&:id)
546
+ assert_equal comment_ids.sort.reverse, authors(:david).ordered_uniq_comments_desc.map(&:id)
547
+ end
542
548
 
543
549
  private
544
550
  # create dynamic Post models to allow different dependency options
@@ -55,7 +55,7 @@ class AssociationsTest < Test::Unit::TestCase
55
55
  def test_storing_in_pstore
56
56
  require "tmpdir"
57
57
  store_filename = File.join(Dir.tmpdir, "ar-pstore-association-test")
58
- File.delete(store_filename) if File.exists?(store_filename)
58
+ File.delete(store_filename) if File.exist?(store_filename)
59
59
  require "pstore"
60
60
  apple = Firm.create("name" => "Apple")
61
61
  natural = Client.new("name" => "Natural Company")
@@ -133,6 +133,13 @@ class AssociationProxyTest < Test::Unit::TestCase
133
133
  assert_nil p.author.reset
134
134
  end
135
135
 
136
+ def test_reload_returns_assocition
137
+ david = developers(:david)
138
+ assert_nothing_raised do
139
+ assert_equal david.projects, david.projects.reload.reload
140
+ end
141
+ end
142
+
136
143
  def setup_dangling_association
137
144
  josh = Author.create(:name => "Josh")
138
145
  p = Post.create(:title => "New on Edge", :body => "More cool stuff!", :author => josh)
@@ -28,7 +28,15 @@ class FinderTest < Test::Unit::TestCase
28
28
  assert Topic.exists?(:author_name => "Mary", :approved => true)
29
29
  assert Topic.exists?(["parent_id = ?", 1])
30
30
  assert !Topic.exists?(45)
31
- assert !Topic.exists?("foo")
31
+
32
+ begin
33
+ assert !Topic.exists?("foo")
34
+ rescue ActiveRecord::StatementInvalid
35
+ # PostgreSQL complains about string comparison with integer field
36
+ rescue Exception
37
+ flunk
38
+ end
39
+
32
40
  assert_raise(NoMethodError) { Topic.exists?([1,2]) }
33
41
  end
34
42
 
@@ -18,6 +18,8 @@ class Author < ActiveRecord::Base
18
18
  has_many :comments_desc, :through => :posts, :source => :comments, :order => 'comments.id DESC'
19
19
  has_many :limited_comments, :through => :posts, :source => :comments, :limit => 1
20
20
  has_many :funky_comments, :through => :posts, :source => :comments
21
+ has_many :ordered_uniq_comments, :through => :posts, :source => :comments, :uniq => true, :order => 'comments.id'
22
+ has_many :ordered_uniq_comments_desc, :through => :posts, :source => :comments, :uniq => true, :order => 'comments.id DESC'
21
23
 
22
24
  has_many :special_posts
23
25
  has_many :special_post_comments, :through => :special_posts, :source => :comments
@@ -324,6 +324,22 @@ class MultipleFixturesTest < Test::Unit::TestCase
324
324
  end
325
325
  end
326
326
 
327
+ # This is to reproduce a bug where if a TestCase is loaded
328
+ # twice by Ruby, it loses its fixture setup hook.
329
+ class_def = <<-CODE
330
+ class DoubleLoadedTestCase < Test::Unit::TestCase
331
+ fixtures :topics
332
+
333
+ def setup
334
+ end
335
+
336
+ def test_should_properly_setup_fixtures
337
+ assert_nothing_raised { topics(:first) }
338
+ end
339
+ end
340
+ CODE
341
+ 2.times { eval(class_def) }
342
+
327
343
  class OverlappingFixturesTest < Test::Unit::TestCase
328
344
  fixtures :topics, :developers
329
345
  fixtures :developers, :accounts
@@ -64,6 +64,15 @@ class OptimisticLockingTest < Test::Unit::TestCase
64
64
 
65
65
  assert_raises(ActiveRecord::StaleObjectError) { p2.save! }
66
66
  end
67
+
68
+ def test_lock_new_with_nil
69
+ p1 = Person.new(:first_name => 'anika')
70
+ p1.save!
71
+ p1.lock_version = nil # simulate bad fixture or column with no default
72
+ p1.save!
73
+ assert_equal 1, p1.lock_version
74
+ end
75
+
67
76
 
68
77
  def test_lock_column_name_existing
69
78
  t1 = LegacyThing.find(1)
@@ -301,6 +301,14 @@ class ValidationsTest < Test::Unit::TestCase
301
301
  assert_equal "Dan Brown", reply["author_name"]
302
302
  end
303
303
 
304
+ def test_validates_acceptance_of_with_non_existant_table
305
+ Object.const_set :IncorporealModel, Class.new(ActiveRecord::Base)
306
+
307
+ assert_nothing_raised ActiveRecord::StatementInvalid do
308
+ IncorporealModel.validates_acceptance_of(:incorporeal_column)
309
+ end
310
+ end
311
+
304
312
  def test_validate_presences
305
313
  Topic.validates_presence_of(:title, :content)
306
314
 
metadata CHANGED
@@ -1,33 +1,34 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.4
3
- specification_version: 1
4
2
  name: activerecord
5
3
  version: !ruby/object:Gem::Version
6
- version: 2.0.1
7
- date: 2007-12-07 00:00:00 -06:00
8
- summary: Implements the ActiveRecord pattern for ORM.
9
- require_paths:
10
- - lib
11
- email: david@loudthinking.com
12
- homepage: http://www.rubyonrails.org
13
- rubyforge_project: activerecord
14
- description: Implements the ActiveRecord pattern (Fowler, PoEAA) for ORM. It ties database tables and classes together for business objects, like Customer or Subscription, that can find, save, and destroy themselves without resorting to manual SQL.
15
- autorequire: active_record
16
- default_executable:
17
- bindir: bin
18
- has_rdoc: true
19
- required_ruby_version: !ruby/object:Gem::Version::Requirement
20
- requirements:
21
- - - ">"
22
- - !ruby/object:Gem::Version
23
- version: 0.0.0
24
- version:
4
+ version: 2.0.2
25
5
  platform: ruby
26
- signing_key:
27
- cert_chain:
28
- post_install_message:
29
6
  authors:
30
7
  - David Heinemeier Hansson
8
+ autorequire: active_record
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2007-12-20 00:00:00 -06:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activesupport
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - "="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.0.2
23
+ version:
24
+ description: Implements the ActiveRecord pattern (Fowler, PoEAA) for ORM. It ties database tables and classes together for business objects, like Customer or Subscription, that can find, save, and destroy themselves without resorting to manual SQL.
25
+ email: david@loudthinking.com
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files:
31
+ - README
31
32
  files:
32
33
  - Rakefile
33
34
  - install.rb
@@ -96,7 +97,6 @@ files:
96
97
  - test/ar_schema_test.rb
97
98
  - test/association_inheritance_reload.rb
98
99
  - test/associations
99
- - test/associations/ar_joins_test.rb
100
100
  - test/associations/callbacks_test.rb
101
101
  - test/associations/cascaded_eager_loading_test.rb
102
102
  - test/associations/eager_singularization_test.rb
@@ -345,26 +345,32 @@ files:
345
345
  - test/validations_test.rb
346
346
  - test/xml_serialization_test.rb
347
347
  - examples/associations.png
348
- test_files: []
349
-
348
+ has_rdoc: true
349
+ homepage: http://www.rubyonrails.org
350
+ post_install_message:
350
351
  rdoc_options:
351
352
  - --main
352
353
  - README
353
- extra_rdoc_files:
354
- - README
355
- executables: []
356
-
357
- extensions: []
358
-
354
+ require_paths:
355
+ - lib
356
+ required_ruby_version: !ruby/object:Gem::Requirement
357
+ requirements:
358
+ - - ">="
359
+ - !ruby/object:Gem::Version
360
+ version: "0"
361
+ version:
362
+ required_rubygems_version: !ruby/object:Gem::Requirement
363
+ requirements:
364
+ - - ">="
365
+ - !ruby/object:Gem::Version
366
+ version: "0"
367
+ version:
359
368
  requirements: []
360
369
 
361
- dependencies:
362
- - !ruby/object:Gem::Dependency
363
- name: activesupport
364
- version_requirement:
365
- version_requirements: !ruby/object:Gem::Version::Requirement
366
- requirements:
367
- - - "="
368
- - !ruby/object:Gem::Version
369
- version: 2.0.1
370
- version:
370
+ rubyforge_project: activerecord
371
+ rubygems_version: 1.0.0
372
+ signing_key:
373
+ specification_version: 2
374
+ summary: Implements the ActiveRecord pattern for ORM.
375
+ test_files: []
376
+
File without changes