3

Jeremy EvanのSequelを使用して、(SQLite)データベースにWebページから取得したデータを入力しています。データベースには、私がアソシエーションで表現する多くの多対多の関係が含まれています。関連付けはクラス定義で作成され、スクリプトの実行時に常に評価されます。重要なのは、アソシエーションクラス定義に必要なテーブルを配置する必要があるということです。したがって、テーブル作成メソッドは、関連付け定義の最上位にある必要があります。次に例を示します。

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 に答える