Thanks for answer. I understood, this is planned behaviour. But there are
some issues with it:
1. it changed silently in minor release, so some code no more works as
expected. This is not problem with single application but may be problem
with framework-based application when framework requires Sequel. As for me
I got bug with NULL in new record while I tested same code before and got
"[]" (empty js-array) in same cell.
2. it confuse hooks logic:
class Test < Sequel::Model(:tests)
plugin :serialization, :json, :data
def before_save
self.data ||= []
self.name ||= 'bar'
super
end
end
t = Test.create()
p t
will return #<Test @values={:id=>1, :name=>"bar", :data=>nil}>
ie :name field was changed but :data was not! Not intuitive.
3. As for auto_validations plugin. I consider there are two types of
possible validation: high-level (for unserialized data) and low-level (for
raw data before put it to DB). High-level validation can be applied to be
sure username filled or be sure currency specified with price. Low-level
validation can be applied to sure raw data correct according DB/schema
requirements. Thus rational save sequence is: high-level validation ->
before_save modification -> serialization -> low-level validation -> query.
Auto_validations plugin is low-level.
4. Just a question. Why _before_validation, not before_validation?
понедельник, 19 января 2015 г., 4:04:02 UTC+10 пользователь Jeremy Evans
написал:
>
> On Saturday, January 17, 2015 at 9:40:25 PM UTC-8, Valentin Syrovatskiy
> wrote:
>>
>> Hi, Jeremy!
>>
>> Gemfile:
>> source 'https://rubygems.org'
>>
>> gem 'sequel', '4.12'
>> gem 'sqlite3'
>>
>>
>>
>> test.rb:
>> require 'rubygems'
>> require 'bundler/setup'
>> require 'sequel'
>> require 'json'
>>
>>
>> Sequel::Model.db = Sequel.sqlite
>>
>> Sequel::Model.db.create_table(:tests){
>> primary_key :id
>> varchar :name
>> text :data
>> }
>>
>> class Test < Sequel::Model(:tests)
>> plugin :serialization
>> serialize_attributes :json, :data
>>
>> def before_save
>> self.data ||= [1, 2]
>> super
>> end
>> end
>>
>> p Sequel::VERSION
>>
>> t = Test.create(name: 'foo')
>> p t
>>
>> Now I open console, run 'bundle install', then 'ruby test.rb' and got
>>
>>
>>
>> *"4.12.0"#<Test @values={:id=>1, :name=>"foo", :data=>"[1,2]"}>*
>>
>> But with sequel 4.13 up to 4.18 (change in Gemfile) with 'ruby test.rb' i
>> got
>>
>>
>> *"4.18.0"#<Test @values={:id=>1, :name=>"foo", :data=>nil}>*
>>
>> Is this behaviour correct or this is a bug?
>>
>
> I consider the current behavior correct. The behavior was changed in
> 4.13.0 because when was serializing the data after before_save, Sequel
> couldn't correctly run validations on the underlying columns, which made
> serialization difficult to use with auto_vaildations. So Sequel needs to
> serialize before validation, not after, and before_save happens after
> validation. So modifying a deserialized value in before_save no longer has
> an effect on the current save, since the serialization of the column has
> already been done.
>
> If you want to add something to a serialized column before it is
> serialized, you should switch to the _before_validation hook, which is
> called on every save, before validation (if any) is done:
>
> def _before_validation
> self_data ||= [1, 2]
> super
> end
>
> You aren't the first person to bring this up as an issue. As I've
> mentioned in previous posts, I'm open to making the old behavior available
> via an option. However, since it is fairly easy to switch to the new
> behavior, there doesn't seem to be much reason to do so.
>
> Thanks,
> Jeremy
>
--
You received this message because you are subscribed to the Google Groups
"sequel-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sequel-talk.
For more options, visit https://groups.google.com/d/optout.