生成新视图时的NoMethodError

时间:2014-11-05 05:12:23

标签: ruby-on-rails model-view-controller controller

我正致力于制作一个简单的应用,其中的用户可以拥有多个播放列表。我试图呈现播放列表的新视图但我收到此错误:

NoMethodError in PlaylistsController#new
undefined method `playlist' for nil:NilClass

  def new
    @playlist = @user.playlist.new
  end

这里有一些背景信息:

编辑:我将代码的相关部分上传到gist.github:

https://gist.github.com/izikperz/164eab76e64d375d9075

Playlist_controller.rb

class PlaylistsController < ApplicationController
  before_action :set_playlist, only: [:show, :edit, :update, :destroy]
                :set_user

  # GET /playlists
  # GET /playlists.json
  def index
    @playlists = Playlist.all
  end

  # GET /playlists/1
  # GET /playlists/1.json
  def show
  end

  # GET /playlists/new
  def new
    @playlist = @user.playlist.new
  end

  # GET /playlists/1/edit
  def edit
  end

  # POST /playlists
  # POST /playlists.json
  def create
    @playlist = @user.playlists.new(playlist_params)

    respond_to do |format|
      if @playlist.save
        format.html { redirect_to @user.playlist, notice: 'Playlist was successfully created.' }
        format.json { render :show, status: :created, location: @playlist }
      else
        format.html { render :new }
        #format.json { render json: @playlist.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /playlists/1
  # PATCH/PUT /playlists/1.json
  def update
    respond_to do |format|
      if @playlist.update(playlist_params)
        format.html { redirect_to @playlist, notice: 'Playlist was successfully updated.' }
        format.json { render :show, status: :ok, location: @playlist }
      else
        format.html { render :edit }
        format.json { render json: @playlist.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /playlists/1
  # DELETE /playlists/1.json
  def destroy
    @playlist.destroy
    respond_to do |format|
      format.html { redirect_to playlists_url, notice: 'Playlist was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    def set_user
      @user = User.find_by(params[:user_id])
    end
    # Use callbacks to share common setup or constraints between actions.
    def set_playlist
      @playlist = Playlist.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def playlist_params
      params.require(:playlist).permit(:user_id, :title, :img)
    end
end

在我的routes.rb中我有:

resources :users do
    resources :playlists
  end

我的user.rb型号:

class User < ActiveRecord::Base
  before_save { self.email = email.downcase }
  has_secure_password
  validates :password, length: { minimum: 6 }
  has_many :playlists
end

Playlist.rb模型:

class Playlist < ActiveRecord::Base
    belongs_to :user, inverse_of: :playlist
    validates :user_id, presence: true
end

我的数据库架构:

ActiveRecord::Schema.define(version: 20141105043809) do

  create_table "playlists", force: true do |t|
    t.string   "title"
    t.string   "img"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "user_id"
  end

  create_table "users", primary_key: "user_id", force: true do |t|
    t.string   "name"
    t.string   "email"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "password_digest"
    t.string   "imgurl"
  end

end

有人有什么想法吗?

3 个答案:

答案 0 :(得分:2)

@user操作中的new对象为nil

undefined method `playlist' for nil:NilClass

这是因为没有从你的视图发送params [:user_id]。

通过修改来修复它:

new_user_playlist_path(params[:user_id])

为:

new_user_playlist_path(user_id: params[:user_id])

修正后,new操作中会出现另一个错误:

@playlist = @user.playlist.new

它应该是多元化的,因为它在你的协会中:

@playlist = @user.playlists.new
#or
@playlist = @user.playlists.build

或者只是忽略它:

@playlist = Playlist.new(user_id: @user.id) 

答案 1 :(得分:0)

由于用户和播放列表之间的ActiveRecord关联是:has_many:belongs_to,因此这些关联是多对多关联。这意味着一个用户有多个播放列表。该关联将为您提供实例方法@user.playlists而不是@user.playlist。尝试使用复数版本。它应该工作。

答案 2 :(得分:0)

确保您发送user_id以及表单

@user = User.find_by(id: params[:user_id])不是nil

然后更改此

@playlist = @user.playlists.new