2

I want to swap the content in answers table with ActiveRecord.
code 1:

Archieve::Answer.find_each do |answer|
  str = answer.content
  dosomething() #change the value
  answer.update_attribute(:content,str)
end

But It doesn't change the value of content.

code 2:

Archieve::Answer.find_each do |answer|
  str = answer.content
  dosomething() #change the value
  answer.reload
  answer.update_attributes(
    :content => str
  )
end

Before update the :content attributes, I reload the record every time.
It can indeed change the the value.
Why?
What's the difference between code 1 & code 2?
Source Code

###1 Post Debug Message:
Updated Post:

Changed?: false 
valid?: true 
errors: #<ActiveModel::Errors:0xa687568> 
errors: #<ActiveModel::Errors:0xa687568 @base=#<Archieve::Answer id: 9997190932758339, user_id: 4163690810052834, question_id: 3393286738785869, content: "狗狗生病,好可怜呀,", is_correct: false, votes_count: 0, comments_count: 0, created_at: "2011-11-06 18:38:53", updated_at: "2011-11-06 18:38:53">, @messages={}>
kit.yang
  • 2,758
  • 3
  • 17
  • 17

1 Answers1

0

possible ActiveRecord 3.1.1 bug

The OP mentioned to me that he uses require "active_record" in a stand alone script (not using rails runner). There is no separate Rails application for his task, he just uses a script. This is not necessarily bad, and has worked in earlier ActiveRecord versions, e.g. 2.x AFAIK -- maybe this is a regression in Rails 3.1 due to a new dependency?

# the OP's require statements:
require 'rubygems'
require 'logger'
require 'yaml'
require 'uuidtools'
require 'active_record'

complete code here: https://raw.github.com/Zhengquan/Swap_Chars/master/lib/orm.rb

maybe a dependency is missing, or problem with AR 3.1.1 when initialized stand alone?

It could be a bug actually

It could be that update_attribute() triggers a bug in the dirty-tracking of attributes, which then incorrectly assumes that the object has not changed, and as a result it will not be persisted, although the implementation of update_attribute() calls save() (see code fragment below).

I've seen something like this with an older version of Mongoid -- could be that there is a similar hidden bug in your ActiveRecord version for update_attribute()

In the Rails Console monkey-patch update_attribute like this:

class ActiveRecord::Base
  def update_attribute(name, value) # make sure you use the exact code of your Rails Version here
    send(name.to_s + '=', value)
    puts "Changed?: #{changed?}"        # this produced false in the OP's scenario
    puts "valid?: #{valid?}"
    puts "errors: #{errors.inspect}"
    save
  end
end

then try to run your Code 1 again...

you shouldn't see "Changed?: false".. if it returns false, although you changed the attribute, then there is a bug in your ActiveRecord version and you should report it.

Code 1:

NOTE: check the definition of update_attribute() (singular) here: (please read the fine-print regarding validations -- it doesn't sound like a good idea to use that method)

http://ar.rubyonrails.org/classes/ActiveRecord/Base.html#M000400

See also:

Rails: update_attribute vs update_attributes

The source code for update_attribute() looks like this:

2260:       def update_attribute(name, value)
2261:         send(name.to_s + '=', value)
2262:         save
2263:       end

it could fail if there is a bug with the dirty-tracking of attributes...

Code 2:

The second code looks correct.

There are a couple of things to also consider:

1) which attributes did you define as accessible, via attr_accessible ?

e.g. only accessible attributes will be updated via update_attributes()

http://apidock.com/rails/ActiveRecord/Base/update_attributes

2) which validations do you use?

are you sure the validations pass for the record when you call update_attribute?

See also:

http://guides.rubyonrails.org/active_record_querying.html

http://m.onkey.org/active-record-query-interface

http://api.rubyonrails.org/classes/ActiveRecord/Base.html

Community
  • 1
  • 1
Tilo
  • 33,354
  • 5
  • 79
  • 106
  • I define the `:content` with `attr_accessible`.The :content has no other validation except the `Text` type. – kit.yang Nov 15 '11 at 03:00
  • http://stackoverflow.com/questions/6722335/weird-relationship-behavior-on-rails-3-and-update-attribute – Tilo Nov 15 '11 at 03:16
  • I think so. When I execute the `Code 1`,the ActiveRecord logger shows "-----begin----- ---commit---" without do anything. – kit.yang Nov 15 '11 at 03:25
  • I will post the `irb` result soon. – kit.yang Nov 15 '11 at 03:41
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/4999/discussion-between-tilo-and-kit-yang) – Tilo Nov 15 '11 at 04:01