Rspec | Missing id for create controller - ruby-on-rails

I am getting Id missing nil error in my create controller spec. Yet I have passed ID stuff in it still facing same everytime. Here my create spec and controller file
Create Spec
describe 'POST :create' do
context 'with valid data' do
let(:valid_data) { FactoryGirl.attributes_for(:student) }
it 'redirect to show page' do
post :create, student: valid_data
expect(response).to redirect_to(student_path(assigns[:student]))
end
end
end
Student Controller
def create
#student = current_user.students.build(student_params)
respond_to do |format|
if #student.save
format.html { redirect_to #student }
format.json { render :show, status: :created, location: #student }
else
format.html { render :new }
format.json { render json: #student.errors, status: :unprocessable_entity }
end
end
end
private
def student_params
params.require(:student).permit(:Student_Prefix, :First_Name, :Middle_Name, :Last_Name, :Father_Prefix, :Father_Name, :Father_Middle_Name, :Father_Last_Name, :Mother_Prefix, :Mother_Name, :Mother_Middle_Name, :Mother_Last_Name, :user_id)
end
Error
1) StudentsController POST :create with valid data redirect to show page
Failure/Error: expect(response).to redirect_to(student_path(assigns[:student]))
ActionController::UrlGenerationError:
No route matches {:action=>"show", :controller=>"students", :id=>nil} missing required keys: [:id]
# ./spec/controllers/students_controller_spec.rb:38:in `block (4 levels) in <top (required)>'
# -e:1:in `<main>'

Your save is failing in StudentsController, so #student doesn't have an ID. You're getting the error when you try to build the path in your spec:
expect(response).to redirect_to(student_path(assigns[:student]))
assigns[:student] doesn't have an ID.

Related

Parsing Api with Httparty NoMethodError: undefined method `each' for nil:NilClass

Hi I am parsing JSON API from https://api.commissionfactory.com/V1/ via rake task
desc "run feed"
task :mr => :environment do
include HTTParty
url = 'https://api.commissionfactory.com/V1/Affiliate/Merchants?apiKey=fakekey&status=Joined'
response = HTTParty.get(url).parsed_response
response.each do |item|
Vendor.find_or_create_by(name: item['Name'])
end
end
I can get the json data but not parse it via response.each or response.map
When I try with the code above I get a
rake aborted!
NoMethodError: undefined method `each' for nil:NilClass
when I puts response I get the data below as expected:
{"Id"=>201, "DateCreated"=>"2014-04-10T10:47:35.747", "DateModified"=>"2017-06-11T00:00:32.11", "Name"=>"Tony's Furniture", "AvatarUrl"=>"https://c.url.com/io/39BD094A-24B5-4659-8A7A-FE6E023E9ED8.png"}
and I can manipulate the data via
response.map do |item|
puts item['Name']
puts item['Category']
puts item['TargetUrl']
puts item['Summary']
puts item['TrackingUrl']
puts item['AvatarUrl']
end
but as soon as i try to create or save records i get the same issue.
Vendors Controller
class VendorsController < ApplicationController
before_action :set_vendor, only: [:show, :edit, :update, :destroy]
# GET /vendors
# GET /vendors.json
def index
#vendors = Vendor.all
end
# GET /vendors/1
# GET /vendors/1.json
def show
#products = #vendor.products.find(params[:id])
end
# GET /vendors/new
def new
#vendor = Vendor.new
end
# GET /vendors/1/edit
def edit
end
# POST /vendors
# POST /vendors.json
def create
#vendor = Vendor.new(vendor_params)
respond_to do |format|
if #vendor.save
format.html { redirect_to #vendor, notice: 'Vendor was successfully created.' }
format.json { render :show, status: :created, location: #vendor }
else
format.html { render :new }
format.json { render json: #vendor.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /vendors/1
# PATCH/PUT /vendors/1.json
def update
respond_to do |format|
if #vendor.update(vendor_params)
format.html { redirect_to #vendor, notice: 'Vendor was successfully updated.' }
format.json { render :show, status: :ok, location: #vendor }
else
format.html { render :edit }
format.json { render json: #vendor.errors, status: :unprocessable_entity }
end
end
end
# DELETE /vendors/1
# DELETE /vendors/1.json
def destroy
#vendor.destroy
respond_to do |format|
format.html { redirect_to vendors_url, notice: 'Vendor was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_vendor
#vendor = Vendor.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def vendor_params
params.require(:vendor).permit(:name, :description, :Category, :TargetUrl, :Summary, :TrackingUrl, :AvatarUrl)
end
end
Vendor Model
class Vendor < ApplicationRecord
has_many :products
has_many :brands
end
While I have parsed xml data with nokogiri this is my first json parse with httparty. Can you please point out why I cannot seem to parse the data into the rails vendor db
With a little help from a mentor we were able to discover that the
include HTTParty
in my task
desc "run feed"
task :mr => :environment do
include HTTParty
url = 'https://api.commissionfactory.com/V1/Affiliate/Merchants?apiKey=fakekey&status=Joined'
response = HTTParty.get(url).parsed_response
response.each do |item|
Vendor.find_or_create_by(name: item['Name'])
end
end
was throwing the error. with its removal, the task passed.
As an older library, the include statement imports the entire library, which in this case threw the error and was not related to my needs.

Devise create user and login on test setup

app/controllers/categories_controller.rb:
class CategoriesController < ApplicationController
before_action :set_category, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
# GET /categories
# GET /categories.json
def index
#categories = Category.all
end
# GET /categories/1
# GET /categories/1.json
def show
if session[:cart] then
#cart = session[:cart]
else
#cart = {}
end
end
# GET /categories/new
def new
if current_user.admin?
#category = Category.new
end
end
# GET /categories/1/edit
def edit
if current_user.admin?
end
end
# POST /categories
# POST /categories.json
def create
if current_user.admin?
#category = Category.new(category_params)
respond_to do |format|
if #category.save
format.html { redirect_to #category, notice: 'Category was successfully created.' }
format.json { render :show, status: :created, location: #category }
else
format.html { render :new }
format.json { render json: #category.errors, status: :unprocessable_entity }
end
end
end
end
# PATCH/PUT /categories/1
# PATCH/PUT /categories/1.json
def update
if current_user.admin?
respond_to do |format|
if #category.update(category_params)
format.html { redirect_to #category, notice: 'Category was successfully updated.' }
format.json { render :show, status: :ok, location: #category }
else
format.html { render :edit }
format.json { render json: #category.errors, status: :unprocessable_entity }
end
end
end
end
# DELETE /categories/1
# DELETE /categories/1.json
def destroy
if current_user.admin?
#category.destroy
respond_to do |format|
format.html { redirect_to categories_url, notice: 'Category was successfully destroyed.' }
format.json { head :no_content }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_category
#category = Category.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def category_params
params.require(:category).permit(:name, :desc)
end
end
In the controller above I'm preventing standard users to create, update or destroy categories by checking if current_user.admin?. But it's causing some problems in the tests.
test/controllers/categories_controller.rb:
require 'test_helper'
class CategoriesControllerTest < ActionController::TestCase
setup do
#category = categories(:one)
end
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:categories)
end
test "should get new" do
get :new
assert_response :success
end
test "should create category" do
assert_difference('Category.count') do
post :create, category: { desc: #category.desc, name: #category.name }
end
assert_redirected_to category_path(assigns(:category))
end
test "should show category" do
get :show, id: #category
assert_response :success
end
test "should get edit" do
get :edit, id: #category
assert_response :success
end
test "should update category" do
patch :update, id: #category, category: { desc: #category.desc, name: #category.name }
assert_redirected_to category_path(assigns(:category))
end
test "should destroy category" do
assert_difference('Category.count', -1) do
delete :destroy, id: #category
end
assert_redirected_to categories_path
end
end
Because of the restriction, tests related with create, update or destroy are failing. I think I need to create an admin user and login on test setup. But I don't know how to do this.
I'm using Devise gem for users part of the app.
I'm running my tests with rake test:functionals. How can I simulate user create and login in my tests?
If you want to look to the whole project: https://github.com/mertyildiran/SCOR
You can use fixtures to create an admin user in the test database (you probably already have a test/fixtures/users.yml file), and Devise's Test helpers to sign in:
sign_in :user, users(:admin)
If your users are confirmable, remember to set a confirmed_at date.
Check out the Devise wiki article on testing Rails controllers.

Scaffold generated code not passing rspec

I am new to Rspec and I am following a tutorial, I ran the following commands on a new rails project:
bundle exec rails generate scaffold Person first_name:string last_name:string
bundle exec rake db:migrate db:test:prepare
bundle exec rspec
And I get 15 failures, some of them shown below:
1) PeopleController POST create with valid params redirects to the created person
Failure/Error: response.should redirect_to(Person.last)
NoMethodError:
undefined method `assertions' for #<RSpec::Rails::TestUnitAssertionAdapter::AssertionDelegator:0x007fe7b2417980>
# ./spec/controllers/people_controller_spec.rb:80:in `block (4 levels) in <top (required)>'
2) PeopleController POST create with invalid params assigns a newly created but unsaved person as #person
Failure/Error: post :create, {:person => { "first_name" => "invalid value" }}, valid_session
ArgumentError:
wrong number of arguments (1 for 2+)
# ./app/controllers/people_controller.rb:30:in `block in create'
# ./app/controllers/people_controller.rb:29:in `create'
# ./spec/controllers/people_controller_spec.rb:88:in `block (4 levels) in <top (required)>'
3) PeopleController POST create with invalid params re-renders the 'new' template
Failure/Error: post :create, {:person => { "first_name" => "invalid value" }}, valid_session
ArgumentError:
wrong number of arguments (1 for 2+)
# ./app/controllers/people_controller.rb:30:in `block in create'
# ./app/controllers/people_controller.rb:29:in `create'
# ./spec/controllers/people_controller_spec.rb:95:in `block (4 levels) in <top (required)>'
4) PeopleController DELETE destroy redirects to the people list
Failure/Error: response.should redirect_to(people_url)
NoMethodError:
undefined method `assertions' for #<RSpec::Rails::TestUnitAssertionAdapter::AssertionDelegator:0x007fe7b41b9510>
# ./spec/controllers/people_controller_spec.rb:156:in `block (3 levels) in <top (required)>'
5) PeopleController PUT update with valid params redirects to the person
Failure/Error: response.should redirect_to(person)
NoMethodError:
undefined method `assertions' for #<RSpec::Rails::TestUnitAssertionAdapter::AssertionDelegator:0x007fe7b3a4c188>
# ./spec/controllers/people_controller_spec.rb:122:in `block (4 levels) in <top (required)>'
...........
Here is the people controller its referring to
class PeopleController < ApplicationController
before_action :set_person, only: [:show, :edit, :update, :destroy]
# GET /people
# GET /people.json
def index
#people = Person.all
end
# GET /people/1
# GET /people/1.json
def show
end
# GET /people/new
def new
#person = Person.new
end
# GET /people/1/edit
def edit
end
# POST /people
# POST /people.json
def create
#person = Person.new(person_params)
respond_to do |format|
if #person.save
format.html { redirect_to #person, notice: 'Person was successfully created.' }
format.json { render :show, status: :created, location: #person }
else
format.html { render :new }
format.json { render json: #person.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /people/1
# PATCH/PUT /people/1.json
def update
respond_to do |format|
if #person.update(person_params)
format.html { redirect_to #person, notice: 'Person was successfully updated.' }
format.json { render :show, status: :ok, location: #person }
else
format.html { render :edit }
format.json { render json: #person.errors, status: :unprocessable_entity }
end
end
end
# DELETE /people/1
# DELETE /people/1.json
def destroy
#person.destroy
respond_to do |format|
format.html { redirect_to people_url, notice: 'Person was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_person
#person = Person.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def person_params
params.require(:person).permit(:first_name, :last_name)
end
end
Why is a scaffold generated code failing these rspec tests?
Are you also using minitest? Try changing the version in your gemfile to e.g.:
gem 'minitest', '~> 4.0'

Ruby on Rails "Couldnt find status id"

I'm doing this treehouse project, some kind of social network built with ruby on rails (http://teamtreehouse.com/library/building-social-features-in-ruby-on-rails-2).
I was trying to make a user unable to update an existing status from another user and got stuck. This is my statuses_controller.rb:
class StatusesController < ApplicationController
before_filter :authenticate_user!, only: [:new, :create, :edit, :update]
before_action :set_status, only: [:show, :edit, :update, :destroy]
# GET /statuses
# GET /statuses.json
def index
#statuses = Status.order("created_at DESC").to_a
end
# GET /statuses/1
# GET /statuses/1.json
def show
end
# GET /statuses/new
def new
#status = Status.new
end
# GET /statuses/1/edit
def edit
end
# POST /statuses
# POST /statuses.json
def create
#status = current_user.statuses.new(status_params)
respond_to do |format|
if #status.save
format.html { redirect_to #status, notice: 'Status was successfully created.' }
format.json { render action: 'show', status: :created, location: #status }
else
format.html { render action: 'new' }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /statuses/1
# PATCH/PUT /statuses/1.json
def update
#status = current_user.statuses.find(params[:id])
params[:status].delete(:user_id) if params[:status].has_key?(:user_id)
respond_to do |format|
if #status.update(status_params)
format.html { redirect_to #status, notice: 'Status was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
# DELETE /statuses/1
# DELETE /statuses/1.json
def destroy
#status.destroy
respond_to do |format|
format.html { redirect_to statuses_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_status
#status = Status.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def status_params
params.require(:status).permit(:content, :user_id)
end
end
While testing this (if a user 'should update status for the current user when logged in'), I got the following error:
1) Error:
StatusesControllerTest#test_should_update_status_for_the_current_user_when_logged_in:
ActiveRecord::RecordNotFound: Couldn't find Status with id=980190962 [WHERE "statuses"."user_id" = ?]
app/controllers/statuses_controller.rb:45:in `update'
test/controllers/statuses_controller_test.rb:76:in `block in <class:StatusesControllerTest>'
2) Error:
StatusesControllerTest#test_should_update_status_when_logged_in:
ActiveRecord::RecordNotFound: Couldn't find Status with id=980190962 [WHERE "statuses"."user_id" = ?]
app/controllers/statuses_controller.rb:45:in `update'
test/controllers/statuses_controller_test.rb:70:in `block in <class:StatusesControllerTest>'
12 tests, 24 assertions, 0 failures, 2 errors, 0 skips
This is my statuses_controller_test.rb:
test "should update status when logged in" do
sign_in users(:gustavo)
put :update, id: #status, status: { content: #status.content }
assert_redirected_to status_path(assigns(:status))
end
test "should update status for the current user when logged in" do
sign_in users(:gustavo)
put :update, id: #status, status: { content: #status.content, user_id: users(:paul).id }
assert_redirected_to status_path(assigns(:status))
assert_equal assigns(:status).user_id, users(:gustavo).id
end
And that's my fixture users.yml:
gustavo:
first_name: "Gustavo"
last_name: "Paiva"
email: "gustavorpaiva#gmail.com"
profile_name: "grpaiva"
paul:
first_name: "Paul"
last_name: "McCartney"
email: "paulmccartney#gmail.com"
profile_name: "paulpaul"
I'm using Rails 4.0.4, and I've already made some fixtures on treebook's code so it could work perfectly (i think it was made with Rails 2.x). Should that be the case or am I missing something here?
Ps.: This is my project link, before making this changes http://sheltered-everglades-2797.herokuapp.com/
Thanks!
Try #status.id in the put method instead of just #status
test "should update status when logged in" do
sign_in users(:gustavo)
put :update, id: #status.id, status: { content: #status.content }
assert_redirected_to status_path(assigns(:status))
end
If that doesn't work, can you post the code for how is the #status object is built in the controller test?

update with invalid attributes re-renders :new template instead of :edit

I have this action in controller:
def update
#board = Board.find(params[:board_id])
#category = Category.find(params[:id])
if #category.update_attributes(category_params)
flash[:notice] = "You sucessfully changed category name."
redirect_to settings_board_path(#board)
else
render :edit
end
end
And problem with this test case:
context "with invalid attributes" do
let(:updated_category) { FactoryGirl.attributes_for(:category, name: "") }
it "re-renders :edit template" do
patch :create, board_id: board, id: category, category: updated_category
expect(response).to render_template :edit
end
end
I get this error:
expecting <"edit"> but rendering with <["categories/new", "layouts/application"]>
Any idea why?
Your test is calling patch :create, not patch :update, so it's running the wrong action entirely.

Resources