【问题标题】:Rails model with nested attributes fails to save but no error message is displayed具有嵌套属性的 Rails 模型无法保存但不显示错误消息
【发布时间】:2016-11-24 23:54:37
【问题描述】:

我有以下通过多对多关系进行通信的 Rails 模型:

class Task < ApplicationRecord
  belongs_to :case
  has_many :task_actor_roles
  has_many :task_artifacts

  has_many :task_activities
  has_many :activities, through: :task_activities

  accepts_nested_attributes_for :task_activities

  attr_accessor :tasks_attributes
end

...

class TaskActivity < ApplicationRecord
  belongs_to :task
  belongs_to :activity
  belongs_to :instantiation_operator
end

...

class Activity < ApplicationRecord
  belongs_to :software_process
  has_many :artifacts, :dependent => :destroy
  belongs_to :activity_role
  has_many :task_activities
  has_many :tasks, through: :task_activities
end

我正在使用嵌套表单 gem 在新任务表单中添加多个选择字段。 这是生成表单的一段代码:

<%= nested_form_for(task, url: {action: action}) do |f| %>
  <%= f.label :activities %>
  <%= f.fields_for :task_activities do |task_activity| %>
    <%= task_activity.select(:activity_id,@activities.collect { |p| [p.name, p.id] } ) %>
    <%= task_activity.hidden_field :instantiation_operator_id, :value => @operator.id %>
    <%= task_activity.link_to_remove "Remove this activity" %>
  <% end %>
  <p><%= f.link_to_add "Add an activity", :task_activities %></p>
  <div class="field">
     <%= f.label :name %>
     <%= f.text_field :name %>
  </div>
  <%= f.submit %>
<%= end %>

当我发送数据时,页面会重新加载,就好像它会显示验证错误一样,但是它没有显示任何内容。

这是终端日志的样子:

    Started POST "/tasks/create_group" for 127.0.0.1 at 2016-11-24 21:51:40 -0200
Processing by TasksController#create_group as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"[FILTERED]", "task"=>{"case_id"=>"1", "task_activities_attributes"=>{"1480031490821"=>{"activity_id"=>"11", "instantiation_operator_id"=>"6", "_destroy"=>"false"}, "1480031492604"=>{"activity_id"=>"14", "instantiation_operator_id"=>"6", "_destroy"=>"false"}}, "name"=>"Doris Woodard", "description"=>"Aperiam impedit aut fugit amet anim perspiciatis mollit", "priority"=>"Dolores explicabo Ipsum dolorem sit in cum iste enim nisi sint sed ratione odio", "category"=>"Eos cumque consequuntur iste est enim minim beatae et dolores mollit id quis ut occaecat laboriosam molestiae aut ipsa nulla", "status"=>"Veritatis qui id quaerat distinctio Blanditiis odio sit quisquam vel provident optio consectetur", "startDate"=>"25-Feb-2001", "comments"=>"Voluptatem eiusmod amet in ut", "TTC"=>"43"}, "task_activity"=>{"instantiation_operator_id"=>"6"}, "task_actor_role"=>{"task_role_id"=>"2", "task_actor_id"=>"3"}, "commit"=>"Create Task"}
   (0.1ms)  BEGIN
  Case Load (0.3ms)  SELECT  "cases".* FROM "cases" WHERE "cases"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  TaskActor Load (0.4ms)  SELECT  "task_actors".* FROM "task_actors" WHERE "task_actors"."id" = $1 LIMIT $2  [["id", 3], ["LIMIT", 1]]
  TaskRole Load (0.3ms)  SELECT  "task_roles".* FROM "task_roles" WHERE "task_roles"."id" = $1 LIMIT $2  [["id", 2], ["LIMIT", 1]]
  Activity Load (0.2ms)  SELECT  "activities".* FROM "activities" WHERE "activities"."id" = $1 LIMIT $2  [["id", 11], ["LIMIT", 1]]
  InstantiationOperator Load (0.4ms)  SELECT  "instantiation_operators".* FROM "instantiation_operators" WHERE "instantiation_operators"."id" = $1 LIMIT $2  [["id", 6], ["LIMIT", 1]]
  Activity Load (0.4ms)  SELECT  "activities".* FROM "activities" WHERE "activities"."id" = $1 LIMIT $2  [["id", 14], ["LIMIT", 1]]
  CACHE (0.0ms)  SELECT  "instantiation_operators".* FROM "instantiation_operators" WHERE "instantiation_operators"."id" = $1 LIMIT $2  [["id", 6], ["LIMIT", 1]]
   (0.2ms)  ROLLBACK
  InstantiationOperator Load (0.2ms)  SELECT  "instantiation_operators".* FROM "instantiation_operators" WHERE "instantiation_operators"."name" = $1 LIMIT $2  [["name", "group"], ["LIMIT", 1]]
  Case Load (0.3ms)  SELECT  "cases".* FROM "cases" WHERE "cases"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Rendering tasks/group.html.erb within layouts/application
  Project Load (0.2ms)  SELECT  "projects".* FROM "projects" WHERE "projects"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  SoftwareProcess Load (0.2ms)  SELECT  "software_processes".* FROM "software_processes" WHERE "software_processes"."id" = $1 LIMIT $2  [["id", 2], ["LIMIT", 1]]
  TaskRole Load (0.3ms)  SELECT "task_roles".* FROM "task_roles"
  TaskActor Load (0.2ms)  SELECT "task_actors".* FROM "task_actors"
  Activity Load (0.2ms)  SELECT "activities".* FROM "activities"
  Rendered tasks/_form.html.erb (10.8ms)
  Rendered tasks/group.html.erb within layouts/application (14.1ms)
  User Load (0.7ms)  SELECT  "users".* FROM "users" WHERE "users"."remember_token" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["remember_token", "e97f4b0c90c219f7223b805989eb25dbc6e2cae2"], ["LIMIT", 1]]
Completed 200 OK in 220ms (Views: 150.4ms | ActiveRecord: 7.7ms)

当我在表单中注释掉带有嵌套属性的行时,它会毫无问题地保存。所以问题肯定就在于此。

更新

所以我使用 byebug 来检查@task:

@task.valid?
  Case Load (0.4ms)  SELECT  "cases".* FROM "cases" WHERE "cases"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  TaskActor Load (0.2ms)  SELECT  "task_actors".* FROM "task_actors" WHERE "task_actors"."id" = $1 LIMIT $2  [["id", 3], ["LIMIT", 1]]
  TaskRole Load (0.2ms)  SELECT  "task_roles".* FROM "task_roles" WHERE "task_roles"."id" = $1 LIMIT $2  [["id", 2], ["LIMIT", 1]]
  Activity Load (0.3ms)  SELECT  "activities".* FROM "activities" WHERE "activities"."id" = $1 LIMIT $2  [["id", 2], ["LIMIT", 1]]
  InstantiationOperator Load (0.2ms)  SELECT  "instantiation_operators".* FROM "instantiation_operators" WHERE "instantiation_operators"."id" = $1 LIMIT $2  [["id", 3], ["LIMIT", 1]]
  Activity Load (0.2ms)  SELECT  "activities".* FROM "activities" WHERE "activities"."id" = $1 LIMIT $2  [["id", 7], ["LIMIT", 1]]
  CACHE (0.0ms)  SELECT  "instantiation_operators".* FROM "instantiation_operators" WHERE "instantiation_operators"."id" = $1 LIMIT $2  [["id", 3], ["LIMIT", 1]]
false

...

@task.errors
#<ActiveModel::Errors:0x007fcd984174c8 @base=#<Task id: nil, name: "Forrest Wright", description: "In dolores voluptatibus maiores in fugit fuga Quis...", priority: "Voluptatem modi quod consequatur vel sed est exerc...", category: "Sequi vitae at explicabo In", status: "Omnis quo sed obcaecati voluptate corporis cumque ...", startDate: "1986-07-04", comments: "Ut fugit dicta voluptatem Ullam voluptas id et", TTC: 86, endDate: nil, created_at: nil, updated_at: nil, case_id: 1>, @messages={:"task_activities.task"=>["must exist"]}, @details={"task_activities.task"=>[{:error=>:blank}]}>

【问题讨论】:

    标签: ruby-on-rails ruby nested-forms nested-form-for


    【解决方案1】:

    您必须将模型错误记录到 production.log。实现这一点的一种方法是:

    def your_action
      logger.debug @task.errors
      [...]
    end
    

    或使用 byebug (Rails 5+) 或调试器 (Rails 4-) 进行调试

    def your_action
      [...]
      byebug
      [...]
    end
    

    在 Rails 服务器中,您可以检查 @task 变量。

    【讨论】:

    • 谢谢!我正在使用 byebug,我发现 @task.task_activities 按预期返回任务活动实例,它具有活动和实例化操作员 ID,但没有任务 ID,大声笑知道为什么会发生吗?
    • 你必须调用 task.save 然后检查错误(task.errors)。如果记录存在验证错误,则不会保存。实现此目的的其他方法是使用 task.valid?然后是task.errors。这不会尝试将您的记录保存到数据库中。
    • 我调用了 task.save。它只是表现为我在线程中包含的日志。没有显示错误。它只是突然回滚。都无效?显示任何东西。我将使用日志更新线程
    • 实际上,我只是注意到 task_activities.task 有一条错误消息...显然它没有将我正在尝试创建的当前任务链接到它的 task_activity 子项
    • 刚刚发现问题。我回答了我自己的问题。谢谢!
    【解决方案2】:

    解决方案是在has_many :task_activities 前面添加, inverse_of: :task。 问题是任务活动试图在任务之前保存。我使用了 byebug(感谢@vl3 的提醒)并检查了@save.errors。我找到了消息:

    @messages={:"task_activities.task"=&gt;["must exist"]}

    而且没有 task_id 被分配给任务活动。

    我添加的这一行只是让任务在任务活动之前创建。

    【讨论】:

      猜你喜欢
      • 2012-02-07
      • 1970-01-01
      • 2011-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多