Что делать, когда find не находит записей в Ruby on Rails - PullRequest
0 голосов
/ 21 сентября 2009

Я пытаюсь выполнить нетипичную библиотеку, изучая языковое приложение. Я смог создать Книги, Люди и BookCheckOuts. У меня неплохо складываются отношения, но у меня возникают проблемы с тем, как обдумать, как обращаться с книгами, которые никогда не проверялись.

Я создал два свойства в своем классе книг CheckedOut (возвращает логическое значение) и LastCheckedOutTo (возвращает человека). Я в значительной степени в мире с CheckedOut и уверен, что использую правильный механизм RoR для определения, если книга в настоящий момент извлечена, и возврата логического значения в любом случае. Я не настолько уверен в LastCheckedOutTo, как моя реализация выглядит как клудж.

Правильно ли я поступаю? Есть ли лучший способ?

Книжный класс в полном объеме

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 ]

4 голосов
/ 21 сентября 2009

Возможно:

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 голос
/ 21 сентября 2009

Есть много способов сделать это. Вот несколько идей:

Вы можете добавить заказ и еще 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 или что-то?

0 голосов
/ 23 сентября 2009

Это может быть излишним для этого конкретного примера, но в качестве альтернативы вы можете захотеть изучить возможность реализации конечного автомата , т.е. aasm .

0 голосов
/ 21 сентября 2009
  1. Относительно def checked_out я бы переименуйте его в checked_out?, так как есть неписанное (или может быть написано) рубин конвенции что нибудь метод возвращает true или падает в конечном итоге с вопросительным знаком.
  2. Второй метод довольно хорошо, но это не будет хорошо для тяжелых веб-сайты. Я бы предложил денормализировать эта часть и добавление last_checked_out_to_id атрибут для таблица книг и обновление его после каждый процесс проверки. Другой путь было бы book_check_outs.last.person для существующий человек и book_check_outs.people.build для нового.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...