3

Я использую базовый код Ruby для создания таблицы базы данных и для установки некоторых значений, но я получаю сообщение об ошибке «таблица», уже существующая при попытке запустить код (Я использую Ruby 1.9.3 и Active Record 4.0.0).Ошибка при запросе базы данных sqlite ActiveRecord в Ruby

Код и ошибка ниже, но мой вопрос заключается в следующем: во-первых, как я могу предотвратить эту ошибку (потому что, если таблица действительно существует, тогда ошибка имеет смысл), а во-вторых, как я могу просмотреть, какие таблицы база данных имеет и содержимое этих таблиц в командной строке (с использованием терминала 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: альбомы' – fmendez

ответ

4

Wrap кода создания схемы с существованием чекового условия таблицы (явный стиль):

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

Это не сработало для меня, все еще отображает уже существующие «альбомы». Похоже, проблема заключается в том, что в коде, где он на самом деле вызывает «Album.create»? – Integralist

+0

ОК, выработала проблему ': tracks' должно быть' 'tracks'' – Integralist

+0

Также было бы возможно показать более сжатую версию, чтобы я мог видеть, как кто-то подходит к полной версии и рефакторинг ее будет больше рубином «иш – Integralist

0

Я думаю, один простой способ, чтобы обернуть код создания базы данных в пределах блока begin ... rescue ... end ,

Как вы выполнили команду? Если я помню, вам нужно запустить sqlite3 your_db_name.db.

+0

re: командная строка sqlite - я запустил' sqlite3', а затем ' .help', чтобы увидеть команды, а затем я начал запускать команды, которые он показывал мне, но никто не работал так, как я ожидал, поэтому не знал, что я просто делал что-то вопиющее неправильно? – Integralist

1

код был скопирован с этой сути: https://gist.github.com/unnitallman/944011

Оригинальная сутью была

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

Так было бы инициализировать новую базу данных каждый раз. Он разбился, когда вы создали файл базы данных, который сохраняется во всех сценариях сценария.

Смежные вопросы