Rails не может найти пользователя без идентификатора - PullRequest
0 голосов
/ 01 декабря 2018

Привет, у меня есть приложение rails 5, использующее devise для моей аутентификации пользователя.

Приложение имеет модель фермы, которая принадлежит пользователю.Пользователь входит в систему и перенаправляется на страницу индекса фермы #.

На странице индекса фермы мы показываем 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 голосов
/ 01 декабря 2018

Ваш FarmsController new / create и форма вашей фермы (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, вы можете изменить @user = User.find(params[:user_id]) на @user = current_user в новом / создать и исправить форму следующим образом:

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

Вам не нужно менять маршрутывот так.

...