【问题标题】:How to fix 'updating a comment sent me to the wrong route'如何解决“更新评论让我走错了路线”
【发布时间】:2019-04-27 15:34:46
【问题描述】:

我正在构建一个应用程序,并且我有一个设备用户控制器,用于使用评论和帖子的脚手架登录。我的问题是,当我更新评论并点击按钮更新时,当我在控制器中告诉它将我发送到 http://localhost:3000/publicaciones/1 时,它会将我发送到路由 http://localhost:3000/publicaciones/1/comentarios

创建和删除的想法将我引导到正确的路线

mensajes 控制器

before_action :set_comentario, only: [:show, :edit, :update, :destroy]
  before_action :set_publicacione, only: [:new, :create, :destroy, :show]

  # GET /comentarios
  # GET /comentarios.json
  def index
    @comentarios = Comentario.all
  end

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

  # GET /comentarios/new
  def new
    @comentario = Comentario.new
  end

  # GET /comentarios/1/edit
  def edit
  end

  # POST /comentarios
  # POST /comentarios.json
  def create
    @comentario = Comentario.new(comentario_params)
    @comentario.publicacione_id = @publicacione.id
    @comentario.user_id = current_user.id
    respond_to do |format|
      if @comentario.save
        format.html { redirect_to publicacione_path(@publicacione), notice: 'Comentario was successfully created.' }
        format.json { render :show, status: :created, location: @comentario }
      else
        format.html { render :new }
        format.json { render json: @comentario.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /comentarios/1
  # PATCH/PUT /comentarios/1.json
  def update
    respond_to do |format|
      if @comentario.update(comentario_params)
        format.html { redirect_to publicacione_path(@comentario.publicacione_id), notice: 'Comentario was successfully updated.' }
        format.json { render :show, status: :ok, location: publicacione_path(@comentario.publicacione_id) }
      else
        format.html { render :edit }
        format.json { render json: @comentario.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /comentarios/1
  # DELETE /comentarios/1.json
  def destroy
    @comentario.destroy
    respond_to do |format|
      format.html { redirect_to publicacione_path(@comentario.publicacione_id), notice: 'Comentario was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_comentario
      @comentario = Comentario.find(params[:id])
    end

    def set_publicacione
      @publicacione = Publicacione.find(params[:publicacione_id])
    end
    # Never trust parameters from the scary internet, only allow the white list through.
    def comentario_params
      params.require(:comentario).permit(:contenido, :puntaje_reputacion, :user_id, :publicacione_id)
    end
end

publicaciones 控制器

class PublicacionesController < ApplicationController
  before_action :set_publicacione, only: [:show, :edit, :update, :destroy]
  # GET /publicaciones
  # GET /publicaciones.json
  def index
    @publicaciones = Publicacione.all
  end

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

  # GET /publicaciones/new
  def new
    @publicacione = Publicacione.new
  end

  # GET /publicaciones/1/edit
  def edit
  end

  # POST /publicaciones
  # POST /publicaciones.json
  def create
    @publicacione = Publicacione.new(publicacione_params)

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

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

  # DELETE /publicaciones/1
  # DELETE /publicaciones/1.json
  def destroy
    @publicacione.destroy
    respond_to do |format|
      format.html { redirect_to publicaciones_url, notice: 'Publicacione was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_publicacione
      @publicacione = Publicacione.find(params[:id])
    end

    def set_comentarios
      @comentarios = Comentario.all
    end
    # Never trust parameters from the scary internet, only allow the white list through.
    def publicacione_params
      params.require(:publicacione).permit(:titulo, :contenido, :descripcion, :puntaje_reputacion, :user_id, :curso_id)
    end
end

配置/路由

Rails.application.routes.draw do
  resources :publicaciones do
    resources :comentarios
  end
  resources :cursos
  resources :eventos
  resources :sala_de_estudios
  devise_for :users
  resources :campus
  resources :users, only: [:show, :edit, :update]
  root 'campus#index'
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

编辑视图

<h1>Editing Comentario</h1>

<%= render 'form', comentario: @comentario %>

<%= link_to 'Show', publicacione_comentario_path%> |
<%= link_to 'Back', publicacione_path(@comentario.publicacione_id) %>

表单视图

<%= form_with(model: @comentario, url: publicacione_comentarios_path, local: true) do |form| %>
  <% if comentario.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(comentario.errors.count, "error") %> prohibited this comentario from being saved:</h2>

      <ul>
      <% comentario.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :contenido %>
    <%= form.text_field :contenido %>
  </div>

  <div class="field">
    <%= form.label :puntaje_reputacion %>
    <%= form.text_field :puntaje_reputacion %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

当我点击它时,发送给我http://localhost:3000/publicaciones/1/comentarioshttp://localhost:3000/publicaciones/1 是意料之中的

【问题讨论】:

    标签: ruby-on-rails nested-routes


    【解决方案1】:

    这个

    <%= form_with(model: @comentario, url: publicacione_comentarios_path, local: true) do |form| %>
    

    对于新建/创建是正确的,但对于编辑/更新应该是...

    <%= form_with(model: @comentario, url: publicacione_comentario_path(@publicacione, @comentario), local: true) do |form| %>
    

    如果您不想为这两种情况使用不同的形式(我不怪您),请使用格式...

    form_with(model: @comentario, url: [@publicacione, @comentario], local: true)
    

    ...然后form_with helper 方法将生成正确的路径。

    【讨论】:

    • 感谢您的回答,这是我为我解决的问题。你能解释一下为什么这两种形式之间存在这种差异吗?
    • 这是因为更新记录的 RESTful 路径与创建记录的路径不同(您可以 google REST apis),并且 Rails 可以很好地根据是否构建表单来确定需要什么表单对象是#new_record?还是#persisted?但是当你明确提供一个路径时,它会覆盖 Rails 的默认值。
    【解决方案2】:

    你有嵌套的路线

    resources :publicaciones do
      resources :comentarios
    end
    

    你可以放弃他们。

    resources :publicaciones
    resources :comentarios
    

    你也可以使用shallow

    resources :publicaciones do
      resources :comentarios, shallow: true
    end
    

    【讨论】:

    • 我认为他想要嵌套路由。
    【解决方案3】:

    由于有嵌套资源,需要在表单上设置Publicacione对象:

    <%= form_with(model: @comentario, url: publicacione_comentarios_path(@publicacione), local: true) do |form| %>
    

    然后,在控制器中,需要在@publicacione的基础上设置@commentario,以及redirect_to publicacione_path(@publicacione)

      def update
        respond_to do |format|
          if @comentario.update(comentario_params)
            format.html { redirect_to publicacione_path(@publicacione), notice: 'Comentario was successfully updated.' }
            format.json { render :show, status: :ok, location: publicacione_path(@comentario.publicacione_id) }
          else
            format.html { render :edit }
            format.json { render json: @comentario.errors, status: :unprocessable_entity }
          end
        end
      end
    
      private
    
        def set_comentario
          @comentario = @publicacione.comentarios.find(params[:id])
        end
    

    【讨论】:

    • 似乎没有去,我认为 mu 问题是当我点击更新时它没有去功能更新,有什么办法可以测试这个吗?更改了 ypu 所说的所有内容,但行为仍然相同,如果我有 redirect_to @comment,它会将我发送到路线,但它确实没有这么说
    • 是的,最简单的方法是在def update 右侧添加类似“booom”的内容。更好的选择是log.debug('im here')byebug。后者将停止执行并在rails s 命令中调出调试器。
    • 调用 byebug 并没有出现在调试器中,我真的认为它没有进入更新功能。同样在控制台中出现此错误已在 2019-04-27 16:57:39 +0000 web_1 | 为 172.19.0.1 启动 PATCH "/publicaciones/1/commentarios"无法从 172.19.0.1 渲染控制台!允许的网络:127.0.0.1, ::1, 127.0.0.0/127.255.255.255 也许有一些帮助,知道是什么让它不能进入​​更新功能吗?
    • rails s -b 0.0.0.0启动服务器,接受来自每个IP的请求。
    • 好吧,我试试,问题是在heroku上运行时报错是一样的,用rails s -b 0.0.0.0运行服务器是不行的:(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 2014-01-10
    • 2019-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多