将数据库模型转换为 Ruby On Rails 上的模型
Posted
技术标签:
【中文标题】将数据库模型转换为 Ruby On Rails 上的模型【英文标题】:Translating Database Models to Models on Ruby On Rails 【发布时间】:2018-05-27 23:17:03 【问题描述】:我在学校通过购买/转售平台项目开始使用 Ruby On Rails。当我尝试从关系模型中翻译模型时,我遇到了问题。
首先,我已经为我的数据库建模。这是简化的实体关系模型:
然后我将它翻译成关系模型:
最后,我在 Ruby On Rails 中实现了它。
我已经实现了一个模型客户端:
class Client < ApplicationRecord
attr_accessor :name
validates :name, :presence => true
has_many :purchasings, :dependent => :destroy
has_many :sellers, :through => :purchasings
has_many :articles, :through => :purchasings
end
我已经实现了一个模型卖方:
class Seller < ApplicationRecord
attr_accessor :name
validates :name, :presence => true
has_many :purchasings, :dependent => :destroy
has_many :sellers, :through => :purchasings
has_many :articles, :through => :purchasings
end
我已经实现了一篇示范文章
class Article < ApplicationRecord
attr_accessor :quantity
validates :quantity, :presence => true
has_one :purchasing, :dependent => :destroy
has_one :client, :through => :purchasings
has_one :seller, :through => :purchasings
end
我已经实现了一个模型采购:
class Purchasing < ApplicationRecord
attr_accessor :client_id, :seller_id, :article_id
belongs_to :client, :class_name => "Client"
belongs_to :seller, :class_name => "Seller"
belongs_to :article, :class_name => "Article"
validates :client_id, :presence => true
validates :seller_id, :presence => true
validates :article_id, :presence => true
end
我已经修改了采购数据库迁移:
class CreatePurchasing < ActiveRecord::Migration[5.1]
def change
[...]
add_index :purchasings, :client_id
add_index :purchasings, :seller_id
add_index :purchasings, :article_id
add_index :purchasings, [:client_id, :seller_id], :unique => true
end
def down
[...]
end
end
我知道这是不正确的,因为当我在 Rails 控制台上执行以下代码时:
cl1 = Client.create(:name => "John")
cl2 = Client.create(:name => "James")
sel1 = Seller.create(:nom => "Jack")
sel2 = Seller.create(:nom => "Jil")
a1 = Article.create(:quantity => 5)
p1 = Purchasing.new(:client => cl1, :client_id => cl1.id, :seller => sel1, :seller_id => sel1.id, :article => a1, :article_id => a1.id)
p1.save
p2 = Purchasing.new(:client => cl2, :client_id => cl2.id, :seller => sel1, :seller_id => sel1.id, :article => a1, :article_id => a1.id)
p2.save
p2.save
返回 true,而文章不能由同一个卖家出售并由两个不同的客户购买。
【问题讨论】:
有问题吗? 另外,删除 attr_accessors。他们没有做你认为他们做的事。 @SergioTulentsev 好吧,我的测试没有产生我期望的结果,所以我正在寻找一种解决方案,以便获得正确的行为(p2.save 返回 false,因为该文章已经被客户)。 @SergioTulentsev 你能更准确地了解 atr_accessors 吗?我的理解是 attr_accessors 相当于在Java中声明getter/setter? “等同于在 Java 中声明 getter/setter”——正确,但在这里会适得其反。您的模型中不需要它们。声明它们会覆盖活动记录生成的 getter/setter。因此,这些属性不会被持久化。 【参考方案1】:您在采购表的不正确列上添加索引。根据要求,article_id 和 Seller_id 最好不要重复。所以你实际上需要的是对seller_id 和article_id 列的唯一性约束。您可以通过在数据库层上的两列seller_id 和文章id 的组合上创建唯一索引来实现。您还应该在购买模型上添加应用层验证。
class Purchasing < ApplicationRecord
attr_accessor :client_id, :seller_id, :article_id
belongs_to :client, :class_name => "Client"
belongs_to :seller, :class_name => "Seller"
belongs_to :article, :class_name => "Article"
validates :client_id, :presence => true
validates :seller_id, :presence => true
validates :article_id, :presence => true
validates :article_id, uniqueness: scope: :seller_id
end
现在您还应该编写一个数据库迁移来为这两列添加唯一索引。
class AddUniquenessConstraintInPurshasing < ActiveRecord::Migration
def change
add_index :purchasings, [:article_id, :seller_id], :unique => true
end
结束
【讨论】:
感谢您的详细解答。validates :article_id, uniqueness: scope: :seller_id
解释了article_id 对于给定的seller_id 是唯一的这一事实。我理解对了吗?
满足同一个卖家不分商品数量不能销售同一个商品的需求。此验证不允许您在购买表中有任何重复的 article_id 和 Seller_id 对。所以我宁愿说一个卖家只能卖一次特定的物品。如果你的要求不同,你的设计也应该改变。希望对您有所帮助!
感谢您的回答。它澄清了一切。最后,我想我应该像你说的那样更新我的模型,它不是那么相关以上是关于将数据库模型转换为 Ruby On Rails 上的模型的主要内容,如果未能解决你的问题,请参考以下文章
将重复的SQL模型复制到Ruby on Rails postgresql模型中