2013-10-05 26 views
3

我正在使用一些基本的Ruby代码来创建数据库表并设置一些值,但我在尝试运行代码时收到有关“相册”表的错误(我使用Ruby 1.9.3和Active Record 4.0.0)。在Ruby中查询ActiveRecord sqlite数据库时出错

代码和错误在下面,但我的问题是这样的:首先,我怎样才能防止这个错误(因为如果表确实已经存在,那么错误就会有意义),其次我怎样才能查看哪些表数据库和命令行上的这些表的内容(使用Mac OSX终端 - 我试过了sqlite3命令并查看了帮助文件,但我似乎无法让它做我想做的事情)。

的代码是...

# gem install sqlite3 
# gem install activerecord 

require 'active_record' 

ActiveRecord::Base.logger = Logger.new(STDERR) 
ActiveRecord::Base.establish_connection(
    :adapter => 'sqlite3', 
    :database => 'dbfile_example' # :memory: 
) 

ActiveRecord::Schema.define do 
    create_table :albums do |table| 
    table.column :title,  :string 
    table.column :performer, :string 
    end 

    create_table :tracks do |table| 
    table.column :album_id,  :integer 
    table.column :track_number, :integer 
    table.column :title,  :string 
    end 
end 

# Active Records don't specify their attributes directly 
# but rather infer them from the table definition with which they're linked 

class Album < ActiveRecord::Base 
    has_many :tracks # adds additional collection methods to the class 
end 

class Track < ActiveRecord::Base 
    belongs_to :album # specifies a one-to-one association with another Class (only use if this table holds the foreign key) 
end 

album = Album.create(
    :title  => 'In Utero', 
    :performer => 'Nirvana' 
) # notice you don't have to include the brackets to indicate it's a Hash 

# notice the Album object instance can reference the 'tracks' collection 
# via the `has_many` method and the `create` method is one of the additional 
# methods added as part of the call to `has_many` 

track_listing = [ 
    nil, 
    'Serve the Servants', 
    'Scentless Apprentice', 
    'Heart-Shaped Box', 
    'Rape Me', 
    'Frances Farmer', 
    'Dumb', 
    'Very Ape', 
    'Milk It', 
    'Pennyroyal Tea', 
    'Radio Friendly Unit Shifter', 
    'Tourettes', 
    'All Apologies' 
] 

track_listing.each_with_index do |value, index| 
    album.tracks.create(:track_number => index, :title => value) if index # zero is falsey so we skip it 
end 

album = Album.create(
    :title  => 'La-te-ra-lus', 
    :performer => 'Tool' 
) 

track_listing = [ 
    nil, 
    'The Grudge', 
    'Eon Blue Apocalypse', 
    'The Patient', 
    'Mantra', 
    'Schism', 
    'Parabol', 
    'Parabola', 
    'Ticks & Leeches', 
    'Lateralus', 
    'Disposition', 
    'Reflection', 
    'Triad', 
    'Faaip de Oiad' 
] 

track_listing.each_with_index do |value, index| 
    album.tracks.create(:track_number => index, :title => value) if index 
end 

p Album.find(1).tracks.length 
p Album.find(2).tracks.length 
p Album.find_by_title('La-te-ra-lus').title 
p Track.find_by_title('Very Ape').album_id 

...和错误是...

-- create_table(:albums) 
D, [2013-10-05T14:07:55.478413 #46822] DEBUG -- : (0.2ms) CREATE TABLE "albums" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "title" varchar(255), "performer" varchar(255)) 
E, [2013-10-05T14:07:55.478496 #46822] ERROR -- : SQLite3::SQLException: table "albums" already exists: CREATE TABLE "albums" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "title" varchar(255), "performer" varchar(255)) 
/Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/gems/gems/sqlite3-1.3.8/lib/sqlite3/database.rb:91:in `initialize': SQLite3::SQLException: table "albums" already exists: CREATE TABLE "albums" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "title" varchar(255), "performer" varchar(255)) (ActiveRecord::StatementInvalid) 
    from /Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/gems/gems/sqlite3-1.3.8/lib/sqlite3/database.rb:91:in `new' 
    from /Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/gems/gems/sqlite3-1.3.8/lib/sqlite3/database.rb:91:in `prepare' 
    from /Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/gems/gems/sqlite3-1.3.8/lib/sqlite3/database.rb:134:in `execute' 
    from /Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/gems/gems/activerecord-4.0.0/lib/active_record/connection_adapters/sqlite3_adapter.rb:328:in `block in execute' 
    from /Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/gems/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract_adapter.rb:425:in `block in log' 
    from /Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/gems/gems/activesupport-4.0.0/lib/active_support/notifications/instrumenter.rb:20:in `instrument' 
    from /Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/gems/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract_adapter.rb:420:in `log' 
    from /Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/gems/gems/activerecord-4.0.0/lib/active_record/connection_adapters/sqlite3_adapter.rb:328:in `execute' 
    from /Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/gems/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/schema_statements.rb:190:in `create_table' 
    from /Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/gems/gems/activerecord-4.0.0/lib/active_record/migration.rb:625:in `block in method_missing' 
    from /Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/gems/gems/activerecord-4.0.0/lib/active_record/migration.rb:597:in `block in say_with_time' 
    from /Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/1.9.1/benchmark.rb:280:in `measure' 
    from /Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/gems/gems/activerecord-4.0.0/lib/active_record/migration.rb:597:in `say_with_time' 
    from /Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/gems/gems/activerecord-4.0.0/lib/active_record/migration.rb:617:in `method_missing' 
    from sqlite-example.rb:13:in `block in <main>' 
    from /Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/gems/gems/activerecord-4.0.0/lib/active_record/schema.rb:42:in `instance_eval' 
    from /Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/gems/gems/activerecord-4.0.0/lib/active_record/schema.rb:42:in `define' 
    from /Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/gems/gems/activerecord-4.0.0/lib/active_record/schema.rb:62:in `define' 
    from sqlite-example.rb:12:in `<main>' 
+0

此代码是否在单个文件脚本中(例如包含所有代码的.rb)?如果是这样,那么你确实试图每次创建数据库。如果是这种情况,您可以将该特定部分(表创建)分隔到另一个文件中,或者在创建它们之前通过删除表来启动脚本:'drop_table:albums' – fmendez

回答

4

符合条件检查表的存在(显式的)包装你的架构创建的代码。

+0

这对我不起作用,仍然显示已经存在的表格“相册”。看起来问题在代码中实际调用'Album.create'的代码后面? – Integralist

+0

好的,算出':tracks'应该是''tracks'' – Integralist

+0

另外,是否有可能展示更简洁的版本,以便我可以看到有人会采取完整版并将其重构为更红宝石“ISH – Integralist

0

我想一个简单的方法是将一个begin ... rescue ... end块内包装数据库创建代码。

你是如何运行命令的?如果我记得,你需要运行sqlite3 your_db_name.db

ActiveRecord::Schema.define do 
    unless ActiveRecord::Base.connection.tables.include? 'albums' 
    create_table :albums do |table| 
     table.column :title,  :string 
     table.column :performer, :string 
    end 
    end 

    unless ActiveRecord::Base.connection.tables.include? 'tracks' 
    create_table :tracks do |table| 
     table.column :album_id,  :integer 
     table.column :track_number, :integer 
     table.column :title,  :string 
    end 
    end 
end 

可以写在一个更简洁的方式,但留下明确的风格更容易理解:

+0

re:sqlite命令行 - 我运行'sqlite3',然后' .help'来查看命令,然后我开始运行它显示给我的命令,但没有一个像我预期的那样工作,所以不知道我是否在做一些明显错误的事情? – Integralist

1

的代码从这个要点被复制:https://gist.github.com/unnitallman/944011

原来的要点有

ActiveRecord::Base.establish_connection(
    :adapter => "sqlite3", 
    :dbfile => ":memory:" 
) 

因此,这将每次初始化一个新的数据库。当你创建一个数据库文件时会崩溃,该文件在脚本的运行过程中保持不变。