动作控制器:刷新页面时发生异常

时间:2019-05-27 06:38:31

标签: ruby-on-rails

将页面刷新到我的自定义控制器操作时遇到问题。第一次执行操作后,每次刷新页面时,都会遇到ActiveRecord::RecordNotFound异常。

我在控制器中的动作中编写了这些自定义查询,它们在我的route.rb中添加了该动作的路径 这是我正在访问的URL:http://localhost:3000/health_units/especialidades?specialty=ENFASE 从索引页访问它时效果很好,但是如果我尝试刷新页面甚至键入它,都会收到此错误。

这是我的控制者:

class HealthUnitsController < ApplicationController
  before_action :set_health_unit, only: [:show, :edit, :update, :destroy]

  # GET /health_units
  # GET /health_units.json
  def index
    @health_units = HealthUnit.all
  end

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

  # GET /health_units/new
  def new
    @health_unit = HealthUnit.new
  end

  # GET /health_units/1/edit
  def edit
  end

  # POST /health_units
  # POST /health_units.json
  def create
    @health_unit = HealthUnit.new(health_unit_params)

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

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

  # DELETE /health_units/1
  # DELETE /health_units/1.json
  def destroy
    @health_unit.destroy
    respond_to do |format|
      format.html { redirect_to health_units_url, notice: 'Health unit was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  def basic_search
    if params[:keywords].empty?
      redirect_to health_units_path
    else
      @health_units = HealthUnit.where("specialties && :kw or 
        treatments && :kw", kw: params[:keywords].split(' '))
      respond_to do |format|
        format.html { render template: "health_units/index.html.slim" }
        format.json { render template: "health_units/index.json.jbuilder"}
      end
    end
  end

  def list_by_specialties
    if params[:specialty].nil?
      redirect_to health_units_path
    else
      @specialty = params[:specialty]
      @health_units = HealthUnit.where("specialties && ARRAY[?]",
        @specialty)
      respond_to do |format|
        format.html { render template: "health_units/specialty.html.slim" }
        format.json { render template: "health_units/index.json.jbuilder"}
      end
    end
  end

  def list_by_treatments
    if params[:treatments].empty?
      redirect_to health_units_path
    else
      @health_unit = HealthUnit.where("treatments && ?",
        params[:treatments].split(' '))
      respond_to do |format|
        format.html { render template: "health_units/index.html.slim" }
        format.json { render template: "health_units/index.json.jbuilder"}
      end
    end
  end

  def search_by_neighborhood
    if params[:neighborhood].nil?
      redirect_to health_units_path
    else
      @health_units = HealthUnit.where(neighborhood: params[:neighborhood])
      respond_to do |format|
        format.html { render template: "health_units/index.html.slim" }
        format.json { render template: "health_units/index.json.jbuilder"}
      end
    end
  end

  def advanced_search
    @health_unit = HealthUnit.new
  end

  def advanced_search_results
  end


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

    # Never trust parameters from the scary internet, only allow the white list through.
    def health_unit_params
      params.require(:health_unit).permit(:cnes, :name, :address, :neighborhood, :phone, :latitude, :longitude, :description)
    end

end

这是我的routes.rb

  resources :health_units do
    collection do
      resources :comments, path: 'comentarios'
      post :basic_search, path: 'resultados'
      post :advanced_search, path: 'pesquisar'
      post :list_by_specialties, path: 'especialidades', as: :specialty
      post :list_by_treatments, path: 'atendimentos', as: :treatments
      post :search_by_neighborhood, path: 'bairro', as: :neighborhood
    end

这是我在控制台中看到的错误:

Started GET "/health_units/especialidades?specialty=ENFASE" for 127.0.0.1 at 2019-05-27 03:29:07 -0300
Processing by HealthUnitsController#show as HTML
  Parameters: {"specialty"=>"ENFASE", "id"=>"especialidades"}
  HealthUnit Load (0.5ms)  SELECT  "health_units".* FROM "health_units" WHERE "health_units"."id" = $1 LIMIT $2  [["id", 0], ["LIMIT", 1]]
  ↳ app/controllers/health_units_controller.rb:127
Completed 404 Not Found in 3ms (ActiveRecord: 0.5ms)



ActiveRecord::RecordNotFound (Couldn't find HealthUnit with 'id'=especialidades):

app/controllers/health_units_controller.rb:127:in `set_health_unit'
Started GET "/favicon.ico" for 127.0.0.1 at 2019-05-27 03:29:07 -0300

ActionController::RoutingError (No route matches [GET] "/favicon.ico"):

actionpack (5.2.3) lib/action_dispatch/middleware/debug_exceptions.rb:65:in `call'
actionpack (5.2.3) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
railties (5.2.3) lib/rails/rack/logger.rb:38:in `call_app'
railties (5.2.3) lib/rails/rack/logger.rb:26:in `block in call'
activesupport (5.2.3) lib/active_support/tagged_logging.rb:71:in `block in tagged'
activesupport (5.2.3) lib/active_support/tagged_logging.rb:28:in `tagged'
activesupport (5.2.3) lib/active_support/tagged_logging.rb:71:in `tagged'
railties (5.2.3) lib/rails/rack/logger.rb:26:in `call'
actionpack (5.2.3) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
actionpack (5.2.3) lib/action_dispatch/middleware/request_id.rb:27:in `call'
rack (2.0.7) lib/rack/method_override.rb:22:in `call'
rack (2.0.7) lib/rack/runtime.rb:22:in `call'
activesupport (5.2.3) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
actionpack (5.2.3) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (5.2.3) lib/action_dispatch/middleware/static.rb:127:in `call'
rack (2.0.7) lib/rack/sendfile.rb:111:in `call'
railties (5.2.3) lib/rails/engine.rb:524:in `call'
puma (3.12.1) lib/puma/configuration.rb:227:in `call'
puma (3.12.1) lib/puma/server.rb:660:in `handle_request'
puma (3.12.1) lib/puma/server.rb:474:in `process_client'
puma (3.12.1) lib/puma/server.rb:334:in `block in run'
puma (3.12.1) lib/puma/thread_pool.rb:135:in `block in spawn_thread'

我希望能够刷新页面并获得与第一次访问时相同的结果。

2 个答案:

答案 0 :(得分:3)

该请求将作为GET请求。

Started GET "/health_units/especialidades?specialty=ENFASE" for 127.0.0.1 at 2019-05-27 03:29:07 -0300
Processing by HealthUnitsController#show as HTML

rails希望它是根据定义的路线发出的POST请求

post :list_by_specialties, path: 'especialidades', as: :specialty

因此,与其匹配HealthUnitsController#list_by_specialties,而是匹配HealthUnitsController#show的路线

您需要查看为什么您的请求以GET而不是POST的身份出现。修复后,它将可以正常工作

出现ActiveRecord::RecordNotFound错误的原因

ActiveRecord::RecordNotFound (Couldn't find HealthUnit with 'id'=especialidades):

因为它试图查找ID为HealthUnit的{​​{1}},而返回especialidades.to_i,并且由于没有ID为0的记录,您会遇到0错误

答案 1 :(得分:1)

这是因为,当您刷新路由时,会以id作为特殊对象来显示操作,并尝试使用id="especialidades"查找HealthUnit,并且不会发现并引发错误

解决这个问题的一种方法是定义约束

class RandomConstraint
  def matches?(request)
    return false unless request.path_parameters[:id].present?
  end
end

get :list_by_specialties, path: 'especialidades', as: :specialty, constraints: RandomConstraint.new