没有ID的Rails找不到用户

时间:2018-12-01 09:43:39

标签: ruby-on-rails devise ruby-on-rails-5

嗨,我有一个使用devise进行用户身份验证的Rails 5应用。

该应用具有属于用户的服务器场模型。用户登录并进入Farm#index页面。

在“场索引”页面上,我们显示了current_user.farm.all以及一个使用@user创建新场的按钮。通过before_action:authenticate_user对用户进行身份验证!

当我创建一个新服务器场时,我得到

ActiveRecord::RecordNotFound in FarmsController#new
Couldn't find User without an ID

app / views / farms / index.html.erb

<div class="row">
  <div class="col-sm-6">
    <h1>Farms</h1>
  </div>

  <div class="col-sm-6 text-right">
  <%= link_to new_farm_path(@user), class: 'btn btn-primary' do %>
    Add New Farm
  <% end %>
  </div>
</div>

<div class="table-responsive">
  <table class="table table-striped table-bordered table-hover">
    <thead>
      <tr>


            <th>Address</th>


          <th></th>

      </tr>
    </thead>

    <tbody>
      <% @farms.each do |farm| %>
        <%= content_tag :tr, id: dom_id(farm), class: dom_class(farm) do %>


                      <td><%= farm.address %></td>


            <td><%= link_to 'Show', farm %></td>

        <% end %>
      <% end %>
    </tbody>
  </table>
</div>

app / controllers / farms_controller.rb

class FarmsController < ApplicationController
  before_action :authenticate_user!
  before_action :set_farm, only: [:show, :edit, :update, :destroy]

  # GET /farms
  # GET /farms.json
  def index
    @farms = current_user.farms.all
  end

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

  # GET /farms/new
  def new
    @user = User.find(params[:user_id])
    @farm = Farm.new
  end

  # GET /farms/1/edit
  def edit
  end

  # POST /farms
  # POST /farms.json
  def create
    @user = User.find(params[:user_id])
    @farm = Farm.new(farm_params)
    @farm.user = @user

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

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

  # DELETE /farms/1
  # DELETE /farms/1.json
  def destroy
    @farm.destroy
    respond_to do |format|
      format.html { redirect_to farms_url, notice: 'Farm was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

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

    # Never trust parameters from the scary internet, only allow the white list through.
    def farm_params
      params.require(:farm).permit(:address, :user_id)
    end
end

路线

Rails.application.routes.draw do
    resources :farms, shallow: true do
      resources :paddocks, shallow: true do
        resources :crops, shallow: true
        resources :treatments, shallow: true do
          resources :ingredients, shallow:true
        end
      end
    end
  resources :ingredients, only: [:index, :show]
  resources :treatments, only: [:index, :show]

  namespace :admin do
      resources :users
      resources :announcements
      resources :notifications
      resources :services

      root to: "users#index"
    end
  get '/privacy', to: 'home#privacy'
  get '/terms', to: 'home#terms'
  resources :notifications, only: [:index]
  resources :announcements, only: [:index]
  authenticate :user, lambda { |u| u.admin? } do
    mount Sidekiq::Web => '/sidekiq'
  end

  devise_for :users, controllers: { omniauth_callbacks: "users/omniauth_callbacks" }
  root to: 'home#index'
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

app / models / farm.rb

class Farm < ApplicationRecord
  belongs_to :user
  has_many :paddocks
end

app / models / user.rb

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :masqueradable, :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :omniauthable

  has_person_name

  has_many :notifications, foreign_key: :recipient_id
  has_many :services
  has_many :farms
end

app / views / farms / _form.html.erb

<%= form_for [@user, @farm] do |form| %>

  <div class="form-group">
    <%= form.label :address %>
    <%= form.text_field :address, class: 'form-control' %>
  </div>

  <div class="form-group">

    <%= form.submit class: 'btn btn-primary' %>

  </div>
<% end %>

1 个答案:

答案 0 :(得分:1)

您的FarmsController新建/创建和您的服务器场表单(form_for [@user, @farm] do |form|)是为嵌套路由定义的,用户如下:

resources :users, shallow: true do
  resources :farms, shallow: true do
    #...
  end
end

生成:user_id存在的路径:

user_farms    GET    /users/:user_id/farms(.:format)      farms#index
              POST   /users/:user_id/farms(.:format)      farms#create
new_user_farm GET    /users/:user_id/farms/new(.:format)  farms#new

要解决您的问题,请将resources :users添加到嵌套路由,并在场索引视图中更改link_to

<%= link_to new_user_farm_path(@user), class: 'btn btn-primary' do %>

另一种解决方案:

如果始终为current_user创建服务器场,则可以在new / create中将@user = User.find(params[:user_id])更改为@user = current_user并修复如下形式:

form_for @farm do |form| do
  #...
end

您不必以此方式更改路线。