Test controller failed: NoMethodError: undefined method `env' for nil:NilClass - ruby-on-rails

I have a problem with unit testing in ruby on rails (rails v. 5.001). The user needs to login in a test unit, but how can I implement this? Here is the code:
appointments_controller_test.rb
require 'test_helper'
class AppointmentsControllerTest < ActionDispatch::IntegrationTest
include Devise::TestHelpers
setup do
#heikoAppointment = appointments(:appointment_heiko)
#heiko = users(:heiko)
heiko = users(:heiko)
end
test "should get index" do
get appointments_url
assert_response :success
end
test "should get new" do
sign_in #heiko
get new_appointment_url
assert_response :success
end
......
appointments_controller.rb
class AppointmentsController < ApplicationController
load_and_authorize_resource
layout 'appointment', only: [:shopper_show, :senior_show]
def index
#shopping_lists = ShoppingList.where(user_id: current_user.id)
#users = User.senior.where.not(id: current_user.id).order(:firstname)
##appointments = Appointment.where(user_id: current_user.id)
##invitations = Invitation.where(user_id: current_user.id)
#todo: merge #invitations.appointmen into #appointments
end
# GET /shopping_processes/1
# GET /shopping_processes/1.json
def show
#appointment = Appointment.find(params[:id])
#shopping_lists = get_both_lists
#users = get_both_users
end
# POST /shopping_processes
# POST /shopping_processes.json
def create
#appointment.status = nil
#appointment.processed = nil
#appointment.user_id = current_user.id
sl_created = create_shopping_list?
respond_to do |format|
if #appointment.save
format.html { redirect_to #appointment, notice: t(:appointment_created) }
format.json { render :show, status: :created, location: #appointment }
else
if sl_created
ShoppingList.find(#appointment.shopping_list_id).destroy
end
format.html { render :new }
format.json { render json: #appointment.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /shopping_processes/1
# PATCH/PUT /shopping_processes/1.json
def update
respond_to do |format|
if #appointment.update(appointment_params)
format.html { redirect_to #appointment, notice: t(:appointment_updated) }
format.json { render :show, status: :ok, location: #appointment }
else
format.html { render :edit }
format.json { render json: #appointment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /shopping_processes/1
# DELETE /shopping_processes/1.json
def destroy
#appointment.destroy
respond_to do |format|
format.html { redirect_to appointments_url, notice: t(:appointment_deleted) }
format.json { head :no_content }
end
end
def shopper_index
end
def ready_index
appointments_hash = {}
customers = User.where.not(current_appointment: nil).where(role: :senior)
customers.each {|user| appointments_hash[user.current_appointment.id] = user.current_appointment}
shoppers = User.where.not(current_appointment: nil).where(role: :shopper)
shoppers.each {|user| appointments_hash.delete(user.current_appointment.id)}
#appointments = []
appointments_hash.each { |appointment_id, appointment| #appointments.push(appointment)}
end
def shopper_show
#appointment = Appointment.find(params[:id])
#shopping_lists = get_both_lists
both_users = get_both_users
#users = {}
first = true
both_users.each do |user|
#users[user.id] = {color: (first ? 'blue' : 'yellow'), name: user.firstname + ' ' + user.lastname}
first = false
end
end
def senior_show
#appointment = Appointment.find(params[:id])
if #appointment.user == current_user
#shopping_list = #appointment.shopping_list
else
#shopping_list = #appointment.invitation.shopping_list
end
#D.S.:Diese zuweisung funktioniert nicht richtig. Sie wurde vor den DB änderung erstellt und muss angepasst werden
#D.S.:ShoppingItem.joins(:list_item) und ListItem.where(shopping_list_id: #shopping_list.id]) ergeben ein korrektes Resultat
#D.S.:Aber zusammengenommen ist die query leer
##shopping_items = ShoppingItem.joins(:list_item).where(list_item: [shopping_list_id: #shopping_list.id])
end
private def get_both_lists
shopping_lists = [ #appointment.shopping_list]
if #appointment.invitation && #appointment.invitation.shopping_list
shopping_lists << #appointment.invitation.shopping_list
end
shopping_lists
end
private def get_both_users
users = [ #appointment.user]
if #appointment.invitation
users.push(#appointment.invitation.user)
end
users
end
private
# Use callbacks to share common setup or constraints between actions.
def set_appointment
#appointment = Appointment.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def appointment_params
params.require(:appointment).permit(:shopper_id, :status, :appointed, :processed, :shopping_list_id, invitation_attributes: [:user_id, :message ])
end
def create_shopping_list?
if #appointment.shopping_list_id.blank?
name = "Liste für den " + #appointment.appointed.strftime("%d.%m.%Y").to_s
invitee_id = "" + (#appointment.invitation.user_id.to_s) if #appointment.invitation
name = name + ( " mit " + User.find(invitee_id).firstname) unless invitee_id.blank?
sl = current_user.shopping_lists.create(:name => name)
#appointment.shopping_list_id = sl.id
true
else
false
end
end
end
And here is the Error I get when I run the test:
Error:
AppointmentsControllerTest#test_should_get_new:
NoMethodError: undefined method `env' for nil:NilClass
Does somebody know the solution? I would be very thankful
UPDATE: include Devise::TestHelpers is deprecated. Now I use include Devise::Test::IntegrationHelpers. Now my appointments_controller_test.rb looks like this:
require 'test_helper'
class AppointmentsControllerTest < ActionDispatch::IntegrationTest
include Devise::Test::IntegrationHelpers
def sign_in(user)
post user_session_path \
"heiko#me.com" => user.email,
"hhdk#s0" => user.password
end
setup do
#heikoAppointment = appointments(:appointment_heiko)
#heiko = users(:user_heiko)
sign_in(#heiko)
end
test "should get index" do
get appointments_url
assert_response :success
end
test "should get new" do
sign_in(#heiko)
get new_appointment_url
assert_response :success
end
However I get another error:
AppointmentsControllerTest#test_should_get_new [C:/Users/Clemens/meindorfladen/Server/test/controllers/appointments_controller_test.rb:33]:
Expected response to be a <2XX: success>, but was a <302: Found> redirect to <http://www.example.com/users/sign_in>
Does somebody knows why there is this redirect to http://www.example.com/users/sign_in? I thought now the user is signed in

You should include Devise::Test::IntegrationHelpers not Devise::TestHelpers as per the readme.

Related

Rails - How to pass controller tests when I use before_action

I need to run some tests and I have come at a stand still here.
I am using before_action in my Appointments controller
Here is the controller
class AppointmentsController < ApplicationController
before_action :set_appointment, only: %i[ show edit update destroy ]
#before we run anything if the user is not signed in show index and show functions
before_action :authenticate_user!, except: [:index,:show]
#only the correct user can edit,update and destroy
before_action :correct_user, only: [:edit, :update , :destroy]
# GET /appointments or /appointments.json
def index
#appointments = Appointment.all.decorate
end
# GET /appointments/1 or /appointments/1.json
def show
end
# GET /appointments/new
def new
##appointment = Appointment.new
#appointment = current_user.appointments.build
end
# GET /appointments/1/edit
def edit
end
#function to allow for search functionality
def search
#appointments = Appointment.where("date LIKE?", "%"+params[:q]+"%")
end
# POST /appointments or /appointments.json
def create
##appointment = Appointment.new(appointment_params)
#appointment = current_user.appointments.build(appointment_params)
#here underneath I am using my custom gem to filter bad words within the notes field when creating an appointment
#appointment.notes = Badwordgem::Base.sanitize(#appointment.notes)
respond_to do |format|
if #appointment.save
format.html { redirect_to appointment_url(#appointment), notice: "Appointment was successfully created." }
format.json { render :show, status: :created, location: #appointment }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #appointment.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /appointments/1 or /appointments/1.json
def update
respond_to do |format|
if #appointment.update(appointment_params)
format.html { redirect_to appointment_url(#appointment), notice: "Appointment was successfully updated." }
format.json { render :show, status: :ok, location: #appointment }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #appointment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /appointments/1 or /appointments/1.json
def destroy
#appointment.destroy
respond_to do |format|
format.html { redirect_to appointments_url, notice: "Appointment was successfully destroyed." }
format.json { head :no_content }
end
end
#function here that restricts editing so the current logged in user can edit only their records
def correct_user
#appointment = current_user.appointments.find_by(id: params[:id])
redirect_to appointments_path, notice:"NOT ALLOWED TO EDIT THIS" if #appointment.nil?
end
private
# Use callbacks to share common setup or constraints between actions.
def set_appointment
#appointment = Appointment.find(params[:id])
end
# Only allow a list of trusted parameters through.
def appointment_params
params.require(:appointment).permit(:barber, :customer, :notes, :date,:user_id)
end
end
and here is my test controller
require "test_helper"
class AppointmentsControllerTest < ActionDispatch::IntegrationTest
Devise::Test::IntegrationHelpers
setup do
#appointment = appointments(:one)
end
test "should get index" do
get appointments_url
assert_response :success
end
test "should get new" do
get new_appointment_url
assert_response :success
end
test "should create appointment" do
assert_difference('Appointment.count') do
post appointments_url, params: { appointment: { barber: #appointment.barber, customer: #appointment.customer, date: #appointment.date, notes: #appointment.notes } }
end
assert_redirected_to appointment_url(Appointment.last)
end
test "should show appointment" do
get appointment_url(#appointment)
assert_response :success
end
test "should get edit" do
get edit_appointment_url(#appointment)
assert_response :success
end
test "should update appointment" do
patch appointment_url(#appointment), params: { appointment: { barber: #appointment.barber, customer: #appointment.customer, date: #appointment.date, notes: #appointment.notes } }
assert_redirected_to appointment_url(#appointment)
end
test "should destroy appointment" do
assert_difference('Appointment.count', -1) do
delete appointment_url(#appointment)
end
assert_redirected_to appointments_url
end
end
If I comment out the "before actions" in my controller , of course all the tests pass but with them 15 tests fail.
How do I make the tests pass with the before_action ?
For :authenticate_user just use the helper log_in in te test, after create a user, like this:
class AppointmentsControllerTest < ActionDispatch::IntegrationTest
let(:user) { User.new(user_params) }
......
and put
sign_ig user
inside each 'it methods you want'
For :set_appointment or :correct_user just passing right id params inside the path's call

NoMethodError:undefined method `employee' for nil:NilClass for RSPEC test Rails

I want to run the rspec of Tickets controllers, I Have used scaffold and I have made some changes according to my project.
but I am getting some errors. I also have a login (using Devise).
How do I go ahead?
This is the controller-
class TicketsController < ApplicationController
before_action :set_ticket, only: %i[ show edit update destroy assign]
before_action :set_assign_ticket, only: %i[assignid]
# shows the landing page of employee
def landing
#tickets = current_user.employee.tickets.order('tstatus_id, id desc')
end
# Service engineer index showing the tickets which are assinged to him
def slanding
#tickets = Ticket.where(service_id: current_user.employee.service_id).order('tstatus_id, id desc')
end
# Showing tickets list based on the user type
def index
#tickets = if current_user.employee.designation.role == "ADMIN"
Ticket.all.order('tstatus_id ,id desc ')
else
Ticket.where(employee: current_user.employee)
end
end
def show
#tickets = Ticket.all
end
def new
#ticket = Ticket.new
end
#creating a new ticket
def create
#ticket = Ticket.new(ticket_params)
#ticket.employee = current_user.employee
respond_to do |format|
if #ticket.save
format.html { redirect_to landing_path}
else
format.html { render :new, status: :unprocessable_entity }
end
end
end
# updating a ticket
def update
respond_to do |format|
if #ticket.update(ticket_params)
if current_user.employee.designation.role == "ADMIN"
format.html { redirect_to tickets_url }
else
format.html { redirect_to slanding_path }
end
else
format.html { render :edit, status: :unprocessable_entity }
end
end
end
private
def set_ticket
#ticket = Ticket.where(id: params[:id]).first
end
def ticket_params
params.require(:ticket).permit(:kind, :description, :dev_id, :service_id,:tstatus_id)
end
def set_assign_ticket
#ticket = Ticket.find(params[:id])
end
end
This is the model -
class Ticket < ApplicationRecord
belongs_to :service, optional: true
belongs_to :employee
belongs_to :tstatus
before_validation(on: :create) do
self.service_id = 4 # this will assign the service engineer to NONE
self.tstatus_id = 1 # this will assign the status to logged
end
validates :description, presence: true
end
My test cases are:
require 'rails_helper'
describe TicketsController, type: :controller do
# describe 'GET show' do
it 'gets show based on ID' do
#ticket = Ticket.new(id: 1,kind: "Example Ticket", description: "Ticket#example.com", service_id: 1, employee_id: 1,tstatus_id:1)
get :show, params: { id: #ticket.id }
expect(response.status).to eq(200)
end
# describe 'GET edit' do
it 'has 200 status code' do
get :new
expect(response.status).to eq(200)
end
describe 'POST create' do
it 'has 200 status code' do
mock = double('Employee')
expect(mock).to receive(:employee_id)
post :create, params: {
ticket: {
id: 1,kind: "Example Ticket", description: "Ticket#example.com", service_id: 1, employee_id: 1,tstatus_id:1
}
}
expect(response.status).to eq 302
end
end
end
I am a newbie to rails,
Can someone tell me how to write test cases for the controller above?

How to save data in rails in oracle db without id column?

I have a table DIM_STORE with columns STORE_ID, STORE_NAME, CLIENT_CODE, CREATE_TIMESTAMP, UPDATE_TIMESTAMP.
How to save a new record to oracle db in rails? STORE_ID, STORE_NAME and CLIENT_CODE are of varchar type. And I have a form through which I need to add a new store.
I am getting error as,
NoMethodError: undefined method \`returning_id?' for nil:NilClass: INSERT INTO "DIM_STORE" ("STORE_NAME", "STORE_ID", "CLIENT_CODE", "STORE_ID") VALUES (:a1, :a2, :a3, :a4)))
stores_controller.rb,
class StoresController < ApplicationController
protect_from_forgery with: :null_session, if: Proc.new {|c| c.request.format == 'application/json'}
before_filter :authenticate_user!, :is_admin
before_action :get_client
before_action :set_store, only: [:show, :edit, :update, :destroy]
# GET /stores
# GET /stores.json
def index
#stores = Store.where("CLIENT_CODE = ?", #client.client_code)
respond_to do |format|
if request.format == :json
format.json { render json: #stores.all}
else
format.js
format.html
end
end
end
# GET /stores/1
# GET /stores/1.json
def show
end
# GET /stores/new
def new
respond_to do |format|
#store = Store.new
format.js
format.html
end
end
def form
end
def new_store
end
# GET /stores/1/edit
def edit
end
# POST /stores
# POST /stores.json
def create
#store = Store.new(store_params)
#store.client_code = #client.client_code
puts #store
respond_to do |format|
if #store.save
format.js
else
format.js {render "stores/new"}
format.json {render json: #store.errors, status: :unprocessable_entity}
end
end
end
#GET /stores/create_success
def create_success
redirect_to request.referrer, notice: 'Store was successfully created under client.'
end
# PATCH/PUT /stores/1
# PATCH/PUT /stores/1.json
def update
respond_to do |format|
if #store.update(store_params)
format.js
else
format.js {render 'stores/edit'}
format.json {render json: #store.errors, status: :unprocessable_entity}
end
end
end
#GET /stores/update_success
def update_success
redirect_to request.referrer, notice: 'Store was successfully updated.'
end
# DELETE /stores/1
# DELETE /stores/1.json
def destroy
stores_users = #store.users
if stores_users.nil? || stores_users.empty?
#store.destroy
redirect_to request.referrer, notice: 'Store was successfully destroyed.'
else
redirect_to request.referrer, notice: 'Users still associated with store. Cannot delete store'
end
end
def get_client
#client = Client.friendly.find(params[:client_id])
puts #client.client_code
=begin
#client = Client.find_by_sql ["SELECT * FROM DIM_CLIENT WHERE client_code = ? ", params[:client_id]]
puts #client;
#client.each do |c|
#client_code = c[:client_code]
#client_name = c[:client_name]
end
puts #client_code
=end
=begin
#client.each do |c|
puts c[:client_code];
end
=end
=begin
#client = Client.find_by_sql ["SELECT client_code FROM DIM_CLIENT WHERE client_code = ? ", :client_code]
=end
end
private
def set_store
=begin
#store = Store.find_by_sql ["SELECT store_id FROM DIM_STORE WHERE store_id = ? ", params[:id]]
=end
#store = Store.friendly.find(params[:id])
end
def store_params
params.require(:store).permit(:store_name, :store_id, :client_code)
end
end

Rails test failure 500 when I use .includes

I'm developing a small e-commerce and I´ve a problem when I run the tests for my cart controller.
here cart controller
class CartsController < ApplicationController
include CurrentCart #modul current_cart in controllers/concerns
before_action :set_cart, only: [:show, :edit, :update, :destroy]
before_action :set_current_cart, only: [:index]
# GET /carts
# GET /carts.json
def index
respond_to do |format|
format.html { redirect_to #cart, notice: 'Line item was successfully created.' }
format.json { render :show, status: :created, location: #line_item }
end
end
# GET /carts/1
# GET /carts/1.json
def show
end
# GET /carts/new
def new
#cart = Cart.new
end
# GET /carts/1/edit
def edit
end
# POST /carts
# POST /carts.json
def create
#cart = Cart.new(cart_params)
respond_to do |format|
if #cart.save
format.html { redirect_to #cart, notice: 'Cart was successfully created.' }
format.json { render :show, status: :created, location: #cart }
else
format.html { render :new }
format.json { render json: #cart.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /carts/1
# PATCH/PUT /carts/1.json
def update
respond_to do |format|
if #cart.update(cart_params)
format.html { redirect_to #cart, notice: 'Cart was successfully updated.' }
format.json { render :show, status: :ok, location: #cart }
else
format.html { render :edit }
format.json { render json: #cart.errors, status: :unprocessable_entity }
end
end
end
# DELETE /carts/1
# DELETE /carts/1.json
def destroy
#cart.destroy if #cart.id == session[:cart_id]
session[:cart_id] = nil
respond_to do |format|
format.html { redirect_to catalog_index_url, notice: 'Cart was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_cart
#cart = Cart.includes(line_items: :product).find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def cart_params
params.fetch(:cart, {})
end
end
and here my tests:
require 'test_helper'
class CartsControllerTest < ActionDispatch::IntegrationTest
setup do
#line_item = line_items(:one)
#product = products(:one)
#cart = carts(:one)
end
test "should get index" do
get carts_url
assert_response :success
end
test "should get new" do
get new_cart_url
assert_response :success
end
test "should create cart" do
assert_difference('Cart.count') do
post carts_url, params: { cart: {} }
end
assert_redirected_to cart_url(Cart.last)
end
test "should show cart" do
get cart_url(#cart)
assert_response :success
end
test "should get edit" do
get edit_cart_url(#cart)
assert_response :success
end
test "should update cart" do
patch cart_url(#cart), params: { cart: {} }
assert_redirected_to cart_url(#cart)
end
test "should destroy cart" do
post line_items_url, params: { product_id: products(:one).id }
#cart = Cart.find(session[:cart_id])
assert_difference('Cart.count', -1) do
delete cart_url(#cart)
end
assert_redirected_to catalog_index_url
end
end
here the results:
Failure: CartsControllerTest#test_should_destroy_cart Expected
response to be a <3XX: redirect>, but was a <500: Internal Server
Error>
Failure: CartsControllerTest#test_should_get_edit Expected response
to be a <2XX: success>, but was a <500: Internal Server Error>
Failure: CartsControllerTest#test_should_update_cart Expected
response to be a <3XX: redirect>, but was a <500: Internal Server
Error>
here is the modul current cart for the cartsController:
module CurrentCart
private
def set_current_cart
#cart = Cart.find(session[:cart_id])
rescue ActiveRecord::RecordNotFound
#cart = Cart.create
session[:cart_id] = #cart.id
end
end
I think that the problem is here:
if I remove this in the method set_cart from the cart controller: .includes(line_items: :product) the tests will run perfectly without failure, but I cannot understand why.
(I put the include because otherwise I get this error when I access the cart from the browser:
USE eager loading detected LineItem => [:product] Add to your
finder: :includes => [:product] Call stack
UPDATE:
I found something interesting in the file "test.log" :
Bullet::Notification::UnoptimizedQueryError - user: claudio
DELETE /carts/980190963
AVOID eager loading detected
LineItem => [:product]
Remove from your finder: :includes => [:product]
Call stack
##here there's a path##.rb:45:in `block (2 levels) in <class:CartsControllerTest>'
##here there's a path##:in `block in <class:CartsControllerTest>'

Ruby on Rails controller test

I have a problem with my testing. I have used scaffolds to create my app, but changed something in my controllers. My first controller looks as follow
class ChildrenController < ApplicationController
before_action :set_child, only: [:show, :edit, :update, :destroy]
require 'httparty'
# require 'open-uri'
include HTTParty
# include I18n
def child_admin
#children = Child.all
end
# GET /children
# GET /children.json
def index
#children = Child.all
end
# GET /children/1
# GET /children/1.json
def show
#child = Child.find(params[:id])
authorize! :read, #child
end
# GET /children/new
def new
#child = Child.new
end
# GET /children/1/edit
def edit
end
# POST /children
# POST /children.json
def create
#kigas = Kiga.all
#relations = Relation.all
#child = Child.new child_params
#child.user = current_user
url = "https://maps.googleapis.com/maps/api/geocode/json?address=#{I18n.transliterate(#child.city)}+#{I18n.transliterate(#child.streed)}+#{#child.add_number}&key=AIzaSyBWwoVj5WQMN9-Ij7IJWxQL1CzuigzBsYc"
latlongchild = HTTParty.get(url)
# puts latlongchild
# puts latlongchild["results"].first["geometry"]["location"]
childlat=latlongchild["results"].first["geometry"]["location"]["lat"]
childlng=latlongchild["results"].first["geometry"]["location"]["lng"]
# #child.save
respond_to do |format|
if #child.save
format.html { redirect_to #child, notice: 'Kind wurde erfolgreich registriert.' }
format.json { render :show, status: :created, location: #child }
else
format.html { render :new }
format.json { render json: #child.errors, status: :unprocessable_entity }
end
end
#kigas.each do |kiga|
url2 = "https://maps.googleapis.com/maps/api/distancematrix/json?origins=#{I18n.transliterate(#child.city)}+#{I18n.transliterate(#child.streed)}+#{#child.add_number}&destinations=#{I18n.transliterate(kiga.city)}+#{I18n.transliterate(kiga.streed)}+#{kiga.add_number}&key=AIzaSyDjh9hMXm_lnIyaj_HLQpGvDcDasLjyhxk"
response = HTTParty.get(url2)
mesponse=response["rows"].first["elements"].first["distance"]["value"]
url3 = "https://maps.googleapis.com/maps/api/geocode/json?address=#{I18n.transliterate(kiga.city)}+#{I18n.transliterate(kiga.streed)}+#{kiga.add_number}&key=AIzaSyBWwoVj5WQMN9-Ij7IJWxQL1CzuigzBsYc"
response2 = HTTParty.get(url3)
kigalat=response2["results"].first["geometry"]["location"]["lat"]
kigalng=response2["results"].first["geometry"]["location"]["lng"]
# puts mesponse
# puts mysponse
# puts #child.id
# puts kiga.id
#relation = Relation.new relation_params
#relation.child_id = #child.id
#relation.kiga_id = kiga.id
#relation.distance = mesponse
#relation.kigalat = kigalat
#relation.kigalong = kigalng
#relation.childlat = childlat
#relation.childlong = childlng
#relation.user_id = #child.user_id
#relation.save
end
end
# PATCH/PUT /children/1
# PATCH/PUT /children/1.json
def update
respond_to do |format|
if #child.update(child_params)
format.html { redirect_to #child, notice: 'Kind wurde erfolgreich angepasst.' }
format.json { render :show, status: :ok, location: #child }
else
format.html { render :edit }
format.json { render json: #child.errors, status: :unprocessable_entity }
end
end
end
# DELETE /children/1
# DELETE /children/1.json
def destroy
#child.destroy
respond_to do |format|
format.html { redirect_to children_url, notice: 'Kind wurde erfolgreich ausgetragen.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_child
#child = Child.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def child_params
params.require(:child).permit(:name, :city, :postalcode, :streed, :add_number, :disability, :halal, :koscha, :vegetarian, :vegan, :allday, :gender)
end
def set_relation
#relation = Relation.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def relation_params
# params.require(:relation).permit(:kiga_id, :child_id, :assignment, :preference, :distance)
end
end
and my controller test as follows:
require 'test_helper'
class ChildrenControllerTest < ActionDispatch::IntegrationTest
setup do
#child = children(:one)
end
test "should get index" do
get children_url
assert_response :success
end
test "should get new" do
get new_child_url
assert_response :success
end
test "should create child" do
assert_difference('Child.count') do
post children_url, params: { child: { add_number: #child.add_number, allday: #child.allday, city: #child.city, disability: #child.disability, gender: #child.gender, halal: #child.halal, koscha: #child.koscha, name: #child.name, postalcode: #child.postalcode, streed: #child.streed, vegan: #child.vegan, vegetarian: #child.vegetarian } }
end
assert_redirected_to child_url(Child.last)
end
test "should show child" do
get child_url(#child)
assert_response :success
end
test "should get edit" do
get edit_child_url(#child)
assert_response :success
end
test "should update child" do
patch child_url(#child), params: { child: { add_number: #child.add_number, allday: #child.allday, city: #child.city, disability: #child.disability, gender: #child.gender, halal: #child.halal, koscha: #child.koscha, name: #child.name, postalcode: #child.postalcode, streed: #child.streed, vegan: #child.vegan, vegetarian: #child.vegetarian } }
assert_redirected_to child_url(#child)
end
test "should destroy child" do
assert_difference('Child.count', -1) do
delete child_url(#child)
end
assert_redirected_to children_url
end
end
and I've also defined some abilities:
class Ability
include CanCan::Ability
def initialize(user)
if user.admin?
can :manage, :all
can :view, Child
can :view, Kiga
can :read, Kiga
can :read, Child
can :read, User
elsif user.role == 'Eltern'
can [:update, :destroy], Child do |child|
child.user_id == user.id
end
can :view, Child do |child|
child.user_id == user.id
end
can :read, Child do |child|
child.user_id == user.id
end
can :create, Child
can :read, Kiga
can :results_child, Child
can [:read, :view], Relation do |relation|
relation.user_id == user.id
end
else
end
end
end
I'm usingtest_helper and cancanfor the abilities. I thought my change in the abilities destroyed my testing, because my index, show, create and update test produces errors with the following massage
ActionView::Template::Error: undefined method 'admin?' for nil:NilClass
Can someone help me and can tell me, how I have to rearrange my controller and tests? Or is there another big mistake?
Thank you very much!
The user.admin? call is what's causing the error.
The ability.rb that gets generated by cancancan includes a commented out line as part of the example:
# user ||= User.new # guest user (not logged in)
This is because when you don't have a signed in user nil gets passed in to create the Ability instance.
With user ||= User.new it means that you have an actual, although not saved, user instance to interact with. Putting that line as the first in your initialize method for Ability is probably easier than making all your user checks something like if user && user.admin?.

Resources