提问人:Poppy 提问时间:3/28/2022 更新时间:3/28/2022 访问量:80
如何在视图页中显示对 ActiveRecord 中的记录所做的更新的列表
How to show in a view page a list of updates made to a record in ActiveRecord
问:
我正在用 Ruby 制作一个简单的联系人列表应用程序。 在每个联系人的显示视图中,我想显示基本信息(first_name、last_name、电子邮件和电话),以及该联系人是否有任何更改或更新。 例如,如果他们将电子邮件地址从 [email protected] 更改为 [email protected],并且此更改是在 2022 年 3 月 27 日进行的,我希望此信息的列表也显示在节目页面上。
我想这与包括 ActiveModel::D irty 或回调有关,但不太确定如何实现其中任何一个!
这是我的 Contact.rb 模型文件
# frozen_string_literal: true
class Contact < ApplicationRecord
before_validation :normalize_first_name, on: :create
before_validation :normalize_last_name, on: :create
# after_save :print_changes
# before_update :check_for_changes
# after_update :check_for_previous_changes
validates_presence_of :first_name, :last_name, :email, :phone
validates :phone, numericality: { only_integer: true }
validates :email, uniqueness: true
validates :email,
format: { with: /\A(.+)@(.+)\z/, message: 'Email invalid' },
uniqueness: { case_sensitive: false },
length: { minimum: 4, maximum: 95 }
private
def normalize_first_name
self.first_name = first_name.downcase.titleize
end
def normalize_last_name
self.last_name = last_name.downcase.titleize
end
# def check_for_changes
# puts changes # => {"name"=>["Nimish Gupta", "Nimish Mahajan"], "updated_at"=>[Tue, 20 Nov 2018 00:02:14 PST -08:00, Tue, 20 Nov 2018 00:06:15 PST -08:00]}
# puts previous_changes # => {} At this point this will be empty beacuse changes are not made to DB yet
# end
# def check_for_previous_changes
# # but you can make use of previous_changes method to know what change has occurred.
# puts previous_changes # => {"name"=>["Nimish Gupta", "Nimish Mahajan"], "updated_at"=>[Tue, 20 Nov 2018 00:06:15 PST -08:00, Tue, 20 Nov 2018 00:08:07 PST -08:00]}
# end
end
这是联系人控制器
class ContactsController < ApplicationController
before_action :set_contact, only: %i[show edit update destroy]
# GET /contacts or /contacts.json
def index
@contacts = Contact.all
@contact = Contact.new
end
# GET /contacts/1 or /contacts/1.json
def show
end
# GET /contacts/new
def new
@contact = Contact.new
end
# GET /contacts/1/edit
def edit; end
# POST /contacts or /contacts.json
def create
@contact = Contact.new(contact_params)
respond_to do |format|
if @contact.save
format.html { redirect_to contact_url(@contact), notice: 'Contact was successfully created.' }
format.json { render :show, status: :created, location: @contact }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @contact.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /contacts/1 or /contacts/1.json
def update
respond_to do |format|
if @contact.update(contact_params)
format.html { redirect_to contact_url(@contact), notice: 'Contact was successfully updated.' }
format.json { render :show, status: :ok, location: @contact }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @contact.errors, status: :unprocessable_entity }
end
end
end
# DELETE /contacts/1 or /contacts/1.json
def destroy
@contact.destroy
respond_to do |format|
format.html { redirect_to contacts_url, notice: 'Contact was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_contact
@contact = Contact.find(params[:id])
end
# Only allow a list of trusted parameters through.
def contact_params
params.require(:contact).permit(:first_name, :last_name, :email, :phone)
end
end
以及我希望显示更改的“显示”页面
<p id="notice"><%= notice %></p>
<h1>This is the show page for each contact</h1>
<p>
<strong>First name:</strong>
<%= @contact.first_name %>
</p>
<p>
<strong>Last name:</strong>
<%= @contact.last_name %>
</p>
<p>
<strong>Email:</strong>
<%= @contact.email %>
</p>
<p>
<strong>Phone:</strong>
<%= @contact.phone %>
</p>
<%= link_to 'Edit', edit_contact_path(@contact) %> |
<%= link_to 'Back', contacts_path %>
<h1>Contact history</h1>
<%# <%= check_for_changes(@contact) %>
<table>
<thead>
<tr>
<th>Field</th>
<th>Updated</th>
<th>Previous entry</th>
</tr>
</thead>
<tbody>
<%# <% @contacts.each do |contact| > %>
<tr>
<td>Email</td>
<td>27/03/2022</td>
<td>[email protected]</td>
<%# <td><%= contact.first_name ></td> %>
<%# <td><%= contact.last_name ></td> %>
<%# <td><%= contact.email ></td> %>
</tr>
<%# <% end > %>
</tbody>
</table>
答:
0赞
Siim Liiser
3/28/2022
#1
ActiveModel::Dirty
仅允许您跟踪所做的更改的同一请求中的更改。一旦联系人与新更改一起存储到数据库中并且请求结束,就没有内置方法来获取旧值了。
您必须自己构建解决方案。您将需要一个模型来存储所做的所有更改,这些更改属于您的联系人。从现在开始,我们称之为。ContactChange
为了在更改联系人时创建联系人更改,可以使用这些方法并将其放入回调中,也可以创建服务对象来更新联系人和创建联系人更改。ActiveModel::Dirty
after_save
或者,如果您只想要一个开箱即用的解决方案,那么有一些宝石。例如,纸质记录。
评论
0赞
Poppy
3/29/2022
非常感谢您指向宝石paper_trail指针!我一直在遵循非常有用的教程,它完全符合我在这里的需求(对于任何可能有帮助的人!driftingruby.com/episodes/auditing-with-paper-trail
评论