Why can't rspec find _path method? - ruby-on-rails-3

The app's routes.rb has
resources :users, :only => :show
The user view has
User: #{link_to user.name, user}
The view spec has
describe 'home/index.html.haml' do
it 'should render the users' do
#users = User.all
render
end
end
It does the right thing if I hit the app locally but if I run rspec on the view, I get
Failure/Error: render
ActionView::Template::Error:
undefined method `user_path' for #<#<Class:0x109f2a468>:0x109db5128>

Spork turned out to be the culprit. Restarted it and the specs now pass.

Related

Devise custom user root is not working

After a user signs in, I want them to be redirected to /users/2 or users/44, like a normal resource. (That way an admin can easily view any user's profile page just by knowing their id.)
I have no idea what is going on in my routes file. When a user logs in, I can see in the logs that it authenticates properly, and that my application_controller's after_sign_in_path_for is called.
But this is the error that I am getting when I try to redirect_to user_path(current_user).
No route matches {:action=>"show", :controller=>"users", :user_id=>11}
My config/routes.rb
devise_for :users, :path_names => {:sign_in => 'signin', :sign_out => 'signout', :sign_up => 'signup' }
devise_scope :user do
get "signin", :to => "devise/sessions#new"
get "signout", :to => "devise/sessions#destroy", via: :delete
get "signup", :to => "devise/registrations#new"
end
resources :users do
member do
get 'settings', to: 'users#edit'
end
end
My application_controller.rb
class ApplicationController < ActionController::Base
...
def after_sign_in_path_for(resource)
redirect_to user_path(:user_id=>current_user.id)
end
end
Shouldn't the resource :users block take care of creating a user show path? I do have a show method in my users_controller.rb. Please help, I've been trying to get this working for 2 days now.
My problem was that I was redirecting in the after_sign_in_path(resource) method instead of just returning the path:
def after_sign_in_path_for(resource)
return user_path(:user_id=>current_user.id)
end
is the correct way to do this.

Redirect to root_path after failed Devise user registration

I've read & attempted the solutions posted in numerous SO posts (i.e. here, here, and here) as well as Devise's answer on how to change the path after a failed registration, and Devise's RegistrationsController code, all to no avail.
Instead of doing the custom failure method in the /lib/ folder like most suggest, It seems like the easiest place to fix/override this would be in the RegistrationsController#create method at the bottom where it's:
else
clean_up_passwords resource
respond_with resource
end
It's (I assume) correctly responding with the user (i.e. redirecting them to root_path/users), but here's the tricky part: I create a nested model when my user registers, and that was quite difficult hacking into Devise for that. I'm afraid that if I go messing with the RegistrationsController#create method, that I'll break my perfectly-working nested models.
Someone also mentioned that the Devise solution didn't work for them, but then got it to work after changing a routing problem. I doubt that's the case with me, but here's my routes.rb file just in case:
devise_for :users, :controllers => { :registrations => "registrations" }
resources :users
resources :users do
resources :lockers
end
resources :lockers do
resources :products
end
resources :products
resources :lockups
match '/user/:id', :to => 'users#show', :as => :user
root :to => 'home#index'
I completely appreciate any help anyone can provide me. I'm still pretty new to Rails, but I'm always happy to learn.
EDIT: Thanks to Passionate, I've been trying to figure out how to change the logic in the final else block in the registrations controller. Here's what I've tried (along with my noob logic):
# Obviously cleared all the fields since it made no mention of resource
# redirect_to root_path
# Too many arguments since root_path takes 0
# redirect_to root_path resource
# Just bombed, something about a String somethingorother
# render root_path
# Heh, apparently call 'respond_with' and 'redirect_to' multiple times in one action
# respond_with resource
# redirect_to root_path
First you have to fix routes.rb file . Since you're using custom controller , you also have to customize devise_scope block . Change
get "signup", :to => "devise/registrations#new"
to
get "signup", :to => "registrations#new"
And, if you try to override the method and want to set the root_path after devise rails registration, you can do like
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def create
build_resource
// The `build_resource` will build the users .
if resource.save
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_navigational_format?
sign_up(resource_name, resource)
respond_with resource, :location => after_sign_up_path_for(resource)
else
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
expire_session_data_after_sign_in!
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords resource
## replace your logic here
redirect_to root_path
end
end
end
Please note that the above code works with devise 2.2.4 . Currently, the code which is on master branch on github is changed somewhat due to rails 4 and strong_parameter compatibility .

FactoryGirl,Rspec2 and devise rails 3

I am using Rspec, FactoryGirl and Spork for my tests.There are 2 things I am a litte unclear on, first is the location of my factories.rb file. At present I have it located in
spec/support/factories.rb
And it looks like this
FactoryGirl.define do
factory :user do
email "example#yahoo.com"
password "password"
password_confirmation "password"
confirmed_at Time.now
end
end
Within my spec_helper I have
config.include FactoryGirl::Syntax::Methods
Secondly I want to login a user before starting my tests for a controller , this particular controller has a before filter :authenticate_user!
I am using devise for my authentication so have added
config.include Devise::TestHelpers, :type => :controller
Reading the devise docs you can add a controller_macros.rb and specify methods like so to use
def login_user
before(:each) do
#request.env["devise.mapping"] = Devise.mappings[:user]
user = FactoryGirl.create(:user)
user.confirm! # or set a confirmed_at inside the factory. Only necessary if you are using the confirmable module
sign_in user
end
end
And so i added this also to my spec_helper
config.include ControllerMacros, :type => :controller
So when I add login_user before my controller tests i get undefined method login_user. Am i using two tools here to do the same thing? Do I actually need the devise methods or can it all be done with factoryGirl. If so how do i setup the login process before i can test a controller?
Factories location should be in spec/factories. Check out this example app https://github.com/RailsApps/rails3-devise-rspec-cucumber/tree/master/spec.
For login, generally you seems to doing it right. Check the example app again and here: https://github.com/plataformatec/devise/wiki/How-To:-Controllers-and-Views-tests-with-Rails-3-%28and-rspec%29
For the undefined method login_user error be sure to have
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
and
config.extend ControllerMacros, :type => :controller
in spec_helper. Devise methods should be available wtih subject:
subject.current_user.should_not be_nil

"Expected css... to return something" : rspec fail while test by hand works (can't reproduce the fail myself)

I'm working on a training app which is an Ogame-Like game (https://github.com/arnlen/ogame-like).
I'm using rspec (with Capybara) in order to test my app.
I'm stacked for several hours because rspec is complaining for an error which *I can't reproduce * by myself with my browser.
Here is my rspec code :
describe 'Planet pages' do
let(:user){FactoryGirl.create(:user)}
before {sign_in user}
subject {page}
describe "new planet page" do
before {visit new_planet_path}
describe "with valid information" do
before do
visit new_planet_path
fill_in "Name", with: "MyPlanet"
click_button "Validate"
end
# This test doesn't pass
it {should have_selector('h1', text: "Planet")}
end
end
end
The failure :
1) Planet pages new planet page with valid information
Failure/Error: it {should have_selector('h1', text: "Planet")}
expected css "h1" with text "Planet" to return something
# ./spec/requests/planet_pages_spec.rb:34:in `block (4 levels) in <top (required)>'
Here is the involved code.
My function "sign_in" used by rspec (location : spec/support/utilities.rb)
def sign_in(user)
visit signin_path
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"
end
My UsersController
class UsersController < ApplicationController
before_filter :signed_in_user, only: [:index, :show, :edit, :update, :destroy]
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
redirect_to new_planet_path
else
render 'new'
end
[...]
My PlanetsController
class PlanetsController < ApplicationController
before_filter :signed_in_user
def index
#planets = current_user.planets
end
def new
#planet = Planet.new
end
def create
#planet = Planet.new(name: params[:planet][:name],
coordinates: generate_coordinates,
metal_ressource: 1000,
user_id: current_user.id)
if #planet.save
flash[:success] = "Welcome on your first planet!"
redirect_to action: 'index'
else
flash[:error] = "Error naming your planet"
render 'new'
end
end
end
And My Planet Index view
<% #planets.each do |planet| %>
<h1>Planet : <%= planet.name %></h1>
<p><%= "Coordinates : #{planet.coordinates}" %></p>
<% end %>
I tried to user the Capybara method "save_and_open_page", but rspec raised an error "undefined method"
I also tried step by step debugging by iterations on my spec file, and it revealed that the error occurs right after the "click_button 'Validate'". For an unknown reason, rspec seems not to be able to reach the planets_path ("index" action from PlanetsController).
I'm out, if anybody has an idea, I take it !
EDIT : SOLVED - Found the problem!
Using the "save_and_open_page" method from Capybara, I figured out what was going on: the planet created by rspec didn't have any coordinates, which was not allowed by the model.
How to debug with the wonderful "save_and_open_page" method
Add this to your gemfile : "gem 'launchy'"
Install it : bundle install
Put the command "save_and_open_page" wherever you want
Hope it could help. :)
Capybara also has a save_page method, which is easier to use as it does not seem to need the "launchy" gem. The pages are saved in tmp/capybara. In the rspec tests, be sure to use save_page inside before, it, or some other block. It will not work as a separate command. Example:
before { visit signup_path; save_page }

Install recaptcha gem with exsisting devise gem with rubymine 3.1

What I've tried doing already: I've tried reading the documentation at github and getting it to work on Rubymine and I've managed to confuse myself with what is needed as far as controllers, and what is needed in the config folder. I've tried google and found some pretty good tutorials but their missing steps that I don't necessarily know to jump too.
What I'm trying to figure out: I want to be able use recaptcha in a login registration utlitizing the devise gem, I've already generated the pages for my devise login.
What I have so far:
I've installed and attached: devise 1.2.rc and recaptcha 0.3.1 I'm running Rubymine on windows xp. Ruby SDK 1.8.7-p302, with Rails 3.0.3
I've been to google and have my public and private keys
The next step tells me I'm supposed to add my keys to project/config/initializers/recaptcha.rb This is what is contained in that file:
Recaptcha.configure do |config|
config.public_key = 'myKey'
config.private_key = 'myKey'
end
Now I'm supposed to fix up my gemfile with:
gem 'recaptcha', :require => 'recaptcha/rails'
I also have my config/application.rb reading:
require 'rails/all'
require 'net/http'
I've also added to my External Libraries/[gem] devise/app/views/devise/registrations/new.html.erb the recaptcha tag:
<%= recaptcha_tags %>
<p><%= f.submit "Sign up" %></p>
Where I am running into issues (I think) is the
app/controllers/registrations_controller.rb and the config/routes.rb
I'm kinda of at a loss for what exactly goes into these files. Any help would be appreciated or a tutorial someone has written that walks me through this step by step would be very helpful. Thanks
Here's what I have done after Felix's post:
external libraries/app/controllers/devise/registrations_controller.rb
class Devise::RegistrationsController < Devise::RegistrationsController
def create
if verify_recaptcha then
super
else
build_resource
clean_up_passwords(resource)
flash[:notice] = 'Invalid Captcha'
render_with_scope :new
end
build_resource
if resource.save
if resource.active?
set_flash_message :notice, :signed_up
sign_in_and_redirect(resource_name, resource)
else
set_flash_message :notice, :inactive_signed_up, :reason => resource.inactive_message.to_s
expire_session_data_after_sign_in!
redirect_to after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords(resource)
render_with_scope :new
end
end
From Project/config/routes.rb:
devise_for :users, :controllers => {:registrations => 'registrations'}
This is the error that its spitting out:
ActionController::RoutingError (uninitialized constant RegistrationsController):
Rendered C:/Ruby/lib/ruby/gems/1.8/gems/actionpack-3.0.3/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (0.0ms) ..... any ideas?
For your routes, you can keep your normal devise routes except specifying your custom controller:
devise_for :users, :controllers => {:registrations => 'registrations'}
In the registrations_controller.rb, you want to subclass the Devise RegistrationsController and override the 'create' method:
class RegistrationsController < Devise::RegistrationsController
def create
if verify_recaptcha then
super
else
build_resource
clean_up_passwords(resource)
flash[:notice] = 'Invalid Captcha'
render_with_scope :new
end
end
end