Question

The title might be a bit misleading or broad, but what I am trying to do is to provide the necessary data for the sequel gem to create a table. Sequel's syntax for creating tables is the following

DB.create_table :items do
  primary_key :id
  String :name
  Float :price
end

For my particular case the column type and name are provided by the user, so I can only do it at runtime. For the time being I am accepting an array of column_name:column_type pairs, like so for instance:

['column1:string', 'column2:float']

but I am having a hard time yielding this information to the above block. My current attempt is:

my_db.create_table 'my_table' do
      array_of_typed_columns.each do |tc|
        column, type = tc.split(':')
        type.capitalize.constantize; column.to_sym
      end
    end

My understanding is that the above code would result in consecutive Type symbolized_column_name expressions yielded to the table creation block, but I always end up with a table with no columns. Any ideas?

Was it helpful?

Solution

The DSL where a line begins with a word, and then a list of parameters with a coma between them is actually a method call, so the original code is actually:

DB.create_table :items do
  primary_key(:id)
  String(:name)
  Float(:price)
end

From the sequel documentation:

Most method calls inside the create_table block will create columns, since method_missing calls column. Columns are generally created by specifying the column type as the method name, followed by the column name symbol to use, and after that any options that should be used. If the method is a ruby class name that Sequel recognizes, Sequel will transform it into the appropriate type for the given database. So while you specified String, Sequel will actually use varchar or text depending on the underlying database.

The create_table block uses method_missing to find out what you are trying to say. So what you could try to do is use send instead:

my_db.create_table 'my_table' do
  array_of_typed_columns.each do |tc|
    column, type = tc.split(':')
    send(type.capitalize, column.to_sym)
  end
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top