通过RJS传递实例变量?

时间:2010-06-06 15:38:38

标签: ruby-on-rails ajax

嘿,伙计们这里是我的代码(大致):

books.html.erb

<% @books.each do |book| %>
    <% @bookid = book.id %>
    <div id="enter_stuff">
    <%= render "input", :bookid => @bookid  %>
    </div>
<%end%>

_input.html.erb

<% @book = Book.find_by_id(@bookid) %>

<strong>your book is: <%=h @book.name %></strong>

create.rjs

page.replace_html :enter_stuff, :partial => 'input', :object => @bookid

这里的问题是只有create.js似乎不起作用(但是,如果不是传递我传递的部分“......”它确实有效,所以我知道它在部分中有实例变量没有被重置。任何想法?)

所以最后一个问题是,如何通过create.rjs文件将实例变量传递给partial?

P.S。我知道我会有重复的div ID,但我现在并不担心。

最佳, 埃利奥特

1 个答案:

答案 0 :(得分:1)

以您的方式将变量传递给部分应该可以正常工作。您尚未显示控制器代码的外观,但我猜您尚未在控制器的@bookid方法中定义create。该方法应如下所示:

# books_controller.rb
def create
  @book = Book.create(params[:book])
  @bookid = @book.id
end

然而,虽然这个解决方案可能会解决您当前的问题,但还有一些进一步改进的空间。您的代码还有一些其他问题:

  • 通过将book id而不是Book实例传递给partial,您需要再次从数据库中获取每本书,即使所有书籍都在@books数组中可用。通过重新设计部分使用Book而不是ID,可以避免不必要的数据库访问。

  • 在部分内部,您使用实例变量而不是传递给部分的对象来引用书籍(ID)。虽然这很有效,但由于实例变量与控制器和周围的视图代码共享,因此它不太健壮。如果在@bookid引用其他内容的其他上下文中重用partial,则可能以变量名冲突结束。如果您将部分重命名为_book.html.erb,则只需使用render :partial => @book即可呈现图书 - 假设您已将图书定义为资源,Rails将自动确定要使用的正确部分,并使该书在部分内可用作变量book

  • 哦,顺便说一句,马上摆脱身份证复制。你知道这个问题真是太棒了,但这会让你以后遇到麻烦。通过在所有书籍周围放置一个包装器div,您将能够摆脱重复的ID并仍然保持Ajax更新正常工作。

通过上述改进,代码看起来像这样:

应用程序/控制器/ books_controller.rb

class BooksController < ApplicationController
  def index
    @books = Book.find(:all)
  end

  def create
    @book = Book.create(params[:book])
  end
end

应用程序/视图/书籍/ index.html.erb

<div id="books">
  <%= render :partial => @books %>
</div>

<% remote_form_for Book.new do |f| %>
  New book title: <%= f.text_field :name %>
<% end %>

应用程序/视图/书籍/ _book.html.erb

<% div_for book do %>
  <strong>Your book is: <%= h(book.name) %></strong>
<% end %>

create.js.rjs

page.insert_html :bottom, 'books', :partial => @book