How can I reload the table schema in sequel?
Asked Answered
N

1

5

Given I have the following migration:

Sequel.migration do
  up do
    alter_table :users do
      add_column :is_admin, :default => false
    end

    # Sequel runs a DESCRIBE table statement, when the model is loaded.
    # At this point, it does not know that users have a is_admin flag.
    # So it fails.

    @user = User.find(:email => "[email protected]")
    @user.is_admin = true
    @user.save!
  end
end

Then sequel does not automatically reload the table structure (see comment inline).

I am using this ugly hack to work around it:

# deep magic begins here. If you remove a single line, it will
# break the migration.

User.db.schema("users", :reload => true)
User.instance_variable_set(:@db_schema, nil)
User.columns
User.new.respond_to?(:is_admin=)
sleep 1

Is there a better way?

Nalda answered 5/9, 2012 at 14:55 Comment(0)
C
9

Much simpler than your hack is this hack: (re)set the dataset to the table name:

User.set_dataset :users

Seen in action:

require 'sequel'
DB = Sequel.sqlite
DB.create_table :users do
  primary_key :id
  String :name
end

class User < Sequel::Model; end
User << { name:"Bob" }

DB.alter_table :users do
  add_column :is_admin, :boolean, default:false
end

p User.first       #=> #<User @values={:id=>1, :name=>"Bob", :is_admin=>false}>

p User.setter_methods    #=> ["name="]
User.set_dataset :users  # Make the magic happen
p User.setter_methods    #=> ["name=", "is_admin="]

@user = User.first
@user.is_admin = true
@user.save

p User.first       #=> #<User @values={:id=>1, :name=>"Bob", :is_admin=>true}>

Note that there is no Sequel::Model#save! method; I changed it to save so that it would work.

Chinfest answered 5/9, 2012 at 15:16 Comment(1)
Thank you! By the way: I wrote a monkey patch that adds save! in my version of sequel, that raises an exception, while save just returns true and false. So it works for me :)Nalda

© 2022 - 2024 — McMap. All rights reserved.