0

我是 ruby​​ on rails 的新手,并且打算使用应用程序中已经存在的一些代码。

代码如下(书籍):-

def index
        @books = Book
        @books = @books.select("books.*, 
                                (select count(*) from book_issues where books.id = book_issues.book_id and book_issues.return_date is null) as issued_cnt,
                                (select count(*) from book_holds where books.id = book_holds.book_id) as hold_cnt")
         @books = @books.joins("inner join book_issues on book_issues.book_id = books.id")
         @books = @books.where('book_issues.return_date is null')
         @books = @books.group('books.id')
        @books.all

        respond_to do |format|
            format.html # index.html.erb
            format.json { render json: @books }
        end
    end

我发现这有点难以理解。为什么要使用此代码以及为什么不使用以下代码:-

def index
  if params[:book_id]
    @book = Book.find(:all,
                        :conditions => ["book_id = ? ", params[:book_id] ],
                        :order      => "action_date ASC")    
  end
end

有人可以帮我解决这个问题。

4

3 回答 3

3

这里要解决的主要问题是“生成当前未签出的书籍数组并将其传递给模板引擎以在页面上呈现”。该 SQL 代码正在处理第一部分。不幸的是,您必须加入 book_issues 以查看是否有任何可用的副本,但现在您想在 Book 上定义一个方法,:available?当至少有一个副本未签出然后使用时返回 true在你的控制器中。

作为进一步的调整,我想在书籍记录上有一个数据库列,让我知道它们是否可用于结帐而不加入book_issues(BooksController#Index 听起来它会被调用很多次,而你不希望它破坏数据库)。这可能意味着更新您的图书结帐逻辑以调整主图书记录。

如果它看起来像这样,代码会更快乐:

#books controller
def index
  @books = Book.available

  respond_to ... # continue as before
end

# book model
scope :available, where(copies_available: true)

# book_issue model
belongs_to :book
after_save :update_parent_availability

def available?
  return_date.nil?
end

def update_parent_availability
  book.copies_available = book.issues.select(&:available?).any?
  book.save if book.changed?
end

:update_parent_availability操作可能受制于竞争条件。您可能应该将其分解到帮助书可用性管理类中并在事务中运行它。

于 2013-06-05T20:14:14.267 回答
3

阅读有关 Rails 中的关联和范围的手册和教程。之后,您应该将代码重写为如下所示:

#model

class Book < ActiveRecord::Base
  # Association for BookIssue, the BookIssue model should have a 'belongs_to :book'
  has_one :book_issue
  # Association for BookHold, the BookHold model should have a 'belongs_to :book'
  has_one :book_hold
  # Scope to get not returned books, it joins all issues that don't have a return date.
  # All book with a return date will be ignored.
  scope :not_returned, joins(:book_issue).where(:book_issues => { return_date: nil } )

end

#controller

def index
  # Use the scope mentioned in the model, to get all not returned books.
  @books = Book.not_returned.all

  respond_to do |format|
    format.html # index.html.erb
    format.json { render json: @books }
  end
end
于 2013-06-05T20:10:13.393 回答
1

我想你会发现Rails 指南的 ActiveRecord 部分很有帮助。我建议彻底阅读ActiveRecord 查询文档。密切注意示例的一般风格。MVC(模型-视图-控制器)模式最强大的方面之一是您可以在模型中构建非常简单的接口来完成“繁重的工作”,而不是用真正不属于那里的逻辑使控制器混乱.

于 2013-06-05T20:01:27.867 回答