3

我正在使用 Jeremy Evan 的Sequel来使用从网页中抓取的数据填充(SQLite)数据库。该数据库涉及我用Associations表达的许多 many_to_many 关系。关联是在类定义中创建的,在脚本运行时总是会对其进行评估。重要的是,关联类定义需要有必要的表。因此,表创建方法应该在关联定义的顶层。这是一个例子:

module Thing
db = Sequel.Sqlite('data.sqlite')

db.create_table(:clients)
    String :client_id, :primary_key => true
    String :client_data
end

db.create_table(:orders)
    String :order_id, :primary_key => true
    String :order_data
end

db.create_table(:orders_clients)
    String :order_id
    String :client_id
    primary_key [:order_id,:client_id]
end

class Person < Sequel::Model
    unrestrict_primary_key
    many_to_many :orders
end

class Order < Sequel::Model
    unrestrict_primary_key
    many_to_many :orders
end
end

首先,我认为这是一个相当肮脏的解决方案,因为我的方法调用和类定义位于同一个命名空间中。如果我尝试分离类定义,我会得到No database associated with Sequel::Model错误(这是有道理的,但我想推迟对关联定义的评估,在表调用之后,只要它们可能发生)。

我希望能够在方法调用中创建表和关联。因此,例如,我可以传递新数据库文件的名称:

def create_tables_and_schema (database_name)
    db = Sequel.Sqlite(database_name)
    db.create_table... #three of those, as above

class Person < Sequel::Model
    unrestrict_primary_key
    many_to_many :orders
end

class Order < Sequel::Model
    unrestrict_primary_key
    many_to_many :orders
end
end

我认为需要的是一种不同的方式来表达表关系。

任何关于方法和风格的建议都值得赞赏。如果解释令人困惑,请要求澄清。

4

1 回答 1

5

Your method calls and class definitions do not need to sit in the same namespace, it's just that the tables need to be created before the model classes. An easy way to separate them is to move the table creation to a separate file. Also, usually you assign the database object to a constant.

create_tables.rb:

DB.create_table(:clients)
  String :client_id, :primary_key => true
  String :client_data
end

DB.create_table(:orders)
  String :order_id, :primary_key => true
  String :order_data
end

DB.create_table(:orders_clients)
  String :order_id
  String :client_id
  primary_key [:order_id,:client_id]
end

models.rb:

DB = Sequel.sqlite('data.sqlite')
require 'create_tables'

class Person < Sequel::Model
  unrestrict_primary_key
  many_to_many :orders
end

class Order < Sequel::Model
  unrestrict_primary_key
  many_to_many :orders
end

You mentioned that you want to create the tables and associations in a method call, but that doesn't make sense if you are creating classes with constants. The main reason to create them via a method call is to allow for multiple databases at runtime, but that wouldn't work with your model classes since they are defined with constant names.

If you don't need multiple databases at runtime, the example above should work if you just want to separate the table creation from the model creation.

If you do need multiple databases at runtime, then creating the tables and models via a method call makes sense, but you need to create anonymous model classes, as otherwise you will have problems.

于 2012-08-01T15:19:05.713 回答