【问题标题】:rails attribute changes in spite of not being in form尽管不在表单中,但rails属性发生了变化
【发布时间】:2015-10-26 23:41:42
【问题描述】:

我有 Rails 应用程序,用户可以在其中相互分配任务。每个任务都有一个分配者和一个执行者。默认情况下,任务创建者(current_user)始终是分配者。分配者和执行者都可以编辑同一个任务。

我的问题如下。假设 user.id=2 是分配者,而 user.id=1 是执行者。如果分配者(id = 2)稍后编辑任务一切正常,但如果执行者(id = 1)编辑它,那么他也成为分配者,所以task.executor_id = 1和task.assigner_id = 1。无法更改新/编辑表单中的分配者。当分配者创建它时,他是当前用户的默认分配者,当 sby 尝试编辑它时,他/她不能更改分配者。是什么导致了这个问题?

这很奇怪,因为它之前运行良好,我有点确定我一直在遇到这个问题,因为我已经改为使用带有 的 _task.html.erb 部分而不是 w / 普通的 @tasks.each 做 |task|版本。我最初认为这是因为我在使用新的 AJAXified 版本时犯了一些错误,但在 git reset --hard 之后,它似乎是别的东西。

def task_params
  params.require(:task).permit(:executor_id, :name, :content, :deadline, :task_name_company)
  .merge(assigner_id: current_user.id)
end

class Task < ActiveRecord::Base
  belongs_to :assigner, class_name: "User"
  belongs_to :executor, class_name: "User"

_task.html.erb

<% if current_user.id == task.assigner.id %>
  <tr style="background: #eaeaea" id="task_<%= task.id %>">
    <td class="col-md-3">
      <%= link_to user_path(id: task.executor.id) do %>
        <%= task.executor.profile.first_name %> <%= task.executor.profile.last_name%> / <%= task.executor.profile.company %>
      <% end %>
    </td>
<% else %>
  <tr id="task_<%= task.id %>">
    <td class = "col-md-3">
      <%= link_to user_path(id: task.assigner.id) do %>
        <%= task.assigner.profile.first_name %> <%= task.assigner.profile.last_name%> / <%= task.assigner.profile.company %>
      <% end %>
    </td>
<% end %>
    <td class="cold-md-4">
      <%= link_to user_task_path(id: task.id) do %>
        <%= task.content %>
      <% end %>
    </td>
    <td class="col-md-3">
      <%= task.deadline %>
    </td>
    <td class="col-md-2" style="padding:0px">
    <% if current_user.id == task.assigner.id %>
      <table class="table table-bordered inside-table" style="background:#eaeaea">
    <% else %>
      <table class="table table-bordered inside-table">
    <% end %>
        <tr>
          <td class="col-md-4" style="border-top:0px;border-bottom:0px;border-left:0px">
            <% if task.completed_at == nil %>
              <%= link_to complete_user_task_path(id: task.id), action: :complete, remote: true, method: :patch do %>
                <i class="fa fa-check"></i>
              <% end %>
            <% else %>
              <%= link_to uncomplete_user_task_path(id: task.id), action: :uncomplete, remote: true, method: :patch do %>
                <i class="fa fa-check"></i>
              <% end %>
            <% end %>
          </td>
          <td class="col-md-4" style="border-top:0px;border-bottom:0px;">
            <%= link_to edit_user_task_path(id: task.id), type: "button" do %>
              <i class="fa fa-pencil"></i>
            <% end %>
          </td>
          <td class="col-md-4" style="border-top:0px;border-bottom:0px;border-right:0px">
            <%= link_to user_task_path(id: task.id), method: :delete, data: { confirm: "Are you sure?" }, remote: true do %>
              <i class="fa fa-trash"></i>
            <% end %>
          </td>
        </tr>
      </table>
    </td>
  </tr>

_form.html.erb

<%= form_for ([@user, @task]) do |f| %>

  <%= render 'layouts/error_messages', object: f.object %>

  <div class="field form-group">
    <%= f.label :Name_or_Company %>
    <%= f.text_field :task_name_company, data: {autocomplete_source: user_tasknamecompanies_path}, class: "form-control task_name_company" %>
  </div>
  <div class="field form-group">
    <%= f.label :content %>
    <%= f.text_area :content, class: "form-control" %>
  </div>
  <div class="field form-group">
    <%= f.label :deadline %>
    <%= f.date_select :deadline, class: "form-control" %>
  </div>
  <div class="actions">
    <%= f.submit "Create Task", class: 'btn btn-primary', "data-sid" => current_user.id, "data-rip" => :executor_id %>
  </div>
<% end %>

更新: 根据 Rich Peck 和 miler350 的回答解决了问题。我做了以下事情:

before_action :set_assigner, only: :create

private

def set_assigner
  @task.assigner.id = current_user.id
end

【问题讨论】:

    标签: ruby-on-rails forms attributes


    【解决方案1】:
    def task_params
      params.require(:task).permit(:executor_id, :name, :content, :deadline, :task_name_company).merge(assigner_id: current_user.id)
    end
    

    每次传入参数时,您都将分配者 ID 设置为 current_user。

    我会删除合并,并且只有这样的强大参数:

    params.require(:task).permit(:executor_id, :name, :content, :deadline, :task_name_company, :assigner_id)
    

    然后,在你的创建操作中,在你做之前:

    @task.save
    

    添加这个:

    @task.assigner_id = current_user.id
    

    然后你可以根据你的选择定义你的权限(必须是分配者,必须是执行者),但只要你不添加任何疯狂的更新,它就可以正常工作。

    【讨论】:

    • 我的控制器操作中没有 task.save,只有 IF task.save。这样做的首选方法是什么?表单中的 hidden_​​field,attr_readonly/attr_protected 还是 before_create 回调?
    • 没关系。 @task.assigner_id = current_user.id 刚刚超出 if @task.save 线。相同的机制。
    【解决方案2】:

    默认情况下,任务创建者(current_user)始终是分配者

    这应该无关紧要 - 有人是 assigner,有人是 executor


    miler350 是正确的 - 您的参数会不断设置您的 assigner_id: current_user.id(看起来像是我的建议之一)。

    解决方法是从您的参数中删除.merge 并将其设置在您的控制器操作中(根据miler350 的回答和这样的):

    #app/controllers/tasks_controller.rb
    class TasksController < ApplicationController
    
        def new
            @task = Task.new
        end
    
        def create
            @task = Task.new task_params
            @task.assigner = current_user
            @task.save
        end
    
        def edit
            @task = Task.find params[:id]
        end
    
        def update
            @task = Task.find params[:id]
            @task.update task_params
        end
    
        private
    
        def task_params
            params.require(:task).permit(:executor_id, :name, :content, :deadline, :task_name_company, :assigner_id)
        end
    
    end
    

    通过让用户“编辑”assignment,您应该每次都定义不同的assigner / executor

    【讨论】:

    • 丰富,我解决了(可以在更新的问题中找到),但我还有一个额外的问题。为什么我可以使用您的解决方案,我的意思是如果我使用与您在创建操作中编写的内容兼容的表单? @task.save 与单击提交按钮不一样?所以不是get提交了两次吗?
    • 我赞成另一个答案!你不需要使用我自己的,我写它是因为它给出了控制器应该如何工作的视角
    • 我的意思是如何使用你的。我只是不明白,所以我想知道是否可以同时提交和@task.save。
    猜你喜欢
    • 1970-01-01
    • 2021-04-02
    • 2018-12-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-27
    • 1970-01-01
    • 2020-05-15
    • 1970-01-01
    相关资源
    最近更新 更多