ruby-on-rails - Rails 6在渲染中传递参数:保存失败后的新参数
问题描述
我在负责创建新Transaction
记录的控制器中有一个标准的创建方法。交易记录有一个必填字段,我将其隐藏在视图中,并通过传递一个 params[:filter] 自动为其分配一个值,因此我对交易和交易transaction_type
都有一个 _form ,如下所示:withdrawal
deposit
#index.html.erb
<%= link_to 'Add funds', new_transaction_path(filter: 'deposit') %>
<%= link_to 'Withdraw Funds', new_transaction_path(filter: 'withdrawal') %>
#new.html.erb
<%= render 'form', transaction: @transaction, transaction_type: params[:filter] %>
#_form.html.erb
<%= simple_form_for @transaction do |f| %>
<%= f.error_notification %>
<%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>
<%= f.text_field :transaction_type, value: transaction_type, type: "hidden" %>
<%= f.input :amount, placeholder: 'Amount', label: false %>
<%= f.button :submit, 'Submit' %>
<% end %>
如果由于某种原因验证失败,为了正确显示错误,将呈现 :new 视图。不幸的是,在这种情况下,如果用户再次填写整个表单(在第一次失败后),将不会创建记录,因为 params[:filter] 没有传递。有没有办法将原始 params[:filter] 直接传递给视图?
#controller
# POST /transactions
def create
@transaction = wallet.transactions.new(transaction_params)
if @transaction.save
redirect_to :index, notice: 'Transaction was successfully created.'
else
render :new
end
end
解决方案
虽然我了解重用视图代码的方面,但您确实应该考虑创建单独的路由和控制器,并通过使用继承和局部变量而不是通过隐藏参数来解决代码重复问题。
resources :deposits, :withdrawls, only: [:new, :create]
class TransactionsController < ApplicationController
helper_method :create_transaction_path
def new
@transaction = Transaction.new
render 'transactions/new'
end
def create
@transaction = Transaction.new(transaction_params) do |t|
t.transaction_type = transaction_type
end
if @transaction.save
yield @transaction if block_given?
success_response
else
yield @transaction if block_given?
failure_response
end
end
private
def transaction_type
controller_name.singularize
end
def create_transaction_path
polymorphic_path(controller_name)
end
def transaction_params
params.require(:transaction)
.permit(:foo, :bar, :baz)
end
def success_response
redirect_to transactions_path,
notice: 'Transaction was successfully created.'
end
def failure_response
render 'transactions/new'
end
end
class DepositsController < TransactionsController
# POST /deposits
def create
super do |transaction|
# do something just when making a deposit
end
end
end
class WithdrawlsController < TransactionsController
# POST /withdrawls
def create
super do |transaction|
# do something just when making a withdrawl
end
end
end
# app/views/transactions/_form.html.erb
<%= simple_form_for transaction, url: create_transaction_path do |f| %>
<%= f.error_notification %>
<%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>
<%= f.input :amount %> # Do not use placeholders instead of labels
<%= f.button :submit, 'Submit' %>
<% end %>
<%= link_to 'Add funds', new_deposit_path %>
<%= link_to 'Withdraw Funds', new_withdrawl_path %>
为什么?
因为它为您提供了完成一项工作的端点,并且当需求出现分歧时,它还为您提供了明显的代码结构,因为它们肯定会发生分歧。
推荐阅读
- javascript - Now.sh 构建中断,原因是:当前未启用对实验性语法“decorators-legacy”的支持
- ios - CloudKit - 公共和私有数据库 - 消息传递平台
- ruby - 向我正在创建的 ruby 哈希添加密钥
- solr - Lucene Solr 自定义标记器 - 如何将分隔符特殊字符包含为标记?
- typescript - 如何修复 VSCode 中的“‘CombinedVueInstance’类型上不存在属性 XX”错误?(带有打字稿的Vue)
- bash - 如何复制一列?
- ruby-on-rails - 有没有更安全的方法可以同时使用 Stripe 和 ActiveMerchant?Ruby on Rails
- java - 基于json中属性的自定义序列化
- angular - canActivate 和 canDeactivate 不能一起工作
- kubernetes - 将 docker 图像作为二进制文件保存在 helm 图表中