【问题标题】:Rails - Model Associations - User and Product - Custom methodsRails - 模型关联 - 用户和产品 - 自定义方法
【发布时间】:2013-06-11 14:15:56
【问题描述】:

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

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 方法将transactioncurrent 布尔值从false 切换到true。当前transactionseeker 被指定为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_productsuser.requested_products 工作得很好。奇怪???

【问题讨论】:

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


    【解决方案1】:

    对于第一次失败的测试

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

    上述方法检查 current: 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 关联是通过交易建立的。您没有设置交易。是在你们工厂做的吗?

    【讨论】:

    • 对于第一个测试,我正在搜索current: true 的每笔交易并询问相关产品。在第二个测试中,我使用了我在 app/models/user.rb 中指定的 request! 方法。那是before { @user.request!(product) } 行,等于@user.transactions.create!(product_id: product.id)
    • 尝试在测试开始时检查所有事务。在测试开头添加p Transaction.all
    • 好的,结果如下:#&lt;ActiveRecord::Relation [#&lt;Transaction id: 1, product_id: "1", seeker_id: "91", borrowing_date: nil, return_date: nil, current: false, created_at: "2013-06-12 05:04:09", updated_at: "2013-06-12 05:04:09"&gt;]&gt;
    • 我看到你在设置借阅日期。但它为零,因此电流为零
    • 好的,这是什么意思?
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-02
      • 1970-01-01
      • 1970-01-01
      • 2012-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多