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
一个post
has_many
comments
和belongs_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.reify
和 version.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 %>
我刚刚在我的 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
一个post
has_many
comments
和belongs_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.reify
和 version.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 %>