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'
Related
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.
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.
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?
I'm now making Rspec test for users_controller.rb. However I'm in trouble the error NoMethodError: undefined method 'user_url' as follow.
FF
Failures:
1) UsersController PUT update user update does not succeed
Failure/Error: put :update, {:id => user.to_param}, valid_session, :user_route => user
NoMethodError:
undefined method `user_url' for #<UsersController:0x52e40e0>
# ./app/controllers/users_controller.rb:21:in `block (2 levels) in update'
# ./app/controllers/users_controller.rb:18:in `update'
# ./spec/controllers/users_controller_spec.rb:64:in `block (3 levels) in <top (required)>'
2) UsersController PUT update user update succeeds
Failure/Error: put :update, {:id => user.to_param}, valid_session, :user_route => user
NoMethodError:
undefined method `user_url' for #<UsersController:0x53bc560>
# ./app/controllers/users_controller.rb:21:in `block (2 levels) in update'
# ./app/controllers/users_controller.rb:18:in `update'
# ./spec/controllers/users_controller_spec.rb:58:in `block (3 levels) in <top (required)>'
Finished in 0.679 seconds
2 examples, 2 failures
Failed examples:
rspec ./spec/controllers/users_controller_spec.rb:61 # UsersController PUT update user update does not succeed
rspec ./spec/controllers/users_controller_spec.rb:56 # UsersController PUT update user update succeeds
Randomized with seed 33412
users_controller.rb
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #user }
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "user#edit" }
format.json { render json: #idea.errors, status: :unprocessable_entity }
end
end
end
end
Also here is my Rspec users_controller_spec.rb. I made two tests about "POST update". One is for being updated successfully. Another is for not being updated. (About the latter, I put the stub User.stub(:update_attribute).and_return(false) which I expect that "update_attribute" returns "false" so that process proceeds to "else".)
require 'spec_helper'
describe UsersController do
let(:valid_attributes) { {
"email" => "hoge#hogehoge.com",
"password" => "12345678"
} }
def valid_session
{}
end
describe "PUT update" do
it "user update succeeds" do
user = User.create! valid_attributes
put :update, {:id => user.to_param}, valid_session
assigns(:user).should eq(user)
end
it "user update does not succeed" do
user = User.create! valid_attributes
User.stub(:update_attribute).and_return(false)
put :update, {:id => user.to_param}, valid_session
assigns(:user).should eq(user)
response.should render_template("edit")
end
end
end
I have no idea to solve this, because I cannot understand where user_url did come. So I would like to have your help.
When you use redirect_to #user, rails sends that request to UsersController#show, but it does so by calling user_url(#user). If I had to guess, you probably don't have the line that defines user_url:
resources :users
in your routes.rb file. This would automatically create the named route user_url that your controller is referencing with redirect_to #user
Alternatively, you could define the route yourself in your routes.rb file like so:
get "/users/show" => "users#show", as: :user
But that's not really the 'Rails-y' way to do it. At any time, you can run the command rake routes in the terminal to see all the named routes you have defined in your routes.rb file. If user isn't there, then you need to define it like I mentioned above.
More info on named routes here: http://guides.rubyonrails.org/routing.html#singular-resources
If you are using devise then check if the following method returns anything.
def after_sign_in_path_for(resource)
in application_controller.rb
If the method returns nothing you will receive the error:
undefined method `user_url' for #
I also ended up removing
stored_location_for(resource)
in after_sign_in_path_for(resource) because it was causing an endless loop. Refer to this answer for details.
rails:3 Devise signup Filter chain halted as :require_no_authentication rendered or redirected
In my controller I have:
class UsersController < ApplicationController
load_and_authorize_resource
def create
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render json: #user, status: :created, location: #user }
else
format.html { render action: "new" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
end
But I get undefined method 'save' for nil:NilClass
Failures:
1) UsersController if the user passes all the authorizations POST #create should create a new User with some parameters
Failure/Error: post :create, :user => { :email => 'puppa#puppa.pup' }
NoMethodError:
undefined method `save' for nil:NilClass
# ./app/controllers/users_controller.rb:47:in `block in create'
# ./app/controllers/users_controller.rb:46:in `create'
# ./spec/controllers/users_controller_spec.rb:66:in `block (4 levels) in <top (required)>'
Finished in 0.10714 seconds
1 example, 1 failure
I was expecting load_resources to populate #user = User.new(params[:user])
I was looking at CanCan internals following the entire flow and I discovered that in controller_resource.rb when we reach #build_resource we have:
def build_resource
resource = resource_base.new(resource_params || {})
assign_attributes(resource)
end
But resource here is nil... it's normal? what I'm missing? It's related with my problem with create action?
EDIT
here is my ability.rb
class Ability
include CanCan::Ability
def initialize(user)
# Define abilities for the passed in user here. For example:
# check if the user is registered or a guest user (not logged in)
if user.present?
if user.any_role? :super_admin
can :manage, :all
end
if user.any_role? :admin
can :manage, [User, Institution, Project, Order]
end
if user.any_role? :user
can :show, Project
can [:add, :change], :cart
can [:create, :show], Order, :user_id => user.id
can :download, UrlConnector
end
end
end
end
EDIT 2
While calling POST create I have:
in RSpec environment:
resource_base: User
resource_class: User
#params: {"user"=>{"email"=>"puppa#puppa.pup"}, "controller"=>"users", "action"=>"create"}
in browser as superadmin or admin, it's the same:
resource_base: User
resource_class: User
#params: {"utf8"=>"✓", "authenticity_token"=>"95qQ4H/+CLU96jCIO6U/YtgIQ5zWxE7pg0BedVMPSGk=", "user"=>{"email"=>"estanost#alumnes.ub.edu", "password"=>"264763", "password_confirmation"=>"264763", "ragionesociale"=>"fff", "partitaiva"=>"12345678901", "address"=>"via plutarco, 36", "city"=>"Manduria", "cap"=>"74024", "phone"=>"099979456", "role_ids"=>["3"]}, "commit"=>"Create User", "action"=>"create", "controller"=>"users"}
Try placing cancan as the last gem in the Gemfile
I think you should get rid of the if user.present? block, add user ||= User.new where that if block starts. This way, you will always have a user object. Of course, it won't pass any of your cancans, so the rest should fall through gracefully.