Rails - 如何将一些信息从一个表单发送到另一个控制器

时间:2014-12-18 16:31:55

标签: ruby-on-rails postgresql

首先,我想描述一下我将要做的事情。因此,我的应用程序是一组任务(例如,练习依赖于编写计算机程序),用户可通过表单发送解决方案,服务器将编译它并返回进程结果。 我的问题是我的模型Solution如下所示:

Solution(id: integer, exercise_id: integer, code: string, user_id: integer,
created_at: datetime, updated_at: datetime, language_id: integer)

exercise_id, user_id, language_id是外键和postgresql返回错误,它不能是空值... 我用来发送此信息的表单如下所示:

<fieldset style="add">
  <legend>Send solution</legend>
    <%= form_for [@user, @exercise, @solution], url: exercise_solutions_path, :html => { role: "form" } do |f| %>
      <div class="form-group">
        <%= f.label "Source code" %>
        <br>
        <%= f.text_area :code %>
      </div>

      <div class="form-group">
        <%= f.label "Programming language" %>
        <br>
        <%= f.select(:language_id, available_lang) %>
      </div>

      <div class="form-group">
        <%= f.submit "Send", :class => "btn btn-default" %>
      </div>
    <% end %>
</fieldset>

坦率地说,我不知道如何包含更多信息,例如user.id或exercise.id。 Params看起来像:

@_params    

{"utf8"=>"✓", "authenticity_token"=>"abwhTn3KrVneli0pCVccoWHyzlI7cRTFK5Wo7DdYRK+lL4GwZ8jUPqdzn8ZznCHsWTkfDAFS2RP6gTkWuk33iw==", "solution"=>{"code"=>"ds", "language_id"=>"C++"}, "commit"=>"Wyślij", "controller"=>"solutions", "action"=>"create", "exercise_id"=>"1"}

SolutionController

class SolutionsController < ApplicationController

  def index
    @solutions = Solution.last(20)
  end

  def new
    @solution = Solution.new
  end

  def create
    @solution = Solution.new(solution_params)
    if @solution.save
      redirect_to @solution
    else
      render :new
    end
  end

  def edit
    @solution = Solution.find(params[:id])
    if @solution.update(solution_params)
      redirect_to @solution
    else
      render :edit
    end
  end

  def destroy
  end

  private

  def solution_params
    params.require(:solution).permit(:language_id, :code)
  end

end

编辑:

<fieldset style="add">
  <legend>Send solution</legend>
    <%= form_for [@user, @exercise, @solution], url: exercise_solutions_path, :html => { role: "form" } do |f| %>
      <div class="form-group">
        <%= f.label "Source code" %>
        <br>
        <%= f.text_area :code %>
      </div>

      <div class="form-group">
        <%= f.label "Programming language" %>
        <br>
        <%= f.select(:language_id, available_lang) %>
      </div>

      <div class="form-group">
        <%= f.hidden_field :exercise_id, value: @exercise.id %>
        <%= f.hidden_field :user_id, value: @user.id %>
        <%= f.submit "Send", :class => "btn btn-default" %>
      </div>
    <% end %>
</fieldset>

1 个答案:

答案 0 :(得分:1)

您可以1)在表单中添加hidden_field来设置缺少的属性:

<div class="form-group">
  <%= f.hidden_field :exercise_id, value: @exercise.id %>
  <%= f.hidden_field :user_id, value: @user.id %>
  <%= f.submit "Send", :class => "btn btn-default" %>
</div>

确保将这些属性添加到solution_params允许的参数:

def solution_params
  params.require(:solution).permit(:language_id, :code, :exercise_id, :user_id)
end

更好的想法是手动设置控制器中的exerciseuser,并按原样保留solution_params。这样你就不允许通过质量分配来设置练习和用户,这可能是欺骗性的。

所以在你的控制器中做2):

def create
  @solution = Solution.new(solution_params)
  @solution.exercise_id = params[:exercise_id]
  @solution.user_id = params[:user_id]

  if @solution.save
    redirect_to @solution
  else
    render :new
  end
end

我假设网址中包含:exercise_id:user_id。如果不是根据需要将它们添加为hidden_​​fields(但这次不在表单对象上):

<%= hidden_field_tag :user_id, @user.id %>

另外请记住在提交表单之前从下拉列表中选择language_id