gpt4 book ai didi

ruby-on-rails - 多模型保存,如何包装交易和报告错误

转载 作者:行者123 更新时间:2023-12-04 04:24:42 25 4
gpt4 key购买 nike

我有一个注册表单模型,可以在注册过程中接受用户的输入:

class RegForm
include ActiveModel::Model
include ActiveModel::Validations

attr_accessor :company_name, :email, :password
validates_presence_of # ...

end

在此注册过程中,我需要创建多个模型,并且不确定如何正确显示错误消息以及如何将模型错误消息冒泡回UI。
if @reg_form.valid?
account = Account.create!(@reg_form)
else
...

Account.create!好像:
def self.create!(reg_form)
account = Account.create_from_reg!(reg_form)
location = location.create_from_reg!(account, reg_form)
..
..
account.location = location
..
account.save!

account
end
  • 所以我很困惑如何显示所有保存
  • 的模型的错误消息
  • 如果reg_form没有所有其他模型的正确数据,则如何显示或验证失败。
  • 如何确保将其包装在事务中,因此如果在注册过程中无法保存任何模型,则我不会保存任何内容。
  • 最佳答案

    让我们从头开始。

    我们希望我们的注册表单对象具有与任何其他ActiveRecord模型相同的API:

    // view.html
    <%= form_for(@book) do |f| %>
    <% end %>

    # controller.rb
    def create
    @book = Book.new(book_params)

    if @book.save
    redirect_to @book, notice: 'Book was successfully created.'
    else
    render :new
    end
    end

    为此,我们创建以下对象:
    class RegForm
    include ActiveModel::Model

    attr_accessor :company_name, :email, :password

    def save
    # Save Location and Account here
    end
    end

    现在,通过包含 ActiveModel::Model,我们的 RegForm获得了大量功能,包括显示错误和验证属性(是的,没有必要包含 ActiveModel::Validations)。在下一步中,我们添加一些验证:
    validates :email, :password, presence: true

    然后我们更改 save,以便 运行这些验证:
    def save
    validate
    # Save Location and Account here
    end

    如果所有验证均通过, validate返回 true,否则返回 false
    validate还将 errors添加到 @reg_form中(所有ActiveRecord模型都具有一个 errors哈希,当验证失败时,将填充该哈希)。这意味着在 View 中我们可以执行以下任何操作:
    @reg_form.errors.messages
    #=> { email: ["can't be blank"], password: ["can't be blank"] }

    @reg_form.errors.full_messages
    #=> ["Email can't be blank", "Password can't be blank"]

    @reg_form.errors[:email]
    #=> ["can't be blank"]

    @reg_form.errors.full_messages_for(:email)
    #=> ["Email can't be blank"]

    同时,我们的 RegistrationsController应该看起来像这样:
    def create
    @reg_form = RegForm.new(reg_params)

    if @reg_form.save
    redirect_to @reg_form, notice: 'Registration was successful'
    else
    render :new
    end
    end

    我们可以清楚地看到,当 @reg_form.save返回 false时,将重新呈现 new View 。

    最后,我们更改 save,以便将我们的模型 save调用包装在 transaction中:
    def save
    if valid?
    ActiveRecord::Base.transaction do
    location = Location.create!(location_params)
    account = location.create_account!(account_params)
    end
    true
    end
    rescue ActiveRecord::StatementInvalid => e
    # Handle database exceptions not covered by validations.
    # e.message and e.cause.message can help you figure out what happened
    end

    值得注意的要点:
  • 使用create!代替create。仅在引发异常时才回退transaction(通常使用带有bang的方法)。
  • validate is just an alias for valid? 。为了避免所有缩进,我们可以改为在save方法的顶部使用一个保护措施:
    return if invalid?
  • 我们可以通过执行以下操作将数据库异常(like an email uniqueness constraint)转换为错误:
    rescue ActiveRecord::RecordNotUnique
    errors.add(:email, :taken)
    end
  • 我们可以使用符号 :base 添加不直接与属性相关的错误:
    errors.add(:base, 'Company and Email do not match')
  • 关于ruby-on-rails - 多模型保存,如何包装交易和报告错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38689867/

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