首页 > 解决方案 > 无法更新 Rails。错误消息“找不到带有 'id'=:id 的电影”

问题描述

我想运行更新操作,但我无法获取 ID。我认为这将是一个简单的问题,但我找不到解决问题的方法。

我认为从编辑发送的值将被发送到更新操作,更新操作会更新值,但我无法获取 ID。我一直在看其他文章,看起来它也在以同样的方式更新。

代码

编辑


<!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>

控制器


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

模型

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 

路线

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


更改 form_with 方法后出错

在此处输入图像描述

标签: ruby-on-railsruby

解决方案


您真的只需要在这里利用 Rails 约定,而不是手动完成所有操作。

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

而不是手动输入每条路线使用resources。此外,Rails 使用 PATCH HTTP 方法而不是 PUT 进行更新已经有一段时间了。由于遗留原因,Rails 也会输出 PUT 路由,但将来可能会改变。

现在的表格:

<%= 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 %>

您无需指定 URL 或方法。Rails 可以根据模型计算出所有这些。使用[:admin, @movie]告诉 rails 去寻找admin_movie_path.

使用标签而不是<p>标签来标记您的输入,以便屏幕阅读器等辅助技术可以访问它。将输入和标签组合在一个元素中可以让您使用 CSS 对其进行样式设置。

您的控制器中有许多错别字和错误:

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

推荐阅读