我正在使用Ruby on Rails构建一个简单的表单来提交订单。
我的表单需要提交来自3种不同模型的信息:用户,catalog_item和订单本身。
这是我的订单模式:
class Order < ApplicationRecord
after_initialize :default_values
validates :quantity, presence: true
belongs_to :user
belongs_to :catalog_item
validates :user_id, presence: true
validates :catalog_item_id, presence: true
accepts_nested_attributes_for :user
validates_associated :user
end
这是我的用户模型:
class User < ApplicationRecord
has_many :orders
end
这是我的控制人员:
class OrdersController < ApplicationController
def checkout
@order = Order.new(catalog_item: CatalogItem.find(params[:catalog_item_id]), user: User.new)
end
def create
@order = Order.new(order_params)
if @order.save
# redirect_to confirmation_path
else
# redirect_to error_path
end
end
private
def user_params
[:name, :email, :phone_number]
end
def order_params
params.require(:order).permit(:id, :catalog_item_id, user_attributes: user_params)
end
end
这是我的观点:
<%= form_for @order do |order_form| %>
<%= order_form.hidden_field :catalog_item_id %>
<%= order_form.fields_for :user do |user_fields| %>
<%= user_fields.label :name %>
<%= user_fields.text_field :name %>
<%= user_fields.label :email %>
<%= user_fields.text_field :email %>
<%= user_fields.label :phone_number %>
<%= user_fields.text_field :phone_number %>
<% end %>
<%= order_form.submit %>
<% end %>
如果表单为HTML:
<form class="new_order" id="new_order" action="/orders" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓"><input type="hidden" name="authenticity_token" value="+z8JfieTzJrNgsr99C4jwBtXqIrpNtiEGPdVi73qJrpiGPpjYzbLwUng+e+yp8nIS/TLODWVFQtZqS/45SUoJQ==">
<input type="hidden" value="1" name="order[catalog_item_id]" id="order_catalog_item_id">
<label for="order_user_attributes_name">Name</label>
<input type="text" name="order[user_attributes][name]" id="order_user_attributes_name">
<label for="order_user_attributes_email">Email</label>
<input type="text" name="order[user_attributes][email]" id="order_user_attributes_email">
<label for="order_user_attributes_phone_number">Phone number</label>
<input type="text" name="order[user_attributes][phone_number]" id="order_user_attributes_phone_number">
<input type="submit" name="commit" value="Create Order" data-disable-with="Create Order">
以下是我的路线:
get 'checkout/:catalog_item_id', to: 'orders#checkout', as: 'checkout'
post 'orders', to: 'orders#create'
当我尝试将@order
保存在操作create
中时,我收到此错误:
#<ActiveModel::Errors:0x007fe95d58b698 @base=#<Order id: nil, quantity: 1, created_at: nil, updated_at: nil, user_id: nil, catalog_item_id: 1>, @messages={:user_id=>["can't be blank"]}, @details={:user_id=>[{:error=>:blank}]}>
但是,如果我这样做,它确实有效:
@catalog_item = CatalogItem.find(order_params[:catalog_item_id])
@user = User.new(order_params[:user_attributes])
@user.save
@order = Order.new(catalog_item: @catalog_item, user: @user)
这是发布表单时在HTTP请求中发送的内容:
order[catalog_item_id]:1
order[user_attributes][name]:Ana
order[user_attributes][email]:ana@gmail.com
order[user_attributes][phone_number]:123123123
commit:Create Order
我是RoR的新手,我不明白为什么order_params没有用户,但它确实有catalog_item_id。
任何帮助都将得到真正的赞赏。谢谢!
答案 0 :(得分:0)
假设您的IdContext.Connection.IOHandler.ReadStream(FS, -1, False)
模型Order
,我的建议 - 轨道最佳实践&#34;解决方案如下:
有关详细信息,请参阅Rails Nested Attributes。基本上嵌套属性的作用是它允许你创建&#34;也只是一个命令中的相关记录(在您的示例中,关联的用户):
belongs_to :user
现在您也可以在创建订单时传递# example code:
Order.create(
catalog_item_id: 1,
user_attributes: {
name: 'Foo',
email: 'foo@bar.com'
}
)
# above will create two records (i.e.):
# 1) <Order id: 1 catalog_item_id: 1>
# 2) <User id: 1, order_id: 1, name: 'Foo', email: 'foo@bar.com'>
作为哈希的一部分,只需将user_attributes
视为请求参数的一部分,请参阅{ {1}}下面。
user_attributes
controller
# app/models/order.rb
belongs_to :user
accepts_nested_attributes_for :user
# from our discussion, the validation needs to be updated into:
validates :user, presence: true
validates :category_item, presence: true
答案 1 :(得分:0)
用户是一个类,因此fields_for :user
为新用户对象创建字段。
尝试拨打order_form.fields_for
而不是fields_for
,将fields_for范围限定为您的订单对象。
答案 2 :(得分:0)
如果您希望用户能够从项目的节目视图创建订单,您可以设置嵌套路线:
resources :catalog_items do
resources :orders, only: [:create]
end
确保你有
class Order < ApplicationRecord
belongs_to :user
belongs_to :catalog_item_id
accepts_nested_attributes_for :user
validates_associated :user # triggers user validations
end
class CatalogItem
has_many :orders
end
然后你可以这样做:
# /app/views/orders/_form.html.erb
<%= form_for [@catalog_item, @order || @catalog_item.orders.new] do |order_form| %>
<%= order_form.fields_for :user do |user_fields| %>
<%= user_fields.label :name %>
<%= user_fields.text_field :name %>
<%= user_fields.label :email %>
<%= user_fields.text_field :email %>
<%= user_fields.label :phone_number %>
<%= user_fields.text_field :phone_number %>
<% end %>
<%= order_form.submit %>
<% end %>
# /app/views/catalog_items/show
<%= render partial: 'orders/form' %>
这会将表单网址设置为/catalog_items/:catalog_item_id/orders
。这意味着我们通过URL传递catalog_item_id
而不是表格参数 -
- 这是一种更好的做法,因为它使路线具有描述性和RESTful。
然后设置控制器:
class OrderController
# POST /catalog_items/:catalog_item_id/orders
def create
@catalog_item = CatalogItem.find(params[:catalog_item_id])
@order = @catalog_item.orders.new(order_params)
# Uncomment the next line if you have some sort of authentication like Devise
# @order.user = current_user if user_signed_in?
if @order.save
redirect_to @catalog_item, success: 'Thank you for your order'
else
render 'catalog_items/show' # render show view with errors.
end
end
# ...
private
def user_params
[:name, :email, :phone_number]
end
def order_params
params.require(:order)
.permit(:id, user_attributes: user_params)
end
end