ruby 在Rails中为数据库设定种子时出错,属性上有错误,我没有使用

ryevplcw  于 2022-12-12  发布在  Ruby
关注(0)|答案(1)|浏览(131)

我正在Odin Project中的flight-booker项目上工作。我正在尝试将往返10个城市的60天航班作为数据库的种子。当我将数据库作为种子时,收到以下错误:
已创建数据库'flight_booker_development'已创建数据库'flight_booker_test' #机场:0x 00007 f003 f0 c6 f20轨道已中止!活动模型::缺少属性错误:无法写入未知属性flight_id

raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{name}`"
      ^^^^^ /home/stuart/repos/flight-booker/db/seeds.rb:23:in `block (4 levels) in <main>'

/home/stuart/repos/flight-booker/db/seeds.rb:22:位于“/home/stuart/repos/flight-booker/db/seeds”中的times' /home/stuart/repos/flight-booker/db/seeds.rb:22:in区块(3层)中。rb:21:位于“/home/stuart/repos/flight-booker/db/seeds”中的times' /home/stuart/repos/flight-booker/db/seeds.rb:21:in区块(2层)中。rb:15:位于block in <main>' /home/stuart/repos/flight-booker/db/seeds.rb:14:in“中任务:TOP =〉db:reset =〉db:setup =〉db:seed(通过使用--trace运行任务查看完整跟踪)
问题似乎是它试图写一个我没有使用的属性。下面是我的seeds.rb文件:

require "faker"

airports = %w[LAX DFW NYC DEN BOS MIA HOU PIT POR MIN]

airports.each { |city_code| Airport.create!(city_code: city_code) }

Airport.all.each do |departure|
  Airport.all.each do |arrival|
    next if departure == arrival
    puts departure
    duration = rand(100..300)
    flight_number = rand(1000..1999)
    frequency = rand(3..5)
    60.times do
      frequency.times do
        Flight.create!(
          origin_id: departure,
          destination_id: arrival,
          duration: duration,
          flight_number: flight_number,
          departure_time: Faker::Time.forward(days: 60, period: :all)
        )
      end
    end
  end
end

我试图使用flight_id来保存航班号,但是我改变了它,因为我意识到我的bookings表中有一个flight_id列。不过我现在没有对bookings表做任何事情。我以前也遇到过同样的错误,然后我执行了迁移,删除了flight_id并将_flight number添加到flights表中。下面是当前的schema.rb

ActiveRecord::Schema[7.0].define(version: 2022_12_09_210422) do
  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "airports", force: :cascade do |t|
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "city_code"
  end

  create_table "bookings", force: :cascade do |t|
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.bigint "user_id", null: false
    t.bigint "flight_id", null: false
    t.index ["flight_id"], name: "index_bookings_on_flight_id"
    t.index ["user_id"], name: "index_bookings_on_user_id"
  end

  create_table "flights", force: :cascade do |t|
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "destination"
    t.string "origin"
    t.datetime "departure_time"
    t.integer "duration"
    t.bigint "destination_id", null: false
    t.bigint "origin_id", null: false
    t.integer "flight_number"
    t.index ["destination_id"], name: "index_flights_on_destination_id"
    t.index ["origin_id"], name: "index_flights_on_origin_id"
  end

  create_table "users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

  add_foreign_key "bookings", "flights"
  add_foreign_key "bookings", "users"
  add_foreign_key "flights", "airports", column: "destination_id"
  add_foreign_key "flights", "airports", column: "origin_id"
end

这里的模型/flight.rb文件:

class Flight < ApplicationRecord
  belongs_to :booking, foreign_key: "flight_id"
  has_one :origin_id, class_name: "Airport"
  has_one :destination_id, class_name: "Airport"
  validates :departure_time, presence: true
  validates :duration, presence: true
  validates :flight_number, presence: true
end

这是flight_id出现的唯一地方,但是如果我删除这行代码,我仍然会得到同样的错误。在错误中,它引用了种子文件的第23行,这是Flight.create操作的开始。它以前确实试图创建flight_id,但是已经被更改为flight_number,我保存了文件,并重新启动了计算机。
下面是flights_controller.rb文件:

class FlightsController < ApplicationController
  before_action :set_flight
  def index
    @flight = Flight.all
  end

  def new
    @flight = Flight.new
  end

  def create
    @flight = Flight.new(flight_params)
  end

  private

  def set_flight
    @flight = Flight.find(params[:id])
  end

  def flight_params
    params.require(:flight).permit(
      :airport,
      :flight_number,
      :origin,
      :origin_id,
      :destination_id,
      :destination,
      :duration,
      :departure_time,
      :arrival_time
    )
  end
end

我以前使用flight_id作为允许的参数,但现在已更改为flight_number。
所以,我有点不知道下一步该怎么做。如果能提供帮助,我将不胜感激。我很乐意提供任何你认为相关的额外信息。谢谢。
编辑并补充说,我尝试从Rails控制台创建一个表条目,并在IRB中得到了同样的错误。
创建航班!(出发时间:“2022年12月25日11:11:11 - 0700”,时长:200,航班号:1599,起始标识:机场。名字,目的地标识:机场。最后一个)机场负载(0.2ms)选择“机场”。* FROM“机场”ORDER BY“机场”。“id”ASC LIMIT $1 “LIMIT”,1机场负载(0.1ms)选择“机场”。* FROM“机场”ORDER BY“机场”。“id”DESC LIMIT $1 “LIMIT”,1
/home/stuart/.rbenv/版本/3.1.2/lib/ruby/gems/3.1.0/gems/活动模型-7.0.4/lib/活动模型/属性.rb:211:在with_value_from_database': can't write unknown attribute航班标识中'(活动模型::缺少属性错误)

raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{name}`"                                          

      ^^^^^                                                                                                                                                                                               irb(main):002:0>
r6vfmomb

r6vfmomb1#

问题是您已经定义了与foreign_key: "flight_id"的关联

class Flight < ApplicationRecord
  belongs_to :booking, foreign_key: "flight_id"
end

此选项记录为:
指定用于存储关联对象类型的列
不用说,使用引用bookingsflights.flight_id列是错误的。
让我们擦除这个失败的尝试,然后重试。将您的工作隐藏在GIT中,然后回滚,让我们正确地设置这些模型。
要设置航班、机场和航空公司之间的关联,应使用三个表,并按如下方式关联它们:

# rails g model airline name
class Airline < ApplicationRecord
  has_many :flights
end

# rails g model airport name iata_code
class Airport < ApplicationRecord
  has_many :flights_as_origin,
    class_name: 'Flight',
    foreign_key: :origin_id
  has_many :flights_as_destination,
    class_name: 'Flight',
    foreign_key: :destination_id
end

# rails g model flight flight_number:string airline:references origin:references destination:references
class Flight < ApplicationRecord
  belongs_to :airline
  # These should be belongs_to assocations
  belongs_to :origin, class_name: 'Airport'
  belongs_to :destination, class_name: 'Airport'
end

这是所有乘客共有的数据。当乘客订票时,您不需要修改这里的任何内容。当创建flights表时,您需要显式地告诉Rails destination_idorigin_id应该指向airports表:

class CreateFlights < ActiveRecord::Migration[7.0]
  def change
    create_table :flights do |t|
      # ...
      t.references :origin, null: false, foreign_key: { to_table: :airports }
      t.references :destination, null: false, foreign_key: { to_table: :airports }
      # ...
    end
  end
end

要对乘客、航班和预订之间的关联进行建模,您实际上需要一个带有连接表的多对多关联:

# rails g model ticket passenger_name:string flight:references seat:string
class Ticket < ApplicationRecord
  belongs_to :flight
end 

class Booking < ApplicationRecord
  belongs_to :user
  has_many :tickets
  has_many :flights, through: :tickets
end

class Flight < ApplicationRecord
  # ...
  has_many :tickets
  has_many :bookings, through: :tickets
end

在这里,您使用tickets表将每一项存储在一个itenary中,以便实际上可以对多段旅程和每次预订多名乘客等内容进行建模。

相关问题