Rails 4 x paper_trail:销毁后 nil:NilClass 的未定义方法

Rails 4 x paper_trail: undefined method for nil:NilClass after destroy

我刚刚在我的 Rails 4 应用程序中安装了 paper_trail gem。

所以,现在我的 schema.rb:

中有了这个
create_table "versions", force: :cascade do |t|
  t.string   "item_type",  null: false
  t.integer  "item_id",    null: false
  t.string   "event",      null: false
  t.string   "whodunnit"
  t.text     "object"
  t.datetime "created_at"
end

我将 paper_trail 添加到我的 Post 模型中:

class Post < ActiveRecord::Base
  has_paper_trail
end

一个posthas_manycommentsbelongs_to一个calendar.

我正在尝试在我的 Calendars#Index 视图中显示最近修改的 post 的历史记录。

我使用 official documentation and this tutorial 作为灵感。

因此,在 calendars_controller.rb 中,我有:

def index
  @user = current_user
  @calendars = @user.calendars.all
  @comments = @user.calendar_comments.where.not(user_id: @user.id).order "created_at DESC"
  @versions = PaperTrail::Version.order('id desc').limit(20)
end

在我的 Calendar index.html.erb 视图中,我有:

<h3 class="main_title">Updates</h3>

    <div id="my_changes">

      <% if @versions.any? %>

        <table id="my_change_table">

          <tr>
            <th><span class="glyphicon glyphicon-calendar" aria-hidden="true"></span> CALENDAR </th>
            <th><span class="glyphicon glyphicon-list" aria-hidden="true"></span> POST </th>
            <th><span class="glyphicon glyphicon-user" aria-hidden="true"></span> AUTHOR </th>
            <th><span class="glyphicon glyphicon-edit" aria-hidden="true"></span> CHANGE </th>
          </tr>

          <% @versions.each do |version| %>

          <% post = Post.find_by_id(version.item_id) %>

            <tr>
              <td><%= Calendar.find_by_id(post.calendar_id).name %></td>
              <td><%= post.subject %></td>
              <td><%= User.find_by_id(version.whodunnit).first_name %></td>
              <td><%= version.event.humanize + "d" %></td>
            </tr>

          <% end %>

        </table>

      <% else %>

        <p>There was no change to your posts yet.</p>

      <% end %>

    </div>

当用户 update 是 post.

时,这实际上非常有效

但是,一旦用户 destroy 成为 post,我就会收到以下错误:

NoMethodError in Calendars#index
undefined method `item_id' for #<Post:0x007fff22e28c58>
<% post = Post.find_by_id(version.item_id) %>

其实这是有道理的,因为我们destroy编辑了post,它已经不存在了,所以我们可以检索它的id

但我认为这正是 paper_trail 的工作。

所以,我一定是漏掉了什么。

我尝试使用 version.reifyversion.previous 方法,但仍然 运行 遇到同样的问题。

知道如何进行这项工作吗?

问题是你销毁一个对象后,reify会重新运行一个新的对象实例,这个实例没有被保存,也没有id。

既然它无论如何都被删除了,你应该期望 Post.find_by_id(version.item_id) 无论如何都找不到它。

编辑

您应该能够从版本中获取原始对象的属性(参见 here

因此您可以将您的代码更改为类似的内容(假设您系统中的所有版本都是日历),我认为它应该可以工作:

      <% @versions.each do |version| %>

      <% post = version.reify %>

        <tr>
          <td><%= Calendar.find_by_id(post.calendar_id).name %></td>
          <td><%= post.subject %></td>
          <td><%= User.find_by_id(version.whodunnit).first_name %></td>
          <td><%= version.event.humanize + "d" %></td>
        </tr>

      <% end %>