简体   繁体   English

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

[英]Rails - Model Associations - User and Product - Custom methods

I'm creating an app with two main models : User and Product. 我正在创建一个具有两个主要模型的应用程序:用户和产品。 User can have many products as an owner, and many products as a borrower. 用户可以拥有许多产品作为所有者,也可以拥有许多产品作为借款人。 Product have only one owner, but can have many seekers, including a borrower. 产品只有一个所有者,但可以有许多寻求者,包括借款人。 I associated them directly for the owning property, but for the borrowing property, I created a Transaction model. 我直接将它们与拥有财产相关联,但是对于借款财产,我创建了一个交易模型。 The three look like this : 这三个看起来像这样:

app/models/transaction.rb 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

A product has many transactions , but it can be borrowed by only one seeker at the time. 一种产品有很多transactions ,但当时只能由一个seeker借用。 When the product is borrowed, the transaction has a borrowing_date that is not nil , and a return_date that is nil . 当产品是借来的,本次交易有borrowing_datenot nilreturn_datenil Then the check_current method toggles the current boolean of this transaction from false to true . 然后, check_current方法将此transactioncurrent布尔值从false切换为true The seeker of that current transaction is specified as a borrower . 该当前transactionseeker被指定为borrower

app/models/user.rb 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 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

When I testing some of my code, five of the tests fail, the same type, and I don't understand why : 当我测试一些代码时,其中五个测试失败,类型相同,并且我不明白为什么:

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

Here are the error messages : 这是错误消息:

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)>'

But when I run some tests manually in the rails console, the user.borrowed_products and user.requested_products work just fine. 但是,当我在Rails控制台中手动运行一些测试时, user.borrowed_productsuser.requested_products正常工作。 Weird ??? 奇怪的 ???

For the first failing test 对于第一次失败的测试

def borrowed_products
      self.transactions.where(current: :true).product
 end

The above method checks for current: true. 上面的方法检查电流:true。 I don't see you setting the attribute in your transaction setup. 我看不到您在交易设置中设置属性。

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

For the Second test. 对于第二次测试。

requested_products association is established through transactions. request_products关联是通过交易建立的。 You are not setting up a transaction. 您没有设置交易。 Is it done in your factory? 是在您的工厂完成的吗?

OK I found ! 好的,我找到了! Yippee-ki-yay ! Yippee-ki-yay!

The error messages were telling me the created_at column was ambiguous. 错误消息告诉我created_at列不明确。 But why ? 但为什么 ? Because there are as much created_at column as there are associated models ! 因为created_at列和关联的模型一样多! So it had something to do with it. 因此,它与此有关。 But where the created_at appeared in my code ? 但是created_at在我的代码中出现了什么地方?

I checked my app/models/transaction.rb , my app/models/user.rb and my app/models/product.rb , and in this last model, I found the line : 我检查了我的app / models / transaction.rb ,我的app / models / user.rb和我的app / models / product.rb ,在最后一个模型中,我找到了这一行:

default_scope -> { order('created_at DESC') }

That I changed to that, just to try : 我改为那,只是尝试:

default_scope -> { order('name DESC') }

And everything went just fine ! 而且一切都很好!

But now, if I want to scope it by created_at , I don't know how to do it :-p 但是现在,如果我想通过created_at对其进行范围划分,我不知道如何做到这一点:-p

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM