Using sequel 4.29.0.
I'm planning to use the before_save
sequel hook to trigger an action, In this case I need to make sure if an specific column changed, in previous implementations I used the @changed_columns
sequel instance variable to get the list of the columns that changed and some something like:
class MyModel < Sequel::Model
def before_save
special_method if @changed_columns.include? :properties
super
end
def special_method
...
end
end
This time I'm using the Postgresql jsonb type column (very handy btw). Every time I use modify that column the @changed_columns
never hold the column, I know I can specify a column as "dirty", however that means I have to change all the places this column is changed and sometimes is not that simple.
An example of how this is not working:
irb(main):001:0> MyModel.columns
=> [:id, :foo, :properties] # :foo is a string, :properties is jsonb
irb(main):002:0> my_model = MyModel.last
=> #<MyModel @values={:id=>37, :foo=>"bar", :properties=>{"foo"=>true}}>
irb(main):003:0> my_model.properties['foo'] = false
=> false
irb(main):004:0> my_model
=> #<MyModel @values={:id=>37, :foo=>"bar", :properties=>{"foo"=>false}}>
irb(main):005:0> my_model.modified?
=> false # this should be true since properties changed a value inside the hash
irb(main):006:0> my_model.foo = 'foo'
=> "foo"
irb(main):007:0> my_model
=> #<MyModel @values={:id=>37, :foo=>"foo", :properties=>{"foo"=>false}}>
irb(main):008:0> my_model.modified?
=> true
irb(main):009:0> my_model.changed_columns
=> [:foo] # should include the :properties column
This is Sequel's expected default behavior. If you want to detect mutation to column values, you need to use the modification_detection plugin:
DB.extension :pg_json
DB.create_table!(:bs){primary_key :id; jsonb :properties}
class B < Sequel::Model; end
B.plugin :modification_detection
B.create(:properties=>{'a'=>1})
b = B.first
b.properties['a'] = 2
b.modified?
# => true