Крепление рельсов контроллера - PullRequest
0 голосов
/ 03 марта 2020

Я пытаюсь написать простой API рельсов. В моем приложении logi c пользовательская модель 'бюджетов has_many' и модель Budget (естественно) принадлежат пользователю. Я пытаюсь настроить простую систему аутентификации, которая будет использоваться в реагирующем интерфейсе. В процессе тестирования запросов я наткнулся на некоторые ошибки, которые, похоже, происходят от моего контроллера. Соответствующие данные следующие:

Контроллер бюджета

class Api::V1::BudgetsController < ApplicationController

  def index
    @budgets = Budget.all
    render json: @budgets
  end

  def show
    @budget = Budget.find(params[:id])
    render json: @budget
  end

  def create
    @budget = current_user.budgets.build(budget_params)
    if @budget.save
      render json: @budget, status: 201
    else
      render json: { errors: @budget.errors.full_messages }, status: 422
    end
  end

  def destroy
    @budget = Budget.find(params[:id])
    @budget.destroy
  end

  private

  def budget_params
    params.require(:budget).permit(:start_date, :end_date, :income)
  end
end

Контроллер сеансов

class Api::V1::SessionsController < ApplicationController

  def create
    user = User.find_by(email: session_params[:email])
    if user
      log_in user
      render json: {
        logged_in: true,
        user
      }
    else
      render json: {
        status: 401,
        error: 'Please try again'
      }
    end
  end

  def destroy
    log_out if logged_in?
  end

  private

  def session_params
    params.require(:user).permit(:name, :email)
  end
end

Помощник сеанса

module SessionsHelper

  def log_in(user)
    session[user_id] = user.id
  end

  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end

  def logged_in?
    !current_user.nil?
  end

  def log_out
    session.clear
    @current_user = nil
  end
end

Запрос RSpe c tests

require 'rails_helper'

RSpec.describe 'Budgets API', type: :request do
  let!(:user) { create(:user) }
  let!(:budgets) { create_list(:budget, 5, user_id: user.id) }
  let(:budget_id) { budgets.first.id }
describe 'POST /api/v1/budgets' do
    let(:valid_attributes) do
      {
        start_date: '2020-03-01',
        end_date: '2020-03-31',
        income: 7000
      }
    end

    let(:invalid_attributes) do
      {
        start_date: '',
        end_date: '',
        income: ''
      }
    end

    context 'when the request is valid' do
      before(:each) { post '/api/v1/budgets', params: { budget: valid_attributes } }

      it 'creates a budget' do
        expect(json['start_date']).to eq('2020-03-01')
      end

      it 'returns status code 201' do
        expect(response).to have_http_status(201)
      end
    end

    context 'when the request is invalid' do
      before(:each) { post '/api/v1/budgets', params: { budget: invalid_attributes } }

      it 'returns status code 422' do
        expect(response).to have_http_status(422)
      end
    end
  end
end

Я получаю следующие ошибки:

Failures:

  1) Budgets API POST /api/v1/budgets when the request is valid creates a budget
     Failure/Error: @budget = current_user.budgets.build(budget_params)

     NoMethodError:
       undefined method `budgets' for nil:NilClass
     # ./app/controllers/api/v1/budgets_controller.rb:14:in `create'
     # ./spec/requests/budgets_spec.rb:62:in `block (4 levels) in <main>'
     # ./spec/rails_helper.rb:73:in `block (3 levels) in <top (required)>'
     # ./spec/rails_helper.rb:72:in `block (2 levels) in <top (required)>'

  2) Budgets API POST /api/v1/budgets when the request is valid returns status code 201
     Failure/Error: @budget = current_user.budgets.build(budget_params)

     NoMethodError:
       undefined method `budgets' for nil:NilClass
     # ./app/controllers/api/v1/budgets_controller.rb:14:in `create'
     # ./spec/requests/budgets_spec.rb:62:in `block (4 levels) in <main>'
     # ./spec/rails_helper.rb:73:in `block (3 levels) in <top (required)>'
     # ./spec/rails_helper.rb:72:in `block (2 levels) in <top (required)>'

  3) Budgets API POST /api/v1/budgets when the request is invalid returns status code 422
     Failure/Error: @budget = current_user.budgets.build(budget_params)

     NoMethodError:
       undefined method `budgets' for nil:NilClass
     # ./app/controllers/api/v1/budgets_controller.rb:14:in `create'
     # ./spec/requests/budgets_spec.rb:74:in `block (4 levels) in <main>'
     # ./spec/rails_helper.rb:73:in `block (3 levels) in <top (required)>'
     # ./spec/rails_helper.rb:72:in `block (2 levels) in <top (required)>'

Любая помощь будет принята с благодарностью.

1 Ответ

2 голосов
/ 03 марта 2020

current_user равно nil, потому что тесты никогда не входили в систему пользователя. Простого создания пользователя недостаточно, они должны войти в систему.

Обычно вы делаете это с помощью before hook.

RSpec.describe 'Budgets API', type: :request do
  let!(:user) { create(:user) }
  before {
    post("/api/v1/sessions",
      params: {
        user: { email: user.email }
      }
    )
  }

Любой, кто знает пользователя адрес электронной почты может получить доступ к вашему API. Вместо того, чтобы использовать собственную аутентификацию, я бы предложил использовать уже существующий гем, такой как Devise .

...