Forum: Ruby on Rails Upgrade to Rails 2 - problem with "save" (MySQL boolean issue?)

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
(Guest)
on 2008-12-20 08:55
(Received via mailing list)
I have been working through an upgrade of my 1.2.6 application to
2.2.2.

I am almost there but I have hit a problem with ActiveRecord.

Before the upgrade, the following code was working fine.

    def create_root(administrator)
        root = create_root_collection(self.pingee_name,
                                      administrator,
                                      GlobalAccessibility.new,
                                      OwnerAccessibility.new)
        root.save
        self.root = root
    end

But now I get am getting an exception "undefined method `each' for
true:TrueClass" when root.save is executed.

fyi, the "create_root_collection" method creates a "root" object and
assigns new object to its "belongs to" association.

I have traced it through carefully and it is definitely failing when
trying to save the "root" object itself.

Given the error message, and the fact that the root object contains
boolean columns, I wonder if the problem is to do with the saving
boolean values. I am using MySQL and declaring the boolean columns in
the following way (using raw SQL not migrations currently):

include_parent_responses boolean default false not null,

Is the "boolean" column type still valid?

Thanks!
(Guest)
on 2008-12-20 15:53
(Received via mailing list)
To add, I am seeing the following when I retrieve an existing Root
object in the Rails console and then try to save it again:

=> #<Root id: 1, type: "Root", name: "Base of Administrator",
yaml_container: nil, parent_id: nil, owner_id: 1, custodian_id: 1,
property_control_id: 1, include_parent_responses: false, inheritable:
false, response_vehicle_id: nil, acquire_child_values: false,
description: nil, rating: nil, link_base_id: nil, base_image_id: nil,
event_when_id: nil, event_description_id: nil>
>> root.save
NoMethodError: undefined method `each' for true:TrueClass
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
base.rb:2808:in `attributes_with_quotes'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
base.rb:2706:in `update_without_lock'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
locking/optimistic.rb:70:in `update_without_dirty'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
dirty.rb:146:in `update_without_callbacks'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
callbacks.rb:253:in `update_without_timestamps'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
timestamp.rb:38:in `update'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
base.rb:2699:in `create_or_update_without_callbacks'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
callbacks.rb:222:in `create_or_update'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
base.rb:2383:in `save_without_validation'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
validations.rb:1009:in `save_without_dirty'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
dirty.rb:79:in `save_without_transactions'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
transactions.rb:179:in `send'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
transactions.rb:179:in `with_transaction_returning_status'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
connection_adapters/abstract/database_statements.rb:66:in
`transaction'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
transactions.rb:129:in `transaction'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
transactions.rb:138:in `transaction'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
transactions.rb:178:in `with_transaction_returning_status'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
transactions.rb:146:in `save'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
transactions.rb:158:in `rollback_active_record_state!'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
transactions.rb:146:in `save'

Any thoughts much appreciated.

On 20 Dec, 06:54, "removed_email_address@domain.invalid"
Frederick C. (Guest)
on 2008-12-20 16:27
(Received via mailing list)
On Dec 20, 1:52 pm, "removed_email_address@domain.invalid"
<removed_email_address@domain.invalid> wrote:
> To add, I am seeing the following when I retrieve an existing Root
> object in the Rails console and then try to save it again:
>
My guess would be that you have a method or an association with a name
that has since been used internally by activerecord. If you can show
more of your model someone might be able to spot the troublemaker.

Fred
(Guest)
on 2008-12-23 16:05
(Received via mailing list)
I have checked for method/association name clashes and can't see any.
Any tips on how I might debug this further would be very much
appreciated - I am completely stuck!

To recap, I am getting the error "undefined method `each' for
true:TrueClass" when an Active Record method (in active_record/base.rb
- see below) is being executed. So I assume 'attribute_names' is being
set to true for some reason.

      # Returns a copy of the attributes hash where all the values
have been safely quoted for use in
      # an SQL statement.
      def attributes_with_quotes(include_primary_key = true,
include_readonly_attributes = true, attribute_names =
@attributes.keys)
        quoted = {}
        connection = self.class.connection
        attribute_names.each do |name|
          if (column = column_for_attribute(name)) &&
(include_primary_key || !column.primary)
            value = read_attribute(name)

            # We need explicit to_yaml because quote() does not
properly convert Time/Date fields to YAML.
            if value && self.class.serialized_attributes.has_key?
(name) && (value.acts_like?(:date) || value.acts_like?(:time))
              value = value.to_yaml
            end

            quoted[name] = connection.quote(value, column)
          end
        end
        include_readonly_attributes ? quoted :
remove_readonly_attributes(quoted)
      end
Frederick C. (Guest)
on 2008-12-23 17:23
(Received via mailing list)
On 23 Dec 2008, at 14:04, removed_email_address@domain.invalid wrote:

>
> I have checked for method/association name clashes and can't see any.
> Any tips on how I might debug this further would be very much
> appreciated - I am completely stuck!

You could start by showing the code in your model. If you've got any
plugins you're using it's worth making sure they aren't the problem

Fred
(Guest)
on 2008-12-23 17:44
(Received via mailing list)
I'm not sure which model is causing the problem. I am now trapping
exceptions and the error first occurs when I execute root.save (see
***1***). 'root' is an instance of my Property model. I also get the
same error when executing code *** 2 *** (which follows the execution
of *** 1 ***) - member.save forces another (different) instance of
Property to be saved to the properties table which again triggers the
same error. FYI 'member.create_default_characteristics(user)' (in ***
2 ***) calls create_root() (*** 1 ***). The log file also suggests
that both errors are raised on an INSERT into my properties table.

*** 1 ***

    def create_root(administrator)
        begin
        root = create_root_collection(self.pingee_name,
                                      administrator,
                                      GlobalAccessibility.new,
                                      OwnerAccessibility.new)
        root.save
        rescue Exception => exe
          logger.info("*** Member.create_root #{exe} #{root.name.to_s}
***")
        end
        self.root = root
    end

*** 2 ***
    def self.add_member_for_user(user)
        member = new(:user_id => user.id, :pingee_name =>
user.pingee_name)
        # Create the member's default characteristics and save it all
to the database in a single
        # transaction
        begin
            transaction do
                member.create_default_characteristics(user)
                member.save!
            end
            member
        rescue Exception => exe
          logger.info("*** Member.add_member_for_user #{exe} ***")
        end
    end
Frederick C. (Guest)
on 2008-12-23 18:33
(Received via mailing list)
On 23 Dec 2008, at 15:44, removed_email_address@domain.invalid wrote:

>
>
> I'm not sure which model is causing the problem. I am now trapping

It would be the model being saved/created. A method called changed
would cause a problem for example.

Fred
(Guest)
on 2008-12-23 18:38
(Received via mailing list)
Fred,

I'll look for "changed".

I can re-create the error in the console - please see below. The error
would suggest that attribute_names in attributes_with_quotes is set to
true though as you can see the 'attributes.keys' for the instance
being saved seems ok.

*** CONSOLE OUTPUT - r, an existing Root object in the DB, raises an
error when I try to save it back
r = Property.find(1)
=> #<Root id: 1, type: "Root", name: "Base of Administrator",
yaml_container: nil, parent_id: nil, owner_id: 1, custodian_id: 1,
property_control_id: 1, include_parent_responses: false, inheritable:
false, response_vehicle_id: nil, acquire_child_values: false,
description: nil, rating: nil, link_base_id: nil, base_image_id: nil,
event_when_id: nil, event_description_id: nil>
>> r.save
NoMethodError: undefined method `each' for true:TrueClass
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
base.rb:2808:in `attributes_with_quotes'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
base.rb:2706:in `update_without_lock'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
locking/optimistic.rb:70:in `update_without_dirty'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
dirty.rb:146:in `update_without_callbacks'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
callbacks.rb:253:in `update_without_timestamps'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
timestamp.rb:38:in `update'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
base.rb:2699:in `create_or_update_without_callbacks'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
callbacks.rb:222:in `create_or_update'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
base.rb:2383:in `save_without_validation'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
validations.rb:1009:in `save_without_dirty'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
dirty.rb:79:in `save_without_transactions'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
transactions.rb:179:in `send'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
transactions.rb:179:in `with_transaction_returning_status'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
connection_adapters/abstract/database_statements.rb:66:in
`transaction'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
transactions.rb:129:in `transaction'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
transactions.rb:138:in `transaction'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
transactions.rb:178:in `with_transaction_returning_status'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
transactions.rb:146:in `save'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
transactions.rb:158:in `rollback_active_record_state!'
  from /usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/
transactions.rb:146:in `save'
  from (irb):24
  from :0>> r.attributes.keys
=> ["rating", "property_control_id", "name", "yaml_container",
"event_description_id", "type", "response_vehicle_id", "id",
"event_when_id", "custodian_id", "description", "base_image_id",
"owner_id", "acquire_child_values", "link_base_id", "parent_id",
"include_parent_responses", "inheritable"]
>>
(Guest)
on 2008-12-23 18:44
(Received via mailing list)
Fred,

I do have a "changed" method!

    #
    # Typically used by "set" accessors to indicate that an attribute
of this object has been changed.
    #
    def changed
        @has_changed = true
    end

Why would this cause a problem?

On 23 Dec, 16:37, "removed_email_address@domain.invalid"
Frederick C. (Guest)
on 2008-12-23 18:50
(Received via mailing list)
On 23 Dec 2008, at 16:43, removed_email_address@domain.invalid wrote:

>        @has_changed = true
>    end
>
> Why would this cause a problem?
>
Because in rails 2.1 there is a changed method that returns the list
of attributes that have changed (and thus need to be saved). You're
overwriting that method.

Fred
This topic is locked and can not be replied to.