gpt4 book ai didi

ruby-on-rails - 如何在rails中冒泡异常

转载 作者:行者123 更新时间:2023-12-02 00:12:31 26 4
gpt4 key购买 nike

Rails 新手,遇到一些关于最佳实践错误处理的问题。

我在/lib 文件夹中的帮助程序中有以下代码,用于将优惠券应用于某些定价。

正如您从下面的代码中看到的那样,我正在尝试几种不同的方法来返回任何错误。具体来说,model.errors.add 和 flash[:error]。

一旦应用了有效的优惠券,下面的代码应该会返回一个新价格。我不确定在发生错误时要返回什么?我不能像下面那样返回 false,因为这个方法实际上应该返回一个数值,而不是一个 bool 值。从 lib/helper 向 View 冒泡并停止执行的最佳方法是什么?

def calc_coupon transaction_price, discount_code, current_tenant
coupon = Coupon.where(code: discount_code, tenant_id: current_tenant.id).first

if coupon.nil?
current_tenant.errors.add :base, "No such coupon exists"
return false
else
if coupon.maxed? || coupon.expired?
flash[:error] = "This coupon is no longer valid."
return false
else
transaction_price = coupon.calculate(transaction_price)
end
end
return transaction_price
end

最佳答案

我认为您走在正确的 rails 上,但您正在苦苦挣扎,因为您将 View 逻辑与业务逻辑混合在一起。
忘记辅助类并将功能添加到您的模型中。

通过将验证添加到模型而不是辅助类并将错误添加到基础您的 Controller 操作将能够在尝试以正常方式保存/创建记录时处理错误,从而“冒泡错误”

例如

    class MyModel < ActiveRecord ...
validate :validate_coupon
protected
def validate_coupon
# add your validations here - call your boolean check which adds errors to the model
# if validations are ok then calculate your transaction price here
end
end

如果您将检查作为模型上的公共(public)方法,则可以从任何地方调用它们,即从 View 中
因此,您的模型上首先检查错误并设置价格的公共(public) transaction_price 方法可以在这样的 View 中使用
<%= @some_object.transaction_price %>

正如我之前所说,因为验证是在模型中添加的,那么您的 Controller 操作只需要检查调用的值以保存并在返回 false 时正常闪烁错误,因此根本不需要在 Controller 操作中执行任何自定义操作.只是默认的脚手架行为。

您可以使用大量的验证选项。看一下
http://guides.rubyonrails.org/active_record_validations_callbacks.html

希望这是有道理的。

更新回应评论

1)你有很多地方。这只是一个建议,您可以计算交易价格作为验证的一部分。如果这不符合您的要求,那很好。我只是想给你最适合你的问题。问题是你应该有两个单独的实例方法,然后你可以从任何你想要的地方调用它们,这使得实验和移动东西变得更加简单。使用您建议的解决方案很好:)

2) 仔细查看脚手架 Controller 和 View 。您将使用 if 语句看到保存/更新如何失败(如果您在验证过程中添加错误,它们将自动失败),您将看到 _form 部分如何显示错误

这是处理我正在开发的应用程序中的引擎的表单示例。
<%= form_for(@engine) do |f| %>
<% if @engine.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@engine.errors.count, "error") %> prohibited this engine from being saved:</h2>

<ul>
<% @engine.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>

基本上,它正在检查错误并遍历它们(如果存在)以显示它们。

要处理 Flash 消息,您应该使用应用程序主布局
以下代码将在名为“info”的 div 中显示 flash 消息,您可以根据需要设置样式
  <% unless flash.empty? %>
<div class="info">
<%- flash.each do |name, msg| -%>
<%= content_tag :div, msg, :id => "flash_#{name}" %>
<%- end -%>
</div>
<% end %>

通过将它放在 view/layouts 文件夹中 application.html.erb 的 main yield 之前,您可以确保无论呈现什么页面,flash 消息都将始终显示给用户

当然,如果您正在显示 Flash 消息,那么也许您不需要显示错误。有时两者都是正确的做法,有时只是其中一个或另一个很好。这取决于您根据具体情况决定。

主要的是 HTTP POST 或 HTTP PUT(创建或更新操作)的接收操作处理您认为合适的使用或不使用闪存保存的失败
例如
一个创建 Action
  def create
@engine = Engine.new(params[:engine])

respond_to do |format|
if @engine.save
format.html { redirect_to @engine, notice: 'Engine was successfully created.' }
format.json { render json: @engine, status: :created, location: @engine }
else
flash.now[:notice] = "Failed to save!" # flash.now because we are rendering. flash[:notice] if using a redirect
format.html { render action: "new" }
format.json { render json: @engine.errors, status: :unprocessable_entity }
end
end
end

希望这能说明问题

更新 2
忘了说 flash 只是一个散列,它使用 session cookie,所以你可以设置任何你喜欢的键
例如
flash.now[:fred]

如果您希望通过添加代码来处理特定 View 中的 :fred 键(或您选择的名称)的代码与应用程序布局提供的样式不同,这将使您能够在特定 View 中设置和处理特定 fred 通知的样式

关于ruby-on-rails - 如何在rails中冒泡异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14679785/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com