[英]Rails - Model Associations - User and Product - Custom methods
我正在创建一个具有两个主要模型的应用程序:用户和产品。 用户可以拥有许多产品作为所有者,也可以拥有许多产品作为借款人。 产品只有一个所有者,但可以有许多寻求者,包括借款人。 我直接将它们与拥有财产相关联,但是对于借款财产,我创建了一个交易模型。 这三个看起来像这样:
app / models / transaction.rb
class Transaction
# has a seeker_id:integer, a product_id:integer and a current:boolean
before_save :check_current
# Associations
belongs_to :seeker, class_name: "User", foreign_key: "seeker_id"
belongs_to :product
# Methods
def check_current
if !self.borrowing_date.nil? && self.return_date.nil?
self.current = true
end
end
end
一种产品有很多transactions
,但当时只能由一个seeker
借用。 当产品是借来的,本次交易有borrowing_date
是not nil
和return_date
是nil
。 然后, check_current
方法将此transaction
的current
布尔值从false
切换为true
。 该当前transaction
的seeker
被指定为borrower
。
app / models / user.rb
class User
.
.
.
has_many :owned_products, class_name: "Product", foreign_key: "owner_id", dependent: :destroy
has_many :transactions, foreign_key: "seeker_id", dependend: :destroy
has_many :requested_products, through: :transactions, source: :product
has_many :active_transactions, -> { where current: true },
class_name: 'Transaction',
foreign_key: "seeker_id",
dependent: :destroy
has_many :borrowed_products, through: :active_transactions,
source: :product
def requesting?(product)
self.transactions.find_by(product_id: product.id)
end
def request!(product)
self.transactions.create!(product_id: product.id)
end
def borrowing?(product)
self.transactions.find_by(product_id: product.id, current: true)
end
def borrowed_products
self.transactions.where(current: :true).product
end
end
app / models / products.rb
class Product
.
.
.
belongs_to :owner, class_name: "User", foreign_key: "owner_id"
has_many :transactions, dependent: :destroy
has_many :seekers, through: :transactions,
source: :seeker
def borrowed?
self.transactions.find_by(current: true)
end
def borrower
self.transactions.find_by(current: true).seeker
end
end
当我测试一些代码时,其中五个测试失败,类型相同,并且我不明白为什么:
describe User do
before { @user = User.new(name: "Utilisateur de test",
email: "test@utilisateur.com",
password: "motdepasse",
password_confirmation: "motdepasse") }
subject { @user }
describe "requested product associations" do
let(:lender) { FactoryGirl.create(:user) }
let(:product) { FactoryGirl.create(:product, owner: lender) }
before do
@user.save
@user.request!(product)
end
it { should be_requesting(product) }
its(:requested_products) { should include(product) } # FAIL
describe "when product is borrowed" do
before do
transaction = Transaction.find_by(product: product)
transaction.update_attributes(borrowing_date: 1.day.ago)
transaction.save
end
it { should be_borrowing(product) }
its(:requested_products) { should_not include(product) } # FAIL
its(:borrowed_products) { should include(product) } # FAIL
describe "then returned" do
before do
transaction = Transaction.find_by(product: product)
transaction.update_attributes(return_date: 1.hour.ago)
end
it { should_not be_borrowing(product) }
its(:requested_products) { should_not include(product) } # FAIL
its(:borrowed_products) { should_not include(product) } # FAIL
end
end
end
end
这是错误消息:
1) User requested product associations requested_products
Failure/Error: its(:requested_products) { should include(product) }
ActiveRecord::StatementInvalid:
SQLite3::SQLException: ambiguous column name: created_at: SELECT 1 AS one FROM "products" INNER JOIN "transactions" ON "products"."id" = "transactions"."product_id" WHERE "transactions"."seeker_id" = ? AND "products"."id" = 1 ORDER BY created_at DESC LIMIT 1
# ./spec/models/user_spec.rb:174:in `block (3 levels) in <top (required)>'
2) User requested product associations when product has been borrowed borrowed_products
Failure/Error: its(:borrowed_products) { should include(product) }
ActiveRecord::StatementInvalid:
SQLite3::SQLException: ambiguous column name: created_at: SELECT 1 AS one FROM "products" INNER JOIN "transactions" ON "products"."id" = "transactions"."product_id" WHERE "transactions"."seeker_id" = ? AND "transactions"."current" = 't' AND "products"."id" = 1 ORDER BY created_at DESC LIMIT 1
# ./spec/models/user_spec.rb:185:in `block (4 levels) in <top (required)>'
3) User requested product associations when product has been borrowed requested_products
Failure/Error: its(:requested_products) { should_not include(product) }
ActiveRecord::StatementInvalid:
SQLite3::SQLException: ambiguous column name: created_at: SELECT 1 AS one FROM "products" INNER JOIN "transactions" ON "products"."id" = "transactions"."product_id" WHERE "transactions"."seeker_id" = ? AND "products"."id" = 1 ORDER BY created_at DESC LIMIT 1
# ./spec/models/user_spec.rb:184:in `block (4 levels) in <top (required)>'
4) User requested product associations when product has been borrowed then returned requested_products
Failure/Error: its(:requested_products) { should_not include(product) }
ActiveRecord::StatementInvalid:
SQLite3::SQLException: ambiguous column name: created_at: SELECT 1 AS one FROM "products" INNER JOIN "transactions" ON "products"."id" = "transactions"."product_id" WHERE "transactions"."seeker_id" = ? AND "products"."id" = 1 ORDER BY created_at DESC LIMIT 1
# ./spec/models/user_spec.rb:195:in `block (5 levels) in <top (required)>'
5) User requested product associations when product has been borrowed then returned borrowed_products
Failure/Error: its(:borrowed_products) { should_not include(product) }
ActiveRecord::StatementInvalid:
SQLite3::SQLException: ambiguous column name: created_at: SELECT 1 AS one FROM "products" INNER JOIN "transactions" ON "products"."id" = "transactions"."product_id" WHERE "transactions"."seeker_id" = ? AND "transactions"."current" = 't' AND "products"."id" = 1 ORDER BY created_at DESC LIMIT 1
# ./spec/models/user_spec.rb:196:in `block (5 levels) in <top (required)>'
但是,当我在Rails控制台中手动运行一些测试时, user.borrowed_products
和user.requested_products
正常工作。 奇怪的 ???
对于第一次失败的测试
def borrowed_products
self.transactions.where(current: :true).product
end
上面的方法检查电流:true。 我看不到您在交易设置中设置属性。
before do
transaction = Transaction.find_by(product: product)
transaction.update_attributes(borrowing_date: 1.day.ago) #Why are you setting borrowing date. How is borrowing date and current related?
transaction.save
end
对于第二次测试。
request_products关联是通过交易建立的。 您没有设置交易。 是在您的工厂完成的吗?
好的,我找到了! Yippee-ki-yay!
错误消息告诉我created_at
列不明确。 但为什么 ? 因为created_at
列和关联的模型一样多! 因此,它与此有关。 但是created_at
在我的代码中出现了什么地方?
我检查了我的app / models / transaction.rb ,我的app / models / user.rb和我的app / models / product.rb ,在最后一个模型中,我找到了这一行:
default_scope -> { order('created_at DESC') }
我改为那,只是尝试:
default_scope -> { order('name DESC') }
而且一切都很好!
但是现在,如果我想通过created_at
对其进行范围划分,我不知道如何做到这一点:-p
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.