Ruby on Rails 从一种形式保存在两个表中
Posted
技术标签:
【中文标题】Ruby on Rails 从一种形式保存在两个表中【英文标题】:Ruby on Rails Saving in two tables from one form 【发布时间】:2014-07-14 22:14:24 【问题描述】:我有两个模型 Hotel 和 Address。 关系是:
class Hotel
belongs_to :user
has_one :address
accepts_nested_attributes_for :address
和
class Address
belongs_to :hotel
我需要从一个表格保存在 hotels 表和 addresses 表中。
输入形式很简单:
<%= form_for(@hotel) do |f| %>
<%= f.text_field :title %>
......other hotel fields......
<%= f.fields_for :address do |o| %>
<%= o.text_field :country %>
......other address fields......
<% end %>
<% end %>
酒店管理员:
class HotelsController < ApplicationController
def new
@hotel = Hotel.new
end
def create
@hotel = current_user.hotels.build(hotel_params)
address = @hotel.address.build
if @hotel.save
flash[:success] = "Hotel created!"
redirect_to @hotel
else
render 'new'
end
end
但是这段代码不起作用。
添加 1 个 酒店参数:
private
def hotel_params
params.require(:hotel).permit(:title, :stars, :room, :price)
end
添加 2 个
主要问题是我不知道如何正确呈现表单。此 ^^^ 表单甚至不包括地址字段(国家、城市等)。但是如果在行
<%= f.fields_for :address do |o| %>
我将 :address 更改为 :hotel,我在表单中获得了地址字段,但在这种情况下,:address 表中当然没有保存任何内容。我不明白从 1 个表格中保存 2 个表的原理,非常抱歉,我是 Rails 新手...
【问题讨论】:
能否也提供您的hotel_params
方法。
您能否提供更多关于提交此表单的输出的信息?
@Vapire 当然添加了hotel_params。
@khaled_gomaa,当然,我在 ADD2 中描述了这个表格。
你目前拥有form
的方式是正确的。不要搞砸了。我猜这里的罪魁祸首是你的new
和create
方法。你能试试我的回答吗?说它是否有效。
【参考方案1】:
您使用 wrong method
将您的孩子附加到父母。而且它也是 has_one relation
,所以您应该使用 build_model
不是 model.build
。你的 new
和 create
方法应该是这样的
class HotelsController < ApplicationController
def new
@hotel = Hotel.new
@hotel.build_address #here
end
def create
@hotel = current_user.hotels.build(hotel_params)
if @hotel.save
flash[:success] = "Hotel created!"
redirect_to @hotel
else
render 'new'
end
end
更新
您的hotel_params
方法应如下所示
def hotel_params
params.require(:hotel).permit(:title, :stars, :room, :price,address_attributes: [:country,:state,:city,:street])
end
【讨论】:
感谢您的关注!使用“def new”中的地址 = @hotel.address.build 行,我在此行收到错误:未定义方法 `build' for nil:NilClass when try to access add page.. nil:NilClass 的仍然未定义方法 `build'。 @AlMacks 我已经更新了我的答案。现在应该可以了。 外键呢?我将如何设置地址:hotel_id = 酒店:id?【参考方案2】:你不应该再次建立地址
class HotelsController < ApplicationController
def new
@hotel = Hotel.new
end
def create
@hotel = current_user.hotels.build(hotel_params)
# address = @hotel.address.build
# the previous line should not be used
if @hotel.save
flash[:success] = "Hotel created!"
redirect_to @hotel
else
render 'new'
end
end
【讨论】:
谢谢,khaled_gomaa!【参考方案3】:这里的底线是你需要正确使用f.fields_for
方法。
--
控制器
您需要做几件事才能使该方法发挥作用。首先,您需要构建关联的对象,然后您需要能够以正确的方式将数据传递给您的模型:
#app/models/hotel.rb
Class Hotel < ActiveRecord::Base
has_one :address
accepts_nested_attributes_for :address
end
#app/controllers/hotels_controller.rb
Class HotelsController < ApplicationController
def new
@hotel = Hotel.new
@hotel.build_address #-> build_singular for singular assoc. plural.build for plural
end
def create
@hotel = Hotel.new(hotel_params)
@hotel.save
end
private
def hotel_params
params.require(:hotel).permit(:title, :stars, :room, :price, address_attributes: [:each, :address, :attribute])
end
end
这应该适合你。
--
表格
表单的一些提示 - 如果您正在加载表单并且没有看到 f.fields_for
块显示,这基本上意味着您没有正确设置您的 ActiveRecord Model
(在 new
操作中)
我上面写的(与Pavan
写的非常相似)应该可以为你工作
【讨论】:
@Richard 我看不到 f.fields_for 你能帮我解决这个问题吗? 你在用<%= f.fields_for ...
吗?
外键怎么办?以上是关于Ruby on Rails 从一种形式保存在两个表中的主要内容,如果未能解决你的问题,请参考以下文章
单击时禁用引导表行并将其保存在 Ruby on Rails 中