Home > Back-end >  Unable to update Rails. Error message "Couldn't find Movie with 'id'=:id "
Unable to update Rails. Error message "Couldn't find Movie with 'id'=:id "

Time:09-21

I want to run the update action, but I can't get the ID. I thought it would be a simple problem, but I could not find a solution to the problem.

I thought the value sent from edit would be sent to the update action and the update action would update the value, but I can't get the ID. I've been looking at other articles and it looks like it's updating in the same way.

Code

edit


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <%= form_with model: @movie, url: '/admin/movies/:id', method: :put do |form| %>
        <%= form.text_field :name %>
        <p>Year</p>
        <%= form.text_field :year %>
        <p>Image URL</p>
        <%= form.text_field :image_url %>
        <p>Description</p>
        <%= form.text_area :description %>
        <p>Show</p>
        <%= form.text_field :is_showing %>
        <%= form.submit"Edit Save"%>
    <% end %>
</body>
</html>

controller


class MoviesController < ApplicationController

    def index
        @movie = Movie.all
    end

    def new
        @movie = Movie.new
    end

    def create
        @movie = Movie.new(post_params)
        @movie.save!
    end

    def edit
        @movie = Movie.find(params[:id])
        @movie.save
    end

    def update
        @movie = Movie.find(params[:id])
            if @movie.update(post_params)
                redirect_to :idnex
            else
                render :edit
        end
    end

    private
        def post_params
            params.require(:movie).permit(:id,:name, :year, :image_url, :description, :is_showing )
        end
end

model

FactoryBot.define do
  factory :movie do
    sequence(:name) { |n| "TEST_MOVIE#{n}"}
    sequence(:year) { 2021 }
    sequence(:description) { "test"}
    sequence(:image_url) {"" }
    sequence(:is_showing) { 1 }
  end
end 

routes

Rails.application.routes.draw do
  # get 'movies', to: 'movies#index'
  get '/admin/movies', to: 'movies#index'
  get '/admin/movies/new', to: 'movies#new'
  post '/admin/movies/new', to: 'movies#create'
  get '/admin/movies/:id/edit', to: 'movies#edit'
  put '/admin/movies/:id', to: 'movies#update'
  get '/admin/movies/:id', to: 'movies#edit'
end


Error after changing form_with method

enter image description here

CodePudding user response:

You really just need to leverage the rails conventions here instead of doing everything manually.

Rails.application.routes.draw do
  scope :admin do
    resources :movies
  end
end

Instead of manually typing out each route use the resources macro. Also Rails has used the PATCH HTTP method instead of PUT for updates for quite some time. For legacy reasons Rails will output a PUT route as well but that may change in the future.

Now the form:

<%= form_with model: [:admin, @movie] do |form| %>
  <div class="field">
    <%= form.label :name %>
    <%= form.text_field :name %>
  </div>
  <div class="field">
    <%= form.label :year %>  
    <%= form.text_field :year %>
  </div>
  <div class="field">
    <%= form.label :image_url, "Image URL" %>
    <%= form.text_field :image_url %>
  </div>
  <div class="field">
    <%= form.label :description %>
    <%= form.text_area :description %>
  </div>
  <div class="field">
    <%= form.label :is_showing, "Show" %>
    <%= form.text_field :is_showing %>
  </div>
  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

You do not need to specify the URL or the method. Rails can figure all that out just based on the model. Using [:admin, @movie] tells rails to look for admin_movie_path.

Use labels instead of <p> tags to label your inputs so that its accessible to assistive technologies like screen readers. Grouping the input and label together in an element lets you style it with CSS.

Your controller has numerous typos and errors in it:

class MoviesController < ApplicationController

  # GET /admin/movies
  def index
    # use the plural name for the instance variable since its many movies
    @movies = Movie.all 
  end

  # GET /admin/movies/new
  def new
    @movie = Movie.new
  end

  # POST /admin/movies/
  def create
    @movie = Movie.new(post_params)
    # check if the movie is saved and respond accordingly
    # save! generally should not be used in controllers
    if @movie.save 
      redirect_to :index, notice: 'Movie created'
    else 
      render :new
    end 
  end

  # GET /admin/movies/1/edit
  def edit
    @movie = Movie.find(params[:id])
  end

  # PATCH|PUT /admin/movies/1
  def update
    @movie = Movie.find(params[:id])   
    if @movie.update(post_params)
      # this was a typo
      redirect_to :index, notice: 'Movie updated' 
    else
      render :edit
    end
  end
  
  private

  def post_params
    params.require(:movie)
    .permit(
      :id, :name, :year, 
      :image_url, :description, :is_showing 
    )
  end
end
  • Related