On Nov 29, 3:39 pm, george <[email protected]> wrote:
> when doing json deserializaion on sequel model objects, im seeing some
> strange effects.  namely, a deserialized object looks like you did
> `ModelSubclass.new` and filled in column values without any checking
> or casting being done on their type.

That was an unintended consequence of the current implementation.  I
agree that typecasting should be done by default, and will commit a
patch shortly that does this.

> for instance, accessing a date
> column will return a date string instead of a proper date class
> object. whats worse is that these newly deserialized objects cannot be
> modified and saved to cause the changes to be persisted to the
> database -- they throw an exception like "Sequel::DatabaseError:
> Mysql::Error: Duplicate entry '1' for key 1". these objects return
> true when '.new?' is called, and it appears to me that this value
> causes sequel to attempt an insert instead of an update when
> '.save_changes' is called (or something similar), thereby causing a
> primary key conflict.  try the sample code below in irb for further
> clarification on these points.

The new flag was not copied over by design.  Basically, the
json_serializer plugin considers incoming JSON untrustworthy, since it
often comes directly from client machines.

> i suppose what im really looking for is a clean way to have the
> deserialize step ('JSON.parse(foo)') optionally do stuff like
> typecasting of columns, updating to current values from the db, and
> setting of model instance flags (at least @new and perhaps
> @modified)...  this could be done with options like 'JSON.parse(foo,
> {:typecast=>true, :autoRefresh=>false, :assumeNew=>true})'.  i presume
> that it would be best to do typecasting by default, and NOT do
> the .refresh by default, but im not sure what would be best (in
> general) for the @new and @modified flags.

Your proposed API can't currently work, because the options hash given
to JSON.parse is not passed to the model's json_create method (https://
github.com/flori/json/blob/master/lib/json/pure/parser.rb#L296).  I
would have definitely used an approach that used the JSON.parse
options hash if it was possible.

> what im doing now looks like this:
> deserializedModelObject = JSON.parse(serializedString).tap{|o|
> o.keys.each{|k| o[k]=o[k] }}.instance_ev...@new=@modified=false ;
> @changed_columns=[] ; self}
>
> i would much rather NOT do this myself for every deserialization...
> especially because in my desired usage, deserialized sequel model
> objects are buried inside other non-sequel model objects.

I assume you trust the JSON you are receiving?

My recommendation would be to use the existing json_serializer plugin
as the basis for your own custom plugin.  Or just override the
json_create class method in your code, assuming you always want those
features:

  class Ptime
    def self.json_create(*)
      obj = super
      obj.instance_eval do
        @new = false
        @modified = false
        changed_columns.clear
      end
      obj
    end
  end

With the patch I'll be committing, that hopefully will take care of
your needs.

Jeremy

-- 
You received this message because you are subscribed to the Google Groups 
"sequel-talk" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sequel-talk?hl=en.

Reply via email to