用茧制作的嵌套字段不保存
Nested fields made with cocoon are not saving
我有 3 个对象,用户、食谱和任务。任务嵌套在食谱中,食谱嵌套在用户中。我可以 save/add/delete 食谱就好了,我可以在 HTML 表格中添加任务,但是当我去保存时,任务不会显示为食谱的一部分,即使我去回到表格。我已经为此工作了一段时间,非常感谢任何见解。
用户控制器:
class UsersController < ApplicationController
before_filter :authenticate_user_or_admin_or_conduit!
before_action :set_user, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
@users = User.all
respond_with(@users)
end
def show
respond_with(@user)
end
def new
@user = User.new
respond_with(@user)
end
def edit
end
def create
@user = User.new(user_params)
if @user.save
if conduit_signed_in?
redirect_to '/conduits', notice: 'User created successfully.'
elsif admin_signed_in?
redirect_to '/admins', notice: 'User created successfully.'
else
redirect_to @user, notice: 'User created successfully.'
end
else
render :new
end
end
def update
@user.update(user_params)
respond_with(@user)
end
def destroy
@user.destroy
respond_with(@user)
end
private
def set_user
@user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
end
配方控制器:
class RecipesController < ApplicationController
before_action :set_recipe, only: [:show, :edit, :update, :destroy]
# GET /recipes
# GET /recipes.json
def index
@recipes = Recipe.all
end
# GET /recipes/1
# GET /recipes/1.json
def show
end
# GET /recipes/new
def new
@recipe = Recipe.new
end
# GET /recipes/1/edit
def edit
end
# POST /recipes
# POST /recipes.json
def create
@recipe = Recipe.new(recipe_params)
respond_to do |format|
if @recipe.save
format.html { redirect_to @recipe, notice: 'Recipe was successfully created.' }
format.json { render :show, status: :created, location: @recipe }
else
format.html { render :new }
format.json { render json: @recipe.errors, status: :unprocessable_entity }
end
end
class UsersController < ApplicationController
before_filter :authenticate_user_or_admin_or_conduit!
before_action :set_user, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
@users = User.all
respond_with(@users)
end
def show
respond_with(@user)
end
def new
@user = User.new
respond_with(@user)
end
def edit
end
def create
@user = User.new(user_params)
if @user.save
if conduit_signed_in?
redirect_to '/conduits', notice: 'User created successfully.'
elsif admin_signed_in?
redirect_to '/admins', notice: 'User created successfully.'
else
redirect_to @user, notice: 'User created successfully.'
end
else
render :new
end
end
def update
@user.update(user_params)
respond_with(@user)
end
def destroy
@user.destroy
respond_with(@user)
end
private
def set_user
@user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
end
配方控制器:
class RecipesController < ApplicationController
before_action :set_recipe, only: [:show, :edit, :update, :destroy]
# GET /recipes
# GET /recipes.json
def index
@recipes = Recipe.all
end
# GET /recipes/1
# GET /recipes/1.json
def show
end
# GET /recipes/new
def new
@recipe = Recipe.new
end
# GET /recipes/1/edit
def edit
end
# POST /recipes
# POST /recipes.json
def create
@recipe = Recipe.new(recipe_params)
end
# PATCH/PUT /recipes/1
# PATCH/PUT /recipes/1.json
def update
respond_to do |format|
if @recipe.update(recipe_params)
format.html { redirect_to @recipe, notice: 'Recipe was successfully updated.' }
format.json { render :show, status: :ok, location: @recipe }
else
format.html { render :edit }
format.json { render json: @recipe.errors, status: :unprocessable_entity }
end
end
end
# DELETE /recipes/1
# DELETE /recipes/1.json
def destroy
@recipe.destroy
respond_to do |format|
format.html { redirect_to recipes_url, notice: 'Recipe was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_recipe
@recipe = Recipe.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def recipe_params
params.require(:recipe).permit(:reward, task_attributes: [:description, :counter, :done, :_destroy, :id])
end
end
任务控制器:
class TasksController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
# GET /tasks
# GET /tasks.json
def index
@tasks = Task.all
end
# GET /tasks/1
# GET /tasks/1.json
def show
end
# GET /tasks/new
def new
@task = Task.new
end
# GET /tasks/1/edit
def edit
end
# POST /tasks
# POST /tasks.json
def create
@task = Task.new(task_params)
respond_to do |format|
if @task.save
format.html { redirect_to @task, notice: 'Task was successfully created.' }
format.json { render :show, status: :created, location: @task }
else
format.html { render :new }
format.json { render json: @task.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tasks/1
# PATCH/PUT /tasks/1.json
def update
respond_to do |format|
if @task.update(task_params)
format.html { redirect_to @task, notice: 'Task was successfully updated.' }
format.json { render :show, status: :ok, location: @task }
else
format.html { render :edit }
format.json { render json: @task.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tasks/1
# DELETE /tasks/1.json
def destroy
@task.destroy
respond_to do |format|
format.html { redirect_to tasks_url, notice: 'Task was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_task
@task = Task.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def task_params
params.require(:task).permit(:description, :counter, :done, :notes)
end
end
用户模型:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :characters
end
食谱型号:
class Recipe < ActiveRecord::Base
belongs_to :character
has_many :task, :dependent => :destroy
accepts_nested_attributes_for :task, allow_destroy: true
end
任务模型:
class Task < ActiveRecord::Base
belongs_to :recipe
end
用户表单:
<div id="myform">
<%= form_for(@character) do |f| %>
<% if @character.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@character.errors.count, "error") %> prohibited this character from being saved:</h2>
<ul>
<% @character.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<li class="accordion-navigation">
<a href="#panel6a">Recipes</a>
<div id="panel6a" class="content">
<fieldset>
<legend>Recipes consist of a variety of tasks</legend>
<div>
<%= f.fields_for :recipe do |recipe| %>
<%= render "recipe_fields", :f => recipe %>
<% end %>
<div class="links">
<%= link_to_add_association "Add Recipe", f, :recipe, :class =>"button" %>
</div>
</div>
</fieldset>
</div>
</li>
<% end %>
</div>
配方表:
<div class="nested-fields">
<div class="row">
<div class="row">
<div class="large-3 columns">
<div class="field">
<%= f.text_field :reward %>
</div>
</div>
<div class="large-9 columns">
<fieldset>
<legend>Add Task</legend>
<div>
<%= f.fields_for :task do |task| %>
<%= render "task_fields", :f => task %>
<% end %>
<div class="links">
<%= link_to_add_association "Add Task", f, :task, :class =>"small button" %>
</div>
</div>
</fieldset>
<span style="float:right"><%= link_to_remove_association "Remove Recipe", f, data: {confirm: "Are you sure?"}, :class =>"button alert" %></span>
</div>
</div>
</div>
</div>
任务表:
<div class="nested-fields">
<div class="row">
<div class="large-3 columns">
<div class="field">
<%= f.text_field :description %>
</div>
</div>
<div class="large-3 columns">
<div class="field">
<%= f.number_field :counter, label: "Record number if needed" %>
</div>
</div>
<div class="large-3 columns">
<div class="field">
<%= f.check_box :done, label: "Completed?" %>
</div>
</div>
<span style="float:right"><%= link_to_remove_association "Remove Task", f, data: {confirm: "Are you sure?"}, :class =>"small button alert" %></span>
</div>
</div>
我最近处理了这个问题。我猜正在创建任务,只是与食谱无关。如果是这种情况,您需要在 task_attributes
数组中包含 recipe_id
。
嵌套是一种魔法,但无论出于何种原因,父对象的 ID 都不会被设置,除非它被明确包含为允许的参数。
希望对您有所帮助!
另一个 post 肯定指出了一个错误,但我无法修复它,直到我将 task_attributes 添加到用户控制器中的 recipe_attributes,如下所示:
params.require(:user).permit(:name, recipe_attributes: [:reward, :_destroy, :user_id, :id, task_attributes: [:description, :recipe_id, :counter, :done, :_destroy, :id]])
我有 3 个对象,用户、食谱和任务。任务嵌套在食谱中,食谱嵌套在用户中。我可以 save/add/delete 食谱就好了,我可以在 HTML 表格中添加任务,但是当我去保存时,任务不会显示为食谱的一部分,即使我去回到表格。我已经为此工作了一段时间,非常感谢任何见解。
用户控制器:
class UsersController < ApplicationController
before_filter :authenticate_user_or_admin_or_conduit!
before_action :set_user, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
@users = User.all
respond_with(@users)
end
def show
respond_with(@user)
end
def new
@user = User.new
respond_with(@user)
end
def edit
end
def create
@user = User.new(user_params)
if @user.save
if conduit_signed_in?
redirect_to '/conduits', notice: 'User created successfully.'
elsif admin_signed_in?
redirect_to '/admins', notice: 'User created successfully.'
else
redirect_to @user, notice: 'User created successfully.'
end
else
render :new
end
end
def update
@user.update(user_params)
respond_with(@user)
end
def destroy
@user.destroy
respond_with(@user)
end
private
def set_user
@user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
end
配方控制器:
class RecipesController < ApplicationController
before_action :set_recipe, only: [:show, :edit, :update, :destroy]
# GET /recipes
# GET /recipes.json
def index
@recipes = Recipe.all
end
# GET /recipes/1
# GET /recipes/1.json
def show
end
# GET /recipes/new
def new
@recipe = Recipe.new
end
# GET /recipes/1/edit
def edit
end
# POST /recipes
# POST /recipes.json
def create
@recipe = Recipe.new(recipe_params)
respond_to do |format|
if @recipe.save
format.html { redirect_to @recipe, notice: 'Recipe was successfully created.' }
format.json { render :show, status: :created, location: @recipe }
else
format.html { render :new }
format.json { render json: @recipe.errors, status: :unprocessable_entity }
end
end
class UsersController < ApplicationController
before_filter :authenticate_user_or_admin_or_conduit!
before_action :set_user, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
@users = User.all
respond_with(@users)
end
def show
respond_with(@user)
end
def new
@user = User.new
respond_with(@user)
end
def edit
end
def create
@user = User.new(user_params)
if @user.save
if conduit_signed_in?
redirect_to '/conduits', notice: 'User created successfully.'
elsif admin_signed_in?
redirect_to '/admins', notice: 'User created successfully.'
else
redirect_to @user, notice: 'User created successfully.'
end
else
render :new
end
end
def update
@user.update(user_params)
respond_with(@user)
end
def destroy
@user.destroy
respond_with(@user)
end
private
def set_user
@user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
end
配方控制器:
class RecipesController < ApplicationController
before_action :set_recipe, only: [:show, :edit, :update, :destroy]
# GET /recipes
# GET /recipes.json
def index
@recipes = Recipe.all
end
# GET /recipes/1
# GET /recipes/1.json
def show
end
# GET /recipes/new
def new
@recipe = Recipe.new
end
# GET /recipes/1/edit
def edit
end
# POST /recipes
# POST /recipes.json
def create
@recipe = Recipe.new(recipe_params)
end
# PATCH/PUT /recipes/1
# PATCH/PUT /recipes/1.json
def update
respond_to do |format|
if @recipe.update(recipe_params)
format.html { redirect_to @recipe, notice: 'Recipe was successfully updated.' }
format.json { render :show, status: :ok, location: @recipe }
else
format.html { render :edit }
format.json { render json: @recipe.errors, status: :unprocessable_entity }
end
end
end
# DELETE /recipes/1
# DELETE /recipes/1.json
def destroy
@recipe.destroy
respond_to do |format|
format.html { redirect_to recipes_url, notice: 'Recipe was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_recipe
@recipe = Recipe.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def recipe_params
params.require(:recipe).permit(:reward, task_attributes: [:description, :counter, :done, :_destroy, :id])
end
end
任务控制器:
class TasksController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
# GET /tasks
# GET /tasks.json
def index
@tasks = Task.all
end
# GET /tasks/1
# GET /tasks/1.json
def show
end
# GET /tasks/new
def new
@task = Task.new
end
# GET /tasks/1/edit
def edit
end
# POST /tasks
# POST /tasks.json
def create
@task = Task.new(task_params)
respond_to do |format|
if @task.save
format.html { redirect_to @task, notice: 'Task was successfully created.' }
format.json { render :show, status: :created, location: @task }
else
format.html { render :new }
format.json { render json: @task.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tasks/1
# PATCH/PUT /tasks/1.json
def update
respond_to do |format|
if @task.update(task_params)
format.html { redirect_to @task, notice: 'Task was successfully updated.' }
format.json { render :show, status: :ok, location: @task }
else
format.html { render :edit }
format.json { render json: @task.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tasks/1
# DELETE /tasks/1.json
def destroy
@task.destroy
respond_to do |format|
format.html { redirect_to tasks_url, notice: 'Task was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_task
@task = Task.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def task_params
params.require(:task).permit(:description, :counter, :done, :notes)
end
end
用户模型:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :characters
end
食谱型号:
class Recipe < ActiveRecord::Base
belongs_to :character
has_many :task, :dependent => :destroy
accepts_nested_attributes_for :task, allow_destroy: true
end
任务模型:
class Task < ActiveRecord::Base
belongs_to :recipe
end
用户表单:
<div id="myform">
<%= form_for(@character) do |f| %>
<% if @character.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@character.errors.count, "error") %> prohibited this character from being saved:</h2>
<ul>
<% @character.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<li class="accordion-navigation">
<a href="#panel6a">Recipes</a>
<div id="panel6a" class="content">
<fieldset>
<legend>Recipes consist of a variety of tasks</legend>
<div>
<%= f.fields_for :recipe do |recipe| %>
<%= render "recipe_fields", :f => recipe %>
<% end %>
<div class="links">
<%= link_to_add_association "Add Recipe", f, :recipe, :class =>"button" %>
</div>
</div>
</fieldset>
</div>
</li>
<% end %>
</div>
配方表:
<div class="nested-fields">
<div class="row">
<div class="row">
<div class="large-3 columns">
<div class="field">
<%= f.text_field :reward %>
</div>
</div>
<div class="large-9 columns">
<fieldset>
<legend>Add Task</legend>
<div>
<%= f.fields_for :task do |task| %>
<%= render "task_fields", :f => task %>
<% end %>
<div class="links">
<%= link_to_add_association "Add Task", f, :task, :class =>"small button" %>
</div>
</div>
</fieldset>
<span style="float:right"><%= link_to_remove_association "Remove Recipe", f, data: {confirm: "Are you sure?"}, :class =>"button alert" %></span>
</div>
</div>
</div>
</div>
任务表:
<div class="nested-fields">
<div class="row">
<div class="large-3 columns">
<div class="field">
<%= f.text_field :description %>
</div>
</div>
<div class="large-3 columns">
<div class="field">
<%= f.number_field :counter, label: "Record number if needed" %>
</div>
</div>
<div class="large-3 columns">
<div class="field">
<%= f.check_box :done, label: "Completed?" %>
</div>
</div>
<span style="float:right"><%= link_to_remove_association "Remove Task", f, data: {confirm: "Are you sure?"}, :class =>"small button alert" %></span>
</div>
</div>
我最近处理了这个问题。我猜正在创建任务,只是与食谱无关。如果是这种情况,您需要在 task_attributes
数组中包含 recipe_id
。
嵌套是一种魔法,但无论出于何种原因,父对象的 ID 都不会被设置,除非它被明确包含为允许的参数。
希望对您有所帮助!
另一个 post 肯定指出了一个错误,但我无法修复它,直到我将 task_attributes 添加到用户控制器中的 recipe_attributes,如下所示:
params.require(:user).permit(:name, recipe_attributes: [:reward, :_destroy, :user_id, :id, task_attributes: [:description, :recipe_id, :counter, :done, :_destroy, :id]])