Rails - 模型关联 - 用户和产品 - 自定义方法

时间:2013-06-11 14:15:57

标签: ruby-on-rails ruby-on-rails-4 model-associations

我正在创建一个包含两个主要模型的应用:用户和产品。用户可以拥有许多产品作为所有者,许多产品作为借款人。产品只有一个所有者,但可以有很多寻求者,包括借款人。我直接将它们与拥有属性相关联,但是对于借用属性,我创建了一个Transaction模型。这三个看起来像这样:

应用/模型/ 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_datenot nilreturn_datenil。然后check_current方法将此current的{​​{1}}布尔值从transaction切换为false。当前true的{​​{1}}被指定为seeker

应用/模型/ user.rb

transaction

应用/模型/ products.rb

borrower

当我测试我的一些代码时,其中五个测试失败,类型相同,我不明白为什么:

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

以下是错误消息:

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

但是当我在rails控制台中手动运行某些测试时,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)>' 工作正常。很奇怪???

2 个答案:

答案 0 :(得分:0)

第一次失败的测试

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

进行第二次测试。

requested_products关联是通过交易建立的。您没有设置交易。它是在你的工厂完成的吗?

答案 1 :(得分:0)

好的,我找到了! 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