before_destroy 检查是否给出了相关模型的属性(版本控制)
before_destroy check if attribute for related model is given (version control)
我有一个与版本模型 has_many 相关的模型。需要跟踪 parent 模型上的任何操作。在删除表格中,我添加了一个嵌套表格来输入将添加到版本中的票号。如果给出票证,我如何检查模型验证?我将在调用模型上的销毁之前编写版本。
# model.rb
class Model < ActiveRecord::Base
has_many :versions,
:as => :version_object
end
# models_controller.rb
def destroy
@model = Model.find(params[:id])
self.write_versions('Destroy')
@Model.destroy
respond_to do |format|
...
end
end
# delete.html.erb
<%= form_for [@model.parent_object, @model], :html => { :class => 'form-horizontal' }, :method => :delete
do |f| %>
<div class="form-actions">
<%= f.fields_for :versions, @model.versions.build do |v| %>
<%= v.text_field :ticket, {:class => 'text_field', :placeholder => 'Ticket Nummer'}%>
<% end %>
<%= f.submit 'Delete Model', :class => 'btn btn-danger' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
:back, :class => 'btn' %>
</div>
<% end %>
我已经尝试实现 before_destroy 方法来检查是否编写了具有 'Destroy' 操作的版本,但这不会起作用,因为识别特定操作的关键字段可能存在不止一次。这些版本是递增的,可以逐步回滚以获得旧版本,并且我的模型在其 parent.
的生命周期中可能有多个关系标识符
一个解决方案是通过参数在控制器上检查票证是否存在,但验证应该在模型上进行。
我不想使用版本控制 gem。
有人提示如何实现这样的验证吗?
您可以尝试将版本控制逻辑完全封装在您的 Model
class 中,并且完全不访问控制器和模板中的 .versions
关系 .考虑这样的事情:
# model.rb
class Model
has_many :versions
attr_accessor :_current_action, :_ticket_number
validates :_current_action, presence: true
validates :_ticket_number, presence: true
after_create :create_new_version
before_destroy :create_new_version
def set_next_action(action, ticket_number)
self._current_action = action
self._ticket_number = ticket_number
end
private
def create_new_version
unless _current_action.present? && _ticket_number.present?
raise RuntimeError, "Missing versioning action or ticket number"
end
# adjust this to store the actual model data as well
versions.create!(action: _current_action, ticket_number: _ticket_number)
self._current_action = nil
self._ticket_number = nil
end
end
那么,这就是您进行更新的方式:
<!-- edit.html.erb -->
<%= form_for @model, method: :patch do |f| %>
<!-- other fields -->
<%= text_field_tag :_ticket_number, class: "text_field" %>
<%= f.submit "Update model" %>
<% end %>
在控制器中:
# models_controller.rb
def update
@model = Model.find(params[:id])
@model.set_next_action "Update", params[:_ticket_number]
if @model.update(params[:model])
# ...
else
render :edit
end
end
这是删除的方式:
<!-- edit.html.erb -->
<%= form_for @model, method: :delete do |f| %>
<!-- other fields -->
<%= text_field_tag :_ticket_number, class: "text_field" %>
<%= f.submit "Delete model" %>
<% end %>
在控制器中:
# models_controller.rb
def destroy
@model = Model.find(params[:id])
@model.set_next_action "Destroy", params[:_ticket_number]
if @model.valid? # validates presence of ticket number
@model.destroy
# ...
else
render :edit
end
end
注意:我没有测试此代码,因此可能需要进行一些更改才能运行。
我有一个与版本模型 has_many 相关的模型。需要跟踪 parent 模型上的任何操作。在删除表格中,我添加了一个嵌套表格来输入将添加到版本中的票号。如果给出票证,我如何检查模型验证?我将在调用模型上的销毁之前编写版本。
# model.rb
class Model < ActiveRecord::Base
has_many :versions,
:as => :version_object
end
# models_controller.rb
def destroy
@model = Model.find(params[:id])
self.write_versions('Destroy')
@Model.destroy
respond_to do |format|
...
end
end
# delete.html.erb
<%= form_for [@model.parent_object, @model], :html => { :class => 'form-horizontal' }, :method => :delete
do |f| %>
<div class="form-actions">
<%= f.fields_for :versions, @model.versions.build do |v| %>
<%= v.text_field :ticket, {:class => 'text_field', :placeholder => 'Ticket Nummer'}%>
<% end %>
<%= f.submit 'Delete Model', :class => 'btn btn-danger' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
:back, :class => 'btn' %>
</div>
<% end %>
我已经尝试实现 before_destroy 方法来检查是否编写了具有 'Destroy' 操作的版本,但这不会起作用,因为识别特定操作的关键字段可能存在不止一次。这些版本是递增的,可以逐步回滚以获得旧版本,并且我的模型在其 parent.
的生命周期中可能有多个关系标识符一个解决方案是通过参数在控制器上检查票证是否存在,但验证应该在模型上进行。
我不想使用版本控制 gem。
有人提示如何实现这样的验证吗?
您可以尝试将版本控制逻辑完全封装在您的 Model
class 中,并且完全不访问控制器和模板中的 .versions
关系 .考虑这样的事情:
# model.rb
class Model
has_many :versions
attr_accessor :_current_action, :_ticket_number
validates :_current_action, presence: true
validates :_ticket_number, presence: true
after_create :create_new_version
before_destroy :create_new_version
def set_next_action(action, ticket_number)
self._current_action = action
self._ticket_number = ticket_number
end
private
def create_new_version
unless _current_action.present? && _ticket_number.present?
raise RuntimeError, "Missing versioning action or ticket number"
end
# adjust this to store the actual model data as well
versions.create!(action: _current_action, ticket_number: _ticket_number)
self._current_action = nil
self._ticket_number = nil
end
end
那么,这就是您进行更新的方式:
<!-- edit.html.erb -->
<%= form_for @model, method: :patch do |f| %>
<!-- other fields -->
<%= text_field_tag :_ticket_number, class: "text_field" %>
<%= f.submit "Update model" %>
<% end %>
在控制器中:
# models_controller.rb
def update
@model = Model.find(params[:id])
@model.set_next_action "Update", params[:_ticket_number]
if @model.update(params[:model])
# ...
else
render :edit
end
end
这是删除的方式:
<!-- edit.html.erb -->
<%= form_for @model, method: :delete do |f| %>
<!-- other fields -->
<%= text_field_tag :_ticket_number, class: "text_field" %>
<%= f.submit "Delete model" %>
<% end %>
在控制器中:
# models_controller.rb
def destroy
@model = Model.find(params[:id])
@model.set_next_action "Destroy", params[:_ticket_number]
if @model.valid? # validates presence of ticket number
@model.destroy
# ...
else
render :edit
end
end
注意:我没有测试此代码,因此可能需要进行一些更改才能运行。