【问题标题】:Update record, involves Join Table更新记录,涉及Join Table
【发布时间】:2014-05-20 22:43:41
【问题描述】:

Ruby on Rails 4

我有一个表格来编辑记录。形式与创建新记录相同。 (措辞除外)。当我单击提交时,它给出了 nilLNilClass。我的代码适用于更新我的其他不涉及联接表的记录,所以我不确定出了什么问题。

形式:

<%= form_for(@test) do |f| %>

<div class="field">
  <%= f.label :name %><br>
  <%= f.text_field :name %>
</div>
<div class="field">
  <%= f.label :type %><br>
  <%= f.text_field :type %>
</div>
<div class="field">
  <%= f.label :category %><br>
<%= f.select :category, [ ["IP Voice Telephony", "ip_voice"], ["IP Video Surveillance", "ip_video_surveillance"], ["IP Video Telephony", "ip_video_telephony"], ["Enterprise Gateways", "enterprise_gateways"], ["Consumer ATAs", "consumer_atas"], ["IP PBX", "ip_pbx"] ], {prompt: "Select Category"}, class: "input-lg", :id => "category" %>
</div>
<div class="field">
  <%= f.label :description %><br>
  <%= f.text_field :description %>
</div>

<div id="container" style="width:1140px; margin-left: auto; margin-right: auto;">
<button type="button" class="reset">Reset Search</button>
<table width="100%" class="tablesorter">
<thead>
  <tr>
  <th width="5%" class="filter-false"><input type="checkbox" onClick="toggle(this)"></th>
  <th width="37%" data-placeholder="Search">Content</th>
  <th width="10%" data-placeholder="Search">Type</th>
  <th width="10%" data-placeholder="Search">Category</th>
  <th width="10%" data-placeholder="Search">Product</th>
  <th width="10%" data-placeholder="Search">User</th>
  <th width="8%" data-placeholder="Search">Active</th>
  </tr>
</thead>

<tbody>
  <% @questions.each do |q| %>
  <tr>
    <td><%= check_box_tag "test[question_ids][]", q.id, @test.question_ids.include?(q.id) %></td>
    <td><%= q.content %></td>
    <td><%= q.question_type %></td>
    <td><%= q.category %></td>
    <td>GXP</td>
    <td><%= q.user_id %></td>
    <td><%= q.active %></td>
  </tr>
  <% end %>
 </tbody>
</table>

<br>
</div>
<div class="actions">
  <%= f.submit "Update Test", class: "btn btn-lg btn-primary" %>
</div>
<% end %>

控制器:

before_action :set_test, only: [:show, :edit, :update, :destroy]  
before_action :signed_in_user, only: [:index, :edit, :show, :update, :destroy]

def edit
  @test = Test.find(params[:id])
  @questions = Question.all
end

def update
  respond_to do |format|
    if @test.update(test_params)
      format.html { redirect_to @test, notice: 'Test was successfully updated.' }
      format.json { head :no_content }
    else
      format.html { render action: 'edit' }
      format.json { render json: @test.errors, status: :unprocessable_entity }
    end
  end
end

def test_params
    params.require(:test).permit(:name, :user_id, :type, :category, :description, :question_ids => [], questions_attributes: [ :id ] ).
    merge user_id: current_user.id
end  

错误:

Started PATCH "/tests/98" for 127.0.0.1 at 2014-05-20 10:12:58 -0400
Processing by TestsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"x=", "test"=>{"name"=>"one two three four, spelling YEah!!", "type"=>"", "category"=>"ip_voice", "description"=>"not so smart, wooops", "question_ids"=>["1"]}, "commit"=>"Update Test", "id"=>"98"}
Test Load (0.3ms)  SELECT "tests".* FROM "tests" WHERE "tests"."id" = ? LIMIT 1  [["id", "98"]]
User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'x' LIMIT 1
Completed 500 Internal Server Error in 6ms

NoMethodError (undefined method `update' for nil:NilClass):
app/controllers/tests_controller.rb:56:in `block in update'
app/controllers/tests_controller.rb:55:in `update'

这是第 56 行:if @test.update(test_params)

我确实认为我必须在 edit() 中定义 @test 很奇怪。我也试过 @test.save 有同样的错误。我误会了什么。

【问题讨论】:

  • 你有一个before_action 用于在你的控制器中设置@test 变量吗?如果没有,你必须定义一个
  • 等等,我愿意,before_action :set_test, only: [:show, :edit, :update, :destroy] 你不是这个意思吗?
  • 您也必须为此定义操作。检查我的答案。

标签: ruby-on-rails ruby ruby-on-rails-4


【解决方案1】:

您需要在update 操作中定义@test。目前它没有定义,所以它的值是nil,你会收到错误。

update 操作中添加这一行,然后调用@test.update

@test = Test.find(params[:id])

我看到您有一个用于设置测试的before_action 回调,即set_test。在这种情况下,您不需要

@test = Test.find(params[:id])

update 行动中。您需要做的就是在before_action 回调中添加update 操作:

before_action :set_test, only: [:show, :edit, :update, :destroy]  

另外,我建议您从edit 操作中删除 @test 设置,因为您已经在before_action 回调中添加了edit 操作

最后,set_test(最好是private 方法)方法应如下所示:

def set_test
  @test = Test.find(params[:id])
end

【讨论】:

  • 只有连接表记录需要这个吗?我的其他控制器没有在 edit() 中定义任何内容?
  • 它与连接表记录无关。它是一个基本的 Ruby 东西,你必须在使用它之前设置变量(无论是实例变量还是局部变量,在你的情况下是实例变量)值。
  • Pavan 提到使用之前的过滤器。我补充了我的问题。这些应该有效吗?
  • 是的,如果您有before_action 用于设置测试,您只需在此处添加action 名称即可。
  • 正如我之前所说,你是一个大竞争对手!很高兴看到你的答案:)
【解决方案2】:

你需要在你的控制器中这样做

before_action :set_test, only: [:show,:edit,:update,:destroy] 和你的控制器的末尾

private

def set_test

@test = Test.find(params[:id])

end

另外,像这样更新你的编辑方法

def edit
  #@test = Test.find(params[:id]) remove this line you wont need it.
  @questions = Question.all
end

您可以按照 @kirti Thorat 的回答。

【讨论】:

  • 哦,好的。太好了,一个问题的两个答案。 :D +1
  • Pavan,你打错了[:show,:edit,:update.:destroy] 改成:update, :destroy注意逗号而不是点)
  • 不妨在你的回答中更正我的名字,它是 Kirti 而不是 Kriti:D
  • @KirtiThorat 我的错!更正:D
猜你喜欢
  • 2013-04-18
  • 2021-12-14
  • 1970-01-01
  • 2016-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多