当find在Ruby on Rails中找不到任何记录时该怎么办

时间:2009-09-21 04:05:32

标签: ruby-on-rails activerecord

我正在努力完成非典型的图书馆学习语言应用程序。我已经能够创建Books,People和BookCheckOuts。我的关系工作得非常好,但是在处理从未检查过的书籍方面存在问题。

我在我的书类CheckedOut(返回一个布尔值)和LastCheckedOutTo(返回一个人)上创建了两个属性。我对CheckedOut很满意,并且确信我正在使用正确的RoR机制来确定一本书目前是否已经签出并在任何一种情况下都返回一个布尔值。我对LastCheckedOutTo没有那么自信,因为我的实现看起来像是一个kludge。

我是否正确地解决了这个问题?还有更好的方法吗?

Bookful in Entirety

class Book < ActiveRecord::Base
  has_many :book_check_outs
  has_many :people, :through => :book_check_outs

  def checked_out
    if (book_check_outs.find(:first, :conditions => "return_date is null"))
      true
    else
      false
    end
  end

  def last_checked_out_to
    if (book_check_outs.count > 0)
      book_check_outs.find(:first,
        :order => "out_date desc").person
    else
      Person.new()
    end
  end
end

4 个答案:

答案 0 :(得分:4)

也许:

class Book < ActiveRecord::Base
  has_many :book_loans
  has_many :borrowers, :class_name => 'Person', :through => :book_loans

  def loaned?
    book_loans.exists?(:return_date => nil)
  end

  # I would be reluctant to return a new Person object
  #  just because it was not checked out by anyone, instead you could return nil
  #  OR exception out.   
  def current_borrower
    book_loans.first(:order => "out_date desc").person 
  end
end

# you can use a helper to keep your presentation clean 
module BookHelper 
  def borrower_name(book)
     if borrower = book.borrower
       borrower.name 
     else 
       "not checked out" 
     end
  end
end 

答案 1 :(得分:1)

实际上有很多方法可以做到这一点。以下是一些想法:

您可以添加订单和其他has_many,因为您真的非常关心返回日期:

  has_many :book_check_outs, :order => "out_date asc"
  has_many :current_book_check_outs, :conditions=>'return_date is null'

然后你得到:

def checked_out?
  current_book_check_outs.any?
end

def last_checked_out_to
  if (book_check_outs.count > 0)
     book_check_outs.last.person
  else
      Person.new()
  end
end

但我对如何使用last_checked_out_to感到有些困惑。如果它没有最后一个人,我想我更愿意返回nil

您应该查看命名范围,因为这些有助于模块化地构建这些动态查询。他们在这里工作得很好。

虽然你在这段代码中没有使用人(人?),但我会稍微重复术语,以便更好地阅读。 book.persons对于它告诉我们的内容似乎并不合适。图书馆员称之为什么? book.checker_outters还是什么?

答案 2 :(得分:0)

  1. 关于我def checked_out 从那以后将其重命名为checked_out? 有不成文(或许是 写的)ruby约定任何 返回true或fall的方法 结束了问号。
  2. 第二种方法非常好, 但是对于沉重的dute来说它不会很好 网站。我建议非规范化 这部分并加入 last_checked_out_to_id属性为 书籍表并在之后更新 每个结账过程。另一种方式 将会 book_check_outs.last.person 现有的人和 新book_check_outs.people.build

答案 3 :(得分:0)

对于这个特定的例子来说可能有点过头了但是你可能想要探索实现state machine的选项,即aasm