如何在Rails 4上编辑/更新嵌套资源?

时间:2014-08-03 01:47:59

标签: ruby-on-rails rails-activerecord

我正在尝试为简单的Rails 4.1待办事项列表应用程序设置编辑/更新操作。 具体来说,我希望能够编辑和更新与“用户”资源相关联并嵌套的资源“项目”。目前我收到以下错误。

分配属性时,必须将哈希作为参数传递。

  respond_to do |format|
    if @project.update_attributes(params[:project]) -------> error is in this line
       format.html { redirect_to([@project.user, @project], :notice => 'project was    successfully updated.') }
    format.xml  { head :ok }

这是我的代码: 路线:

Rails.application.routes.draw do

  resources :users

  resources :users do
    resources :projects
  end

  root 'welcome#index'
end

Users_controller:

class UsersController < ApplicationController

    def index
        @users=User.all
    end

    def new
        @user= User.new
    end

    def create
      @user = User.new(user_params)

      @user.save
      redirect_to @user
    end

    def show
        @user=User.find(params[:id])
    end

    def update
      @user = User.find(params[:id])

      if @user.update(user_params)
        redirect_to @user
      else
        render 'edit'
      end
    end

    #edit is related to the route patch
    def edit
        @user = User.find(params[:id])
    end

    def destroy
        @user = User.find(params[:id])
        @user.destroy

        redirect_to users_path
    end

    private
        def user_params
        params.require(:user).permit(:name, :email)
    end
end

projects_controller:

class ProjectsController < ApplicationController

    def create
        @user = User.find(params[:user_id])
        @project = @user.projects.create(project_params)
        redirect_to user_path(@user)
    end

    def destroy
        @user = User.find(params[:user_id])
        @project = @user.projects.find(params[:id])
        @project.destroy
        redirect_to user_path(@user)
    end

    def update
        @user = User.find(params[:user_id])
        @project = @user.projects.find(params[:id])

      respond_to do |format|
      if @project.update_attributes(params[:project])
        #1st argument of redirect_to is an array, in order to build the correct route to the nested resource project
        format.html { redirect_to([@project.user, @project], :notice => 'project was successfully updated.') }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @project.errors, :status => :unprocessable_entity }
      end
    end
    end

    def edit
        @user = User.find(params[:id])
        @project = @user.projects.find(params[:id])
    end

    private
        def project_params
          params.require(:project).permit(:project_name, :description)
        end
end

用户模型:

class User < ActiveRecord::Base
    has_many :projects
end

项目模型:

class Project < ActiveRecord::Base
  belongs_to :user
end

非常感谢!

2 个答案:

答案 0 :(得分:3)

对于初学者,您需要告诉您的父模型他将与嵌套的子模型(或更多)一起保存,例如:

class User < ActiveRecord::Base
    has_many :projects
    accepts_nested_attributes_for :projects
end

在Rails 4中,您可以通过白名单或允许您想要传递的参数:

#UsersController
def user_params
        params.require(:user).permit([:id, :name, :email, projects_attributes: [:name,
 :price] ]) #list all the attributes that you want to allow to be passed from the       view  to the model when in the controller
    end 

仍然在UsersController中,您需要传递已修改的参数,或 user_params 而不是参数

def update
  @user = User.find(user_params[:id])

  if @user.update(user_params) #this will already save your nested project along with the user
    redirect_to @user
  else
    render 'edit'
  end
end

由于项目与UsersController中的用户一起保存,我的意思是,您不需要在ProjectsController中保存/更新项目,将其从用户中删除,然后将其保存回来。

答案 1 :(得分:0)

您的路线应为:

Rails.application.routes.draw do

  resources :users do
    resources :projects
  end

  root 'welcome#index'
end

另外,不要忘记将新属性列入白名单!