RubyonRails |如何在有三个外键的数据库表中插入新行



我使用的是Ruby 2.6.3

我有四张桌子:

表1:交易(id,title(

表2:跳闸(id,name(

表3:TripBreakdown(id,name(

表4:TripTransaction(id,transaction_id,trip_id,trip_breakdown_id(

每个事务可以属于一个行程和一个行程细分。一个Trip有许多事务,一个TripBreakdown有很多事务因此,每个事务都属于零个或多个Trip和TripBreakdown。

为此,我创建了表#4来存储transaction_id、trip_id和trip_breakdown_id

我想创建TripTransaction表,以便(transaction_id、trip_id、trip_breakdown_id(都是外键。

这就是Model类的样子:

class Transaction < ApplicationRecord
belongs_to :trip_transaction, optional: true
end
class Trip < ApplicationRecord
has_many :trip_transactions, class_name: "TripTransaction", foreign_key: "trip_transaction_id"
end
class TripBreakdown < ApplicationRecord
has_many :trip_transactions, class_name: "TripTransaction", foreign_key: "trip_transaction_id"
end
class TripTransaction < ApplicationRecord
belongs_to :transactions, class_name: "Transaction", foreign_key: "transaction_id"
belongs_to :trips,    class_name: "Trip", foreign_key: "trip_id"
belongs_to :trip_breakdowns,    class_name: "TripBreakdown", foreign_key: "trip_breakdown_id"
end

问题:1( 我不确定我的Model类是否正确?

2( 如何创建新的TripTransaction对象,用三个外键连接它并将其插入数据库?

如果我有一个外键,文档上说我可以做@book = @author.books.create(published_at: Time.now)之类的事情,但在我的情况下,我该怎么做呢?感谢

答案1:您不需要联接表(trip_transactions(,因为事务有一个行程和一个行程细分。您的表事务将具有列trip_id和trip_breakdown_id。若它们可以为零,则在关系中设置optional::true。

您可以简化为:

class Transaction < ApplicationRecord
belongs_to :trip, optional: :true
belongs_to :trip_breakdown, optional: :true
end
class Trip < ApplicationRecord
has_many :transactions
end
class TripBreakdown < ApplicationRecord
has_many :transactions
end

答案2:可以通过多种方式完成,具体取决于您创建记录的方式。给你一个想法的例子是:

@new_transaction = @trip.transactions.new
@new_transaction.trip_breakdown_id = @trip_breakdown.id
@new_transaction.save

@Catmal拥有正确的模型。我会将通用事务重命名为更具体的TripTransaction,并匹配其他相关的类名。

创作可以通过多种方式进行。这些都假设您已经拥有Trip和TripBreakdown对象。这些基本上都做着相同的事情,但也有细微的区别。

# Via Transaction.create!
transaction = Transaction.create!(
trip: trip,
trip_breakdown: trip_transaction
)
# Via Trip's transaction association.
transaction = trip.transactions.create!(
trip_breakdown: trip_transaction
)
# Via TripBreakdown's transaction association.
transaction = trip_breakdown.transactions.create!(
trip: trip
)

他们将创建一个与Trip和TripBreakdown关联的Transaction对象。使用create的!版本意味着如果出现问题,它们将引发异常,而不是静默地返回nil。

使用关联的优点是缓存的关联将被更新。例如,如果要使用Transaction.create!,则可能会导致缓存过期。

# Load the Trip's transactions into memory
p trip.transactions
transaction = Transaction.create!(
trip: trip,
trip_breakdown: trip_transaction
)
# The Trip's transactions were cached. This will not include
# the new transaction.
p trip.transactions
# Now the new transaction is seen.
p trip.transactions.reload

如果您改为通过关联创建,则缓存的关联将被更新。

# Load the Trip's transactions into memory
p trip.transactions
# Create an associated Transaction and update the association.
trip.transactions.create!(
trip_breakdown: trip_transaction
)
# This will include the new Transaction.
p trip.transactions

有关详细信息,请参阅ActiveRecord::Associations::ClassMethods。