Partial updates: why should validations run even if record won't be saved?

Is it a bug that when partial updates are on validations are run even
though the record is not going to save? This obviously cuts down on
performance especially with validations like validates_uniqueness_of
that hit the db. See the console for the database hit on the
validation even though the record was never going to be saveed...

# account.rb
class Account < ActiveRecord::Base
validates_presence_of :subdomain
validates_uniqueness_of :subdomain
end

~/dev/topsecret(master) $ ./script/console
Loading development environment (Rails 2.0.991)
ActiveRecord::Base.logger = >> ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Base.logger = Logger.new(STDOUT)

=> #<Logger:0x1978244 @formatter=nil,
@default_formatter=#<Logger::Formatter:0x1978118
@datetime_format=nil>, @progname=nil, @level=0,
@logdev=#<Logger::LogDevice:0x19763e0
@mutex=#<Logger::LogDevice::LogDeviceMutex:0x197632c @mon_owner=nil,
@mon_waiting_queue=[], @mon_entering_queue=[], @mon_count=0>,
@dev=#<IO:0x2e7d4>, @shift_size=nil, @shift_age=nil, @filename=nil>>

a = Account.first

SQL (0.000233) SET NAMES 'utf8'
SQL (0.000148) SET SQL_AUTO_IS_NULL=0
Account Load (0.095192) SELECT * FROM `accounts` LIMIT 1
Account Columns (0.075976) SHOW FIELDS FROM `accounts`
=> #<Account id: 1049686059, subdomain: "foobar", token:
"5e5160dbb2e9712af96a94348711b5320273bbfb", password: "9849291",
created_at: "2008-05-20 16:18:15", updated_at: "2008-05-21 18:02:06">

a.changed?

=> false

a.save

SQL (0.000187) BEGIN
SQL (0.020573) SELECT `subdomain` FROM `accounts` WHERE
(`accounts`.subdomain = 'foobar' AND `accounts`.id <> 1049686059)
SQL (0.003990) COMMIT
=> true

Let me know if this is indeed a bug and I'll file a proper bug report
and work up a fix. I just wanted to bring this up sooner rather than
later as I understand 2.1 is releasing soon.

Best,

Zack Chandler
http://depixelate.com

Let me know if this is indeed a bug and I'll file a proper bug report
and work up a fix. I just wanted to bring this up sooner rather than
later as I understand 2.1 is releasing soon.

I can definitely see how it might be a little annoying, but I'm not
sure that a quick fix is prudent this late in the release cycle.
There are a few hairy issues with callbacks:

before_save and friends, should they still fire? What about the other
callbacks? What if those callbacks were going to change attributes?
Basically we can't tell until the last minute whether or not a record
is changed, without introducing some bugs.

Let me know if this is indeed a bug and I'll file a proper bug report
and work up a fix. I just wanted to bring this up sooner rather than
later as I understand 2.1 is releasing soon.

I can definitely see how it might be a little annoying, but I'm not
sure that a quick fix is prudent this late in the release cycle.
There are a few hairy issues with callbacks:

before_save and friends, should they still fire? What about the other
callbacks? What if those callbacks were going to change attributes?
Basically we can't tell until the last minute whether or not a record
is changed, without introducing some bugs.

I agree this is too late in the release cycle for 2.1.

Still the only way that callbacks would affect attributes would be if
they were acting on non-attribute related information like an
association's attributes or the current time, etc. This would seem to
affect a very, very small percentage of models and therefore it would
make sense for Rails to make not running validations a "sensible
default" IMO.

Best,

Zack

I agree this is too late in the release cycle for 2.1.

Still the only way that callbacks would affect attributes would be if
they were acting on non-attribute related information like an
association's attributes or the current time, etc. This would seem to
affect a very, very small percentage of models and therefore it would
make sense for Rails to make not running validations a "sensible
default" IMO.

I disagree, many people (i.e. me) hash their passwords in a
before_save or before_validate callback, so until those are run the
hashed_password attribute is unchanged.

Still the only way that callbacks would affect attributes would be if
they were acting on non-attribute related information like an
association's attributes or the current time, etc. This would seem to
affect a very, very small percentage of models and therefore it would
make sense for Rails to make not running validations a "sensible
default" IMO.

I disagree, many people (i.e. me) hash their passwords in a
before_save or before_validate callback, so until those are run the
hashed_password attribute is unchanged.

Yes - hashing password is a good case against trying to further
optimizing the db hits with partial updates.

I suppose those of us looking to squeeze a bit more performance out can just do:

@obj.save if @obj.changed?

Best,

Zack