Ticket #6825: AR serialized attributes don't work with Oracle CLOB.

Hi,

New to Rails (love it!), and contributing bug reports/patches but here
goes....

We are working with rails edge using Oracle. We are using migrations
to create
tables with that have columns of type :text - which get mapped to an
Oracle CLOB type.

We then have ActiveRecord models that use the serialize feature on
these columns..ie.

class User < ActiveRecord::Base
   serialize :preferences
end

When you attempt to do a save on this you will get exceptions (when
using Oracle,
not mysql)

The problem seems to be in oracle_adapter.rb, which uses an after_save
filter to
handle the writing of the CLOB:

# After setting large objects to empty, select the OCI8::LOB
# and write back the data.
after_save :write_lobs
def write_lobs() #:nodoc:
   if connection.is_a?(ConnectionAdapters::OracleAdapter)
      self.class.columns.select { |c| c.sql_type =~ /LOB$/i }.each {

c>

            value = self[c.name]
            next if value.nil? || (value == '')
            lob = connection.select_one(
              "SELECT #{c.name} FROM #{self.class.table_name} WHERE
#{self.class.primary_key} = #{quote_value(id)}",
              'Writable Large Object')[c.name]
            lob.write value
          }
        end
      end

The "lob.write value" call does not take into account that "value" may
be a serialized attribute. To fix this I changed "lob.write value" to:

lob.write self.class.serialized_attributes[c.name] ? value.to_yaml :
value

I am not entirely certain that doing "value.to_yaml" is the best way to
get at the serialized representation of an attribute but it works for
my code.

Tom

tdfowler@pacbell.net wrote:

The "lob.write value" call does not take into account that "value" may
be a serialized attribute. To fix this I changed "lob.write value" to:

lob.write self.class.serialized_attributes[c.name] ? value.to_yaml :
value

I am not entirely certain that doing "value.to_yaml" is the best way to
get at the serialized representation of an attribute but it works for
my code.

Would you be able to provide a failing ActiveRecord test for this?

Michael A. Schoen wrote:

> The "lob.write value" call does not take into account that "value" may
> be a serialized attribute. To fix this I changed "lob.write value" to:
>
> lob.write self.class.serialized_attributes[c.name] ? value.to_yaml :
> value
>
> I am not entirely certain that doing "value.to_yaml" is the best way to
> get at the serialized representation of an attribute but it works for
> my code.

Would you be able to provide a failing ActiveRecord test for this?

Sure...

Here is my test case:

----serialize_test.rb------
require 'abstract_unit'

class Notification < ActiveRecord::Base
       serialize :n_conditions
end

class SerializeTest < Test::Unit::TestCase

  self.use_transactional_fixtures = false

  def setup

    ActiveRecord::Base.connection.create_table :notifications do |t|
       t.column :n_conditions, :text
       t.column :emails_sent, :integer, :limit => 6, :default
=> 0
    end

  end

  def teardown
    ActiveRecord::Base.connection.drop_table :notifications
  end

  def test_write_serialized_attribute1
    notification = Notification.new
    notification.n_conditions = ["this should work"]
    notification.save
  end

  def test_write_serialized_attribute2
    notification = Notification.new
    notification.n_conditions = "this should work"
    notification.save
  end

end

If this is reasonable (seems like it is – Michael), could you attach a new patch to the ticket and raise it on the other thread (RC2 imminent)? Would be a nice fix to have in 1.2, as I have a patched oracle adapter to deal with the same issue.

/Nick

http://dev.rubyonrails.org/ticket/6825
  AR serialized attributes don't work with Oracle CLOB

Thanks!

done, thanks!

Thanks Michael and Koz!

/Nick