2014-11-09 5 views
2

Я пытаюсь создать простую утилиту rails, где пользователи могут создавать любое количество плейлистов. Я очень нов к рельсам и мне интересно, если я должен быть вложенности ресурсы, как это:Вложенные ресурсы в рельсах

Rails.application.routes.draw do 
    resources :users do 
    resources :playlists 
    end 

Действовать таким образом дает это, когда я rake routes:

  Prefix Verb URI Pattern         Controller#Action 
    user_playlists GET /users/:user_id/playlists(.:format)   playlists#index 
        POST /users/:user_id/playlists(.:format)   playlists#create 
new_user_playlist GET /users/:user_id/playlists/new(.:format)  playlists#new 
edit_user_playlist GET /users/:user_id/playlists/:id/edit(.:format) playlists#edit 
    user_playlist GET /users/:user_id/playlists/:id(.:format)  playlists#show 
        PATCH /users/:user_id/playlists/:id(.:format)  playlists#update 
        PUT /users/:user_id/playlists/:id(.:format)  playlists#update 
        DELETE /users/:user_id/playlists/:id(.:format)  playlists#destroy 
      users GET /users(.:format)        users#index 
        POST /users(.:format)        users#create 
      new_user GET /users/new(.:format)       users#new 
     edit_user GET /users/:id/edit(.:format)     users#edit 
       user GET /users/:id(.:format)       users#show 
        PATCH /users/:id(.:format)       users#update 
        PUT /users/:id(.:format)       users#update 
        DELETE /users/:id(.:format)       users#destroy 
       root GET /           default_pages#home 
      signup GET /signup(.:format)       users#new 
      signin GET /signin(.:format)       users#signin 

Я могу успешно добраться до/пользователей/1/плейлисты, в которых я имею эту ссылку (внутри index.html.erb плейлистов):

<%= link_to 'New Playlist', new_user_playlist_path(params[:user_id])%> 

Но щелкая это дает мне эту ошибку:

 undefined method `playlists' for nil:NilClass 

    Extracted source (around line #18): 
    16  # GET /playlists/new 
    17  def new 
    18   @playlist = @user.playlists.new 
    19  end 
    20  # GET /playlists/1/edit 

Это то, что мой playlist_controller выглядит следующим образом:

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.playlists.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 

Моя мысль в том, что поскольку ожидаемый URL должен выглядеть как пользователей/1/плейлистов/1, что мне нужно передать две переменные , один для user_id и один для идентификатора списка воспроизведения (что-то вроде), но я точно не знаю, где/как ... Может ли кто-нибудь помочь мне?

Благодаря

+0

Вы установили отношения на модели 'User'? 'has_many: плейлисты' – dasnixon

+0

Также вы можете использовать' @ user.playlists.build'. Обратите внимание на '.build', который автоматически установит соответствующий внешний ключ. – dasnixon

+0

У меня уже есть настройки моделей, спасибо. Где я могу использовать .build? – user2804881

ответ

3

Я думаю, что проблема в before_action, поэтому @user не установлен. Попробуйте добавить еще один раз before_action под линией before_action :set_playlist, only: [:show, :edit, :update, :destroy]

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

    ... 
end 

UPD

я нашел еще одно место. Попробуйте использовать @user с вашего вида. new_user_playlist_path(@user), он должен быть создан из before_action

+0

Это сработало! Благодаря! – user2804881

+0

Сначала я получил эту ошибку: ActiveRecord :: InverseOfAssociationNotFoundError в PlaylistsController # нового Не удалось найти обратную связь для пользователя (: плейлист в пользователе) И я вспомнил, что я имел в моем плейлисте модели: класса Playlist user2804881

+0

Вы можете найти информацию здесь: http: //guides.rubyonrails.орг/association_basics.html # двунаправленные-ассоциации – Bob