【问题标题】:rails respond_with associated recordrails respond_with 关联记录
【发布时间】:2012-09-30 21:20:28
【问题描述】:

例如,有一个Question 模型has_many :answers

我想在questions#show 上显示新答案的表单(就像 stackoverflow 一样)

路线类似于:

resources :questions do
  resources :answers
end

在这些情况下,显示无效记录错误的最佳方式是什么?

问题是我不能在AnswersControllerrender 执行我需要的操作(因为它将是questions#show),唯一的方法似乎是redirect_to 并将错误存储在flash 哈希中.

这看起来很常见,我相信应该有更好的方法

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 grails-controller respond-with


    【解决方案1】:

    这可能是为您的QuestionsController 添加一个新的资源丰富的成员路由实际上是合理的少数情况之一:

    resources :questions do
      post 'answer', :on => :member
    end
    

    它将通过路由到questions#answer 的 POST 请求识别 question/:id/answer,从而允许您将所有逻辑保存在一个控制器中:

    class QuestionsController < ApplicationController
      ...
      def show
        @question = Question.find(params[:id])
      end
    
      def answer
        @question = Question.find(params[:id])
    
        @answer = @question.answers.build(params[:question][:answer])
    
        if @answer.save
          # show question with newly posted answer at url /question/:id
          redirect_to @question
        else
          # show question with invalid editable answer at url /question/:id/answer
          render 'show'
        end
      end
      ...
    end
    

    解释:在我看来,在一个控制器而不是两个控制器中处理逻辑的决定归结为您认为感兴趣的资源。通常,您会认为每个模型代表一个不同的资源,因此创建一个单独的控制器来处理与每个资源相关的操作。然而,当有多个深度耦合模型在单个视图中处理多个动作(例如shownewcreate)时,将模型视为形成一个单个视图可能更清晰 资源。

    在此示例中,我将资源视为由问题及其答案both 组成的集合资源。由于这个集体资源是由问题本身唯一标识的,我会让问题控制器处理它。问题控制器中的show 操作已经涉及检索集体问答资源,因此您可能会认为answer 操作(可能还有unanswerreanswer 操作)类似于update集体资源。

    以这种方式考虑资源很大程度上取决于设计偏好,并且会根据需求进行权衡。

    【讨论】:

    • 还不能奖励,还剩 30 分钟
    • 我不同意。答案的创建属于AnswersController#create。为什么你认为这是合理的?如果出现错误,并不是不可能渲染特定的模板。
    • @Mischa 见我上面的解释。
    • 我同意cdesrosiers 所说的,因为这对我来说也很自然,我什至在发布之前为我的question 模型定义了answer_with 方法。当然,这仍然只是个人喜好问题。我喜欢这种方法的另一件事是它允许您简单地使用respond_with @question
    • 感谢您的详尽解释。我明白你现在的意思了。就像“更新问题”一样,您可以“回答问题”。答案是动词,不是名词。
    【解决方案2】:

    您可以像这样从AnswersController 渲染questions#show

    render :template => 'questions/show'
    

    如果你想跳转到页面上的特定锚点,你必须在你的回答表单中定义它:

    <%= form_for(@answer, :url => question_answers_url(@question, :anchor => 'answer_form')) do |f| -%>
    

    【讨论】:

      【解决方案3】:

      具有将数据发布到 answers_controller#create 操作的表单的部分。

      所以,在你的问题#show 页面 - show.html.erb 中,渲染一个部分

      <%= render :partial => "answers/answer_form" %>
      

      在 _answer_form.html.erb 中,有一个将数据发布到 answers#create 的表单

      <% form_for @answer do |f| %>
        # have a text area
      <% end %>
      

      就闪光灯而言

      在 AsnwersController 中

      def create
        @question = Question.find(params[:question_id])
        @answer = Answer.build(params)
        if @answer.save
          flash[:notice] = "Answer was posted successfully"  
        else
          flash[:error] = "There were a few errors please try again"  
        end
        redirect_to question_path(@question) 
      end
      

      【讨论】:

      • 使用 flash 处理错误是个坏主意,此外您无法使用此解决方案重新填充字段。如果出现错误,您是否希望用户重新填写整个表单?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-17
      • 2012-06-20
      相关资源
      最近更新 更多