ActiveRecord :: RecordNotFound (Не удалось найти блог с 'id' = undefined): - PullRequest
0 голосов
/ 16 октября 2018

Я хочу изменить статус моего блога с черновика на опубликованный и наоборот.Он работает с перезагрузкой страницы, но я хотел бы реализовать с помощью ajax.

Вот мой blogs_controller.rb

class BlogsController < ApplicationController
  before_action :set_blog, only: [:show, :edit, :update, :destroy, :toggle_status]

  # GET /blogs
  # GET /blogs.json
  def index
    # @blog = Blog.new
    @blogs = Blog.all
  end

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

  # GET /blogs/new
  def new
    @blog = Blog.new
  end

  # GET /blogs/1/edit
  def edit
  end

  # POST /blogs
  # POST /blogs.json
  def create
    @blog = Blog.new(blog_params)

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

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

  # DELETE /blogs/1
  # DELETE /blogs/1.json
   def destroy
    @blog.destroy
    respond_to do |format|
      format.html { redirect_to blogs_url, notice: 'Blog was successfully destroyed.' }
      format.json { head :no_content }
    end
   end

   def toggle_status
    # @blog = Blog.find(params[:id])
    if @blog.draft?
       @blog.published!
    elsif @blog.published?
       @blog.draft!
    end 

    redirect_to blogs_url, notice: "Blog status has been updated"
   end

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

    # Never trust parameters from the scary internet, only allow the white list through.
    def blog_params
      params.require(:blog).permit(:title, :status)
    end
end

Вот мой blog.rb

class Blog < ApplicationRecord
  enum status: { draft: 0, published:1 }
end

Вот мой index.html.erb

<% @blogs.each do |blog| %>
      <tr>
        <td><%= blog.title %></td>
        <td><%= link_to blog.status,toggle_status_blog_path(blog), remote: true, class: "test" %></td>
        <td><%= link_to 'Show', blog %></td>
        <td><%= link_to 'Edit', edit_blog_path(blog) %></td>
        <td><%= link_to 'Destroy', blog, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>

Вот мое application.js

$(document).ready(function() {

  $("a.test").on( "click", function( event ) {
    var id = $(this).attr("id");
    $.ajax({
      url: "/blogs/" + id + "/toggle_status",
      type: "GET",
      success: function(r){

      }
    });
  });
});

Вот мой route.rb

resources :blogs do 
    member do
      get :toggle_status
    end
  end

Iслишком старался, но я не получил желаемых результатов.

Любые предложения приветствуются.

Заранее спасибо.

1 Ответ

0 голосов
/ 16 октября 2018

ActiveRecord :: RecordNotFound (Не удалось найти блог с 'id' = undefined)

У вас есть var id = $(this).attr("id");, но вы не определили атрибут id в ссылке,Таким образом, $(this).attr("id") равно undefined , что дополнительно создает URL, например "/blogs/undefined/toggle_status".Таким образом, :id передается как undefined в запрос Blog.find(params[:id]), который завершается с этим исключением.Чтобы решить вашу проблему, определите id следующим образом:

<%= link_to blog.status,toggle_status_blog_path(blog), remote: true, class: "test", id: blog.id %>

Примечание:

Если ваша версия Jquery > = 1.6 , тогдаattr устарело для 1.6 и более поздних версий.Вы должны prop вместо attr

var id = $(this).prop("id");

Обновление: # 1

Действие выполняется дважды.Это потому, что вы выполняете один и тот же AJAX вызов дважды!Один с remote:true в ссылке, а другой с Jquery AJAX.Вы должны оставить один из них и удалить другой.Таким образом, окончательный ответ будет следующим:

<%= link_to blog.status,toggle_status_blog_path(blog), remote: true, class: "test" %>

Обновление № 2:

Поскольку ваша конечная цель заключается в мгновенном отображении обновленного статуса блога (т.е.(без обновления страницы), затем вам нужно выполнить следующие шаги

1) Измените link_to на

<%= link_to blog.status, "javascript:void(0);", class: "test", id: blog.id %>

2) Верните свой код Jquery.Нам это нужно сейчас.Добавьте необходимый код в функцию success

$(document).ready(function() {
  $("a.test").on( "click", function( event ) {
  var id = $(this).attr("id");
  var current_link = $(this)

  $.ajax({
    url: "/blogs/" + id + "/toggle_status",
    type: "GET",
    dataType: "json",
    success: function(r){
      console.log(r["blog_status"]);
      current_link.text(r["blog_status"]); // this will display the status of the blog
      alert("Blog status has been updated");
     }
  });
  });
});

3) Измените свой метод toggle_status на

def toggle_status
  if @blog.draft?
    @blog.published!
  elsif @blog.published?
    @blog.draft!
  end 

  respond_to do |format|
    format.html { redirect_to blogs_url, notice: "Blog status has been updated"}
    format.json { render json: {blog_status: @blog.status, status: :ok }}
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...