0

我设法用我在 ruby​​-on-rails 中的自定义表单几乎一路走向幸福,但最后一步丢失了,由于常用词太多,无法在网上找到答案。

我相信我的问题的答案对于曾经做过 RoR 的人来说是微不足道的,但请注意,问题的呈现会有些复杂。

让我们看一个等价的问题!

架构:

  • publishers (id, name, address)

  • books (id, title, publisher_id, publishing_year, unit_price, qty)

  • sell_log (id, user_id, timestamp, book_id, qty, unit_price, comment)

自定义动作:

  • 名称:Sell(上下文:一本书)

  • 输入:qty, comment, (隐式输入:book.id, timestamp;派生输入:user_id, book.unit_price, book.qty

  • 结果:

    • 附加了 sell_log

    • 书籍数量减少

  • 可能的错误:

    • 数量是非正数或非整数。

    • 用户输入的数量大于可用数量(book.qty)

(仅供参考:这不是关于数据库设计的问题。)

因此,我们有一个自定义表单(隐藏的 book-id;qty,comment),我们希望将其实现为与“编辑”一本书( )类似的行为update。做了什么(几乎是一切):

--books_controller.rb:添加custom_qty_display列。

--books_helper.rb:

def custom_qty_display_column(record)
  record.qty.to_label + " ["
  link_to( "Sell..." \
            , { :controller => "books", :action => "sell_form", :id => record.id, :page => false } \
            , { :position => "replace", :inline => true, :class => "action" } \
          ) \
  + "]"
end

--views/books/sell_form.erb(仅关键细节)

<%
  form_remote_tag( \
    :url => { :controller => :books, :action => :sell, :id => params[:id] } \
  ) do
%>
...
<%= submit_tag 'Submit' %>
<%= link_to as_(:cancel), main_path_to_return, :class => 'cancel' %>
<% end %>
<div id="as_books-messages" class="messages-container" />

--books_controller.rb:

def sell
  errors = [] # We will collect error messages here
  # Checking parameters ...
  # Checking of available qty ...
  # If "errors" is still empty here, perform the action
  # Produce the output according to the above:
  if request.xhr?
    if errors.empty?
      # Q1: rendering of javascript which replaces the form with the modified row in the table.
    else
      # Q2: rendering of javascript which provides the "errors" for the user
    end
  else
    if errors.empty?
      index
    else
      # Q3: Redisplay the form and errors
    end
  end
end

现在的进展

当我单击图书列表条目中的“出售...”链接时,条目消失,出现自定义表单而不是它。在表单上,​​“取消”链接(和 [X] 按钮)完美运行;提交按钮起作用(输入正确时操作成功完成)。

不存在的是表格仍然存在。理论上,我应该在标有 和 的地方返回适当Q1Q2javascript Q3。我不想对事物进行逆向工程并手动编写 javascript,因为在框架升级时我将被迫重做这一步。我想以关于简单性和可维护性的最佳方式生成必要的 javascript。我现在相信我的概念还不错。

版本信息

  • JRuby 1.5.0
  • 宝石
    • 导轨 2.3.4
    • 主动记录 2.3.4
    • 主动支持 2.3.4

(如果还有什么需要请告诉我)

部分结果

# ...
if errors.empty?
  render :action => 'on_update.js'
else
  # ...
end
# ...
4

2 回答 2

1

应用程序使用的是哪个 Rails 版本?该应用程序使用什么 javascript 库?Book 和 SellLog 是 RESTful 资源吗?

它们是您不在link_to_remote帮助程序中使用并respond_to在控制器操作中阻止的原因吗?

在使用原型的 Rails 2.3 中,我这样做:

in controller:

def sell 
  # …
  # book / quantity / errors
  # …
  respond_to do |format|
    if errors.empty?
      format.js {render :update do |page|
        page.replace_html '_ID_OF_DOM_OBJECT_CONTAINING_ROW_INFO_', :partial => '_PARTIAL_FOR_ROW_INFO_LAYOUT_' 
      end}
      format.html { redirect_to :action => _WHATEVER_THE_SUCCESS_ACTION_IS_ }
    else
      format.js {render :update do |page|
        page.replace_html 'form', :partial => '_DOM_ID_OF_FORM_' 
      end}
      format.html { render :action => _WHATEVER_ACTION_DISPLAYED_THE_FORM_ }
    end
  end
end

_PARTIAL_FOR_ROW_INFO_LAYOUT_ 将具有:

<div id="_ID_OF_DOM_OBJECT_CONTAINING_ROW_INFO_">
  <!-- row display markup -->
</div>

遵循 Rails 约定时,您所做的很多事情会更容易,但我不知道您的 Rails 版本、应用程序 DSL 或您的应用程序使用哪些插件和/或宝石来解释控制器中的当前模式。

于 2010-08-28T19:20:58.543 回答
0

步骤#1:您必须修改link_to助手中的eid

link_to( "Close..." \
    , { :controller => "books", :action => "sell_form", :id => record.id, :page => false, :eid => @controller.params[:eid] } \
    , { :position => "replace", :inline => true, :class => "action" } \
  )

第 2 步:您必须修改和sell_form.erb设置parent_modelparent_column和. 您必须将 设置为,并且必须为带有 的表单生成正确的 HTML id 。nestedeidurlupdatebook_listelement_from_id()

<%
  form_remote_tag( \
    :url => { :controller => :books, :action => :sell, :id => params[:id], :parent_column => "books", :parent_model => "Publisher", :nested => "true", :eid => params[:eid] } \
    , :update => :book_list \
    , :html => { :id => element_form_id(:action => :update) } \
  ) do
%>

步骤#3:将if request.xhr?部分修改为以下简单代码。(未完全测试,最好的情况下可以正常工作。)

if request.xhr?
  if @record.valid?
    render :action => 'on_update.js'
  else
    render :action => 'form_messages.js'
  end
else
  if @record.valid?
    return_to_main
  else
    render :action => 'sell_form'
  end
end
于 2010-09-02T09:08:28.700 回答