Muh*_*mbi 1 ruby postgresql activerecord ruby-on-rails
我有一个Rails 4应用程序,其中我有以下代码:
我的_form_html.erb
<%= nested_form_for @store, :html => {:multipart => true, :honeypot => true} do |f| %>
<%= f.text_field :name %>
<% if params[:action] == "new" %>
<textarea name="store[products_attributes][0][product_fields_attributes][0][text_content]"></textarea>
<% else %>
<textarea name="store[products_attributes][0][product_fields_attributes][0][text_content]">VALUE</textarea>
<% end %>
<%= f.submit%>
<% end %>
Run Code Online (Sandbox Code Playgroud)
我的控制器看起来像:
before_action :set_store, only: [:show, :edit, :update, :destroy]
def new
@store = Store.new
end
def edit
end
def create
@store = Store.new(store_params)
respond_to do |format|
if @store.save
format.html { redirect_to @store, notice: 'Store was successfully created.'}
format.json { render action: 'show', status: :created, location: @store }
else
format.html { render action: 'new' }
format.json { render json: @store.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if @store.update(store_params)
format.html { redirect_to @store, notice: 'Store was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @store.errors, status: :unprocessable_entity }
end
end
def set_store
@store = Store.find(params[:id])
end
def store_params
params.require(:store).permit(:name, products_attributes: [:id, { product_fields_attributes: [:id, :text_content] } ])
end
Run Code Online (Sandbox Code Playgroud)
另外我的edit.html.erb看起来像:
<h3>Edit</h1>
<%= render 'form' %>
Run Code Online (Sandbox Code Playgroud)
我的new.html.erb看起来像:
<h3>Add New</h1>
<%= render 'form' %>
Run Code Online (Sandbox Code Playgroud)
点击"更新"时,在我的rails控制台中看起来像:
Started PATCH "/stores/sNx92thyjcP_jw" for 127.0.0.1 at 2014-05-27 17:10:46 -0600
Processing by StoresController#update as HTML
Parameters: {"utf8"=>"?", "authenticity_token"=>"nFUg4ynXYyg99rPPPoa3uO/iHP4LT1XlOz3Vm3Zm4Z0=", "store"=>{"name"=>"Testing", "description"=>"", "products_attributes"=>{"0"=>{"type_of"=>"Book", "product_fields_attributes"=>{"0"=>{"text_content"=>"testing testing testing 1"}}}}}, "commit"=>"Update Store", "token"=>"sNx92thyjcP_jw"}
Site Load (0.7ms) SELECT "stores".* FROM "stores" WHERE "stores"."token" = 'sNx92thyjcP_jw' LIMIT 1
(0.2ms) BEGIN
SQL (0.5ms) INSERT INTO "products" ("created_at", "store_id", "type_of", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["created_at", Tue, 27 May 2014 23:10:46 UTC +00:00], ["store_id", 102], ["type_of", "Book"], ["updated_at", Tue, 27 May 2014 23:10:46 UTC +00:00]]
SQL (0.7ms) INSERT INTO "product_fields" ("created_at", "text_content", "updated_at", "product_id") VALUES ($1, $2, $3, $4) RETURNING "id" [["created_at", Tue, 27 May 2014 23:10:46 UTC +00:00], ["text_content", "testing testing testing 1"], ["updated_at", Tue, 27 May 2014 23:10:46 UTC +00:00], ["product_id", 111]]
(15.5ms) COMMIT
Redirected to http://localhost:3000/products/sNx92thyjcP_jw
Completed 302 Found in 30ms (ActiveRecord: 17.6ms)
Run Code Online (Sandbox Code Playgroud)
我的店铺型号:
class Store < ActiveRecord::Base
before_create :generate_token
has_many :products
accepts_nested_attributes_for :products
def to_param
token
end
private
def generate_token
self.token = loop do
random_token = SecureRandom.urlsafe_base64(10, false)
break random_token unless Store.exists?(token: random_token)
end
end
Run Code Online (Sandbox Code Playgroud)
我的产品型号:
class Product < ActiveRecord::Base
belongs_to :store
has_many :product_fields
accepts_nested_attributes_for :product_fields
end
Run Code Online (Sandbox Code Playgroud)
我的产品领域型号:
class ProductField < ActiveRecord::Base
belongs_to :product
mount_uploader :image_content, ImageUploader
end
Run Code Online (Sandbox Code Playgroud)
但是当你去编辑商店而不是更新时,它会添加一条新记录.例如,在新页面上,您输入textarea"Testing 1",然后保存.然后转到编辑页面并编辑"测试1"为"测试2"的文本区域,然后单击"保存".现在我有两个记录:"测试1"和"测试2".
这里发生了什么?谢谢大家的帮助!
好的,出于某种原因你正在使用nested_form_for帮助器,但你根本没有使用嵌套字段,而是textarea手动编写html用于嵌套,具有固定ID [0]?这就是它总是创建一个新的嵌套字段的原因.保存商店时,它会检查给定的ID是否存在,如果不0存在(例如,id 永远不存在),它将为它创建一个新记录.
在rails中使用嵌套字段实际上非常简单,你应该写
<%= form_for @store, :html => {:multipart => true, :honeypot => true} do |f| %>
<%= f.text_field :name %>
<%= f.fields_for :products do |product| %>
<%= product.text_area :text_content %>
<% end %>
<%= f.submit%>
<% end %>
Run Code Online (Sandbox Code Playgroud)
您目前没有使用任何动态添加(afaik),因此您不需要使用nested_form_for.从例外情况来看,我假设你总是只想要一种产品?
在您的控制器中,您必须更改您的new操作以创建初始产品以使其工作.
def new
@store = Store.new
@store.products.build
end
Run Code Online (Sandbox Code Playgroud)
这将添加一个空/新产品,然后您可以填写.