Rails:2 个模型,1 个table。单独的表单+控制器。活动记录验证错误后表单呈现错误 model/incorrectly
Rails: 2 models, 1 table. Separate forms + controllers. After active record validation errors form renders wrong model/incorrectly
我有 2 个模型(pass
和 subscription
)、2 个控制器和 2 个表单。这些模型共享一个数据库 table。
共享的 table 是 passes
。要判断一条记录是否为 subscription
,有一列 is_subscription
。因此,我的 subscription
模型有以下内容:
self.table_name = :passes
default_scope { where(is_subscription: true) }
validates :name, presence: true
注意 name
上的验证。
subscription
形式:
<%= form_for(@subscription, html: {class: "my-class"}) do |f| %>
呈现:
<form class="form-horizontal" id="new_subscription" action="/subscriptions" accept-charset="UTF-8" method="post">
<input class="form-control" type="text" name="subscription[name]" id="subscription_name">
...
在控制器中:
def show
end
def new
@subscription = Subscription.new
end
def create
@subscription = current_user.company.passes.new(subscription_params)
if @subscription.save
redirect_to subscription_path(@subscription), notice: "Yay"
else
render :new
end
end
一切正常。但是,如果我尝试创建一个新订阅并从表单中省略 name
- 这会触发活动记录验证和错误。表单重新呈现,现在已更改:
<form class="form-horizontal" id="new_pass" action="/passes" accept-charset="UTF-8" method="post">
<input class="form-control" type="text" value="" name="pass[name]" id="pass_name">
...
我已经尝试设置 as: "subscription"
来修复除了动作之外的所有问题。如果我设置 action:
操作仍然被覆盖。
希望对如何最好地处理此问题有一些见解。不幸的是,我没有能力改变 table 的情况(即使用单独的 tables)。
您可以使用 form_tag
而不是 form_for
。前者不关心正在使用的模型对象——事实上你甚至不传递它。这将要求你使用通用的 text_field_tag
等助手而不是你可能会使用的 form.text_field :foo
现在正在使用。
但它可以让你回避这个问题。
我不知道你为什么在提交订阅时创建一个通行证(你说你有 2 个控制器,但看起来你只为两个控制器使用一个控制器(?))。
如果无法保存通行证,我会设置一个订阅对象:
def create
@subscription = Pass.new(subscription_params)
if @subscription.save
redirect_to subscription_path(@subscription), notice: "Yay"
else
@subscription = Subscription.new(subscription_params)
render :new
end
end
这样您就可以订阅您正在使用的变量。
编辑:另外,检查 activerecord 对单一 Table 继承的支持,它可以帮助您清理模型 https://edgeguides.rubyonrails.org/association_basics.html#single-table-inheritance
我有 2 个模型(pass
和 subscription
)、2 个控制器和 2 个表单。这些模型共享一个数据库 table。
共享的 table 是 passes
。要判断一条记录是否为 subscription
,有一列 is_subscription
。因此,我的 subscription
模型有以下内容:
self.table_name = :passes
default_scope { where(is_subscription: true) }
validates :name, presence: true
注意 name
上的验证。
subscription
形式:
<%= form_for(@subscription, html: {class: "my-class"}) do |f| %>
呈现:
<form class="form-horizontal" id="new_subscription" action="/subscriptions" accept-charset="UTF-8" method="post">
<input class="form-control" type="text" name="subscription[name]" id="subscription_name">
...
在控制器中:
def show
end
def new
@subscription = Subscription.new
end
def create
@subscription = current_user.company.passes.new(subscription_params)
if @subscription.save
redirect_to subscription_path(@subscription), notice: "Yay"
else
render :new
end
end
一切正常。但是,如果我尝试创建一个新订阅并从表单中省略 name
- 这会触发活动记录验证和错误。表单重新呈现,现在已更改:
<form class="form-horizontal" id="new_pass" action="/passes" accept-charset="UTF-8" method="post">
<input class="form-control" type="text" value="" name="pass[name]" id="pass_name">
...
我已经尝试设置 as: "subscription"
来修复除了动作之外的所有问题。如果我设置 action:
操作仍然被覆盖。
希望对如何最好地处理此问题有一些见解。不幸的是,我没有能力改变 table 的情况(即使用单独的 tables)。
您可以使用 form_tag
而不是 form_for
。前者不关心正在使用的模型对象——事实上你甚至不传递它。这将要求你使用通用的 text_field_tag
等助手而不是你可能会使用的 form.text_field :foo
现在正在使用。
但它可以让你回避这个问题。
我不知道你为什么在提交订阅时创建一个通行证(你说你有 2 个控制器,但看起来你只为两个控制器使用一个控制器(?))。
如果无法保存通行证,我会设置一个订阅对象:
def create
@subscription = Pass.new(subscription_params)
if @subscription.save
redirect_to subscription_path(@subscription), notice: "Yay"
else
@subscription = Subscription.new(subscription_params)
render :new
end
end
这样您就可以订阅您正在使用的变量。
编辑:另外,检查 activerecord 对单一 Table 继承的支持,它可以帮助您清理模型 https://edgeguides.rubyonrails.org/association_basics.html#single-table-inheritance