Devise User can't be edited - ruby-on-rails

I have a Rails app using Devise for user authentication. I'm pretty sure the Devise edit user feature worked previously, but for some reason, edit/update doesn't work anymore. When I click "Update", the page just refreshes on the form. It also displays "Please review the problems below:" even though I've entered everything correctly.
The cancel account function works perfectly, however. Could the issue be the url path? If so, why does canceling the account work, while updating doesn't? I do have the user model nested within another model, but I've tried variations on the url path, none of which have worked.
Below is the form page generated by Devise and using simple_form:
.col-md-5.col-md-offset-2
%h2
Edit #{resource_name.to_s.humanize}
= simple_form_for(resource, as: resource_name, url: registration_path(resource_name) , html: { method: :put }) do |f|
= f.error_notification
.form-inputs
= f.input :email, required: true, autofocus: true
- if devise_mapping.confirmable? && resource.pending_reconfirmation?
%p
Currently waiting confirmation for: #{resource.unconfirmed_email}
= f.input :password, autocomplete: "off", hint: "leave it blank if you don't want to change it", required: false
= f.input :password_confirmation, required: false
= f.input :current_password, hint: "we need your current password to confirm your changes", required: true
.form-actions
= f.button :submit, "Update"
%h3 Cancel my account
%p
Unhappy? #{link_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete}
= link_to "Back", root_path
Update:
Here's the printout from development.log:
Started PUT "/users" for 127.0.0.1 at 2014-12-14 00:05:07 -0500
Processing by Users::RegistrationsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Zhtv8rbmwIDuZO7Tv/0db7tSIGfGUEW56fqPKzkgQSo=", "user"=>{"email"=>"test3#test3.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "current_password"=>"[FILTERED]"}, "commit"=>"Update"}
[1m[36mUser Load (0.3ms)[0m [1mSELECT `users`.* FROM `users` WHERE `users`.`id` = 16 ORDER BY `users`.`id` ASC LIMIT 1[0m
[1m[35mUser Load (0.2ms)[0m SELECT `users`.* FROM `users` WHERE `users`.`id` = 16 LIMIT 1
[1m[36m (0.2ms)[0m [1mBEGIN[0m
[1m[35m (0.1ms)[0m ROLLBACK
Rendered devise/registrations/edit.html.haml within layouts/application (4.3ms)
Rendered common/_login.html.haml (0.5ms)
Completed 200 OK in 328ms (Views: 175.1ms | ActiveRecord: 0.7ms)
Here's my routes.rb file. I do have Users listed twice.
devise_for :users
root 'welcome#index'
resources :wedding_checklists do
resources :users
resources :checklist_items
end

It seems to me an error has occurred but was not shown. Please add <%= devise_error_messages! %> to your form and let me know what errors are printed out.

Related

Rails, cant get update to work with cocoon when removing attribute "undefined method '[]' for nil:NilClass"?

I am wondering if someone could tell me why I am getting this error "undefined method '[]' for nil:NilClass". This happens when I remove a picture with cocoon and try update. The method works fine for adding pictures to the edited gallery but I am getting this error when removing and updating. I tried using unless #pictures.blank? end I am assuming the problem is when cocoon removes the picture but I am not sure what to do from there. the server error is,
Started PATCH "/galleries/41" for ::1 at 2017-05-07 16:03:02 +1000
Processing by GalleriesController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"cG1UXCvODhYzqqAr++EAn8GvMVk7+t/eASkzDDOoPmJfw3l6ax/F2xXMhvs7FcrJ3LOuTd0sks5+2fb86kQv0Q==", "gallery"=>{"name"=>"Hellooo", "cover"=>"123456", "pictures_attributes"=>{"0"=>{"_destroy"=>"1", "id"=>"47"}, "1"=>{"_destroy"=>"1", "id"=>"48"}}}, "commit"=>"Update Gallery", "id"=>"41"}
Gallery Load (0.0ms) SELECT "galleries".* FROM "galleries" WHERE "galleries"."id" = ? LIMIT ? [["id", 41], ["LIMIT", 1]]
Unpermitted parameter: pictures_attributes
(0.0ms) begin transaction
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
(0.0ms) commit transaction
Completed 500 Internal Server Error in 4ms (ActiveRecord: 0.0ms)
NoMethodError (undefined method `[]' for nil:NilClass):
...
Perhaps if someone could explain this to me would be great!
_form.html.erb
<%= form_for(#gallery, multipart: true) do |f| %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :cover %>
<%= f.text_field :cover %>
</div>
<div id="pictures">
<%= f.fields_for :pictures do |pic| %>
<%= render 'picture_fields', f: pic %>
</div>
<% end %>
<div class="links">
<%= link_to_add_association 'add picture', f, :pictures %>
<%= f.submit %>
</div>
<% end %>
_picture_fields.html.erb
<div class="nested-fields">
<div class="field">
<%= f.label :picture %>
<%= f.file_field :picture, multiple: true, name: "pictures[picture][]" %>
<%= link_to_remove_association "remove picture", f %>
</div>
</div>
GalleriesController
def update
#gallery = Gallery.find(params[:id])
if #gallery.update(gallery_params)
params[:pictures][:picture].each do |pic|
#pictures = #gallery.pictures.create!(picture: pic)
end
flash[:success] = "Gallery Updated!"
redirect_to root_url
else
render 'edit'
end
end
Edit: Added gallery_params
def gallery_params
params.require(:gallery).permit(:id, :name, :user_id, :cover, picture_attributes: [:id, :gallery_id, :picture, :_destroy])
end
EDIT: Added create action and server log using cocoon
def create
#user = User.first
#gallery = #user.galleries.build(gallery_params)
if #gallery.save
flash[:success] = "Picture created!"
redirect_to root_url
else
render 'new'
end
end
server log
Started POST "/galleries" for ::1 at 2017-05-10 13:18:43 +1000
Processing by GalleriesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"XU3z2jMdbselPJZ2SdZdGPwiAebiPznt8GWRqmbv8LM/MIxO+sNo1z2NTaDQ3nJNm0qaBJ66ny5254MPpHZaQQ==", "gallery"=>{"name"=>"Hello", "cover"=>"123456", "pictures_attributes"=>{"1494386318553"=>{"picture"=>#<ActionDispatch::Http::UploadedFile:0xac59228 #tempfile=#<Tempfile:C:/Users/Lee/AppData/Local/Temp/RackMultipart20170510-7596-16xlrir.jpg>, #original_filename="Skateboard 1.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"gallery[pictures_attributes][1494386318553][picture]\"; filename=\"Skateboard 1.jpg\"\r\nContent-Type: image/jpeg\r\n">, "_destroy"=>"false"}, "1494386321001"=>{"picture"=>#<ActionDispatch::Http::UploadedFile:0xac59150 #tempfile=#<Tempfile:C:/Users/Lee/AppData/Local/Temp/RackMultipart20170510-7596-jxo0st.jpg>, #original_filename="Skateboard 2.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"gallery[pictures_attributes][1494386321001][picture]\"; filename=\"Skateboard 2.jpg\"\r\nContent-Type: image/jpeg\r\n">, "_destroy"=>"false"}}}, "commit"=>"Create Gallery"}
User Load (0.0ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
(0.0ms) begin transaction
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
(0.0ms) rollback transaction
Rendering galleries/new.html.erb within layouts/application
Rendered galleries/_picture_fields.html.erb (1.0ms)
Rendered galleries/_picture_fields.html.erb (0.5ms)
Rendered galleries/_picture_fields.html.erb (0.5ms)
Rendered galleries/_form.html.erb (42.0ms)
Rendered galleries/new.html.erb within layouts/application (58.5ms)
Completed 200 OK in 157ms (Views: 139.3ms | ActiveRecord: 0.0ms)
Mmmm. Confused. There is no params[:pictures] so that is obviously nil (check the log you posted at the top). So that is causing the error. If you are looking for the pictures posted, you should refer to params[:pictures_attributes], but not even sure what you are trying to do there: create an empty picture (again?) for each posted pictures? The pictures are saved by doing the gallery.update(gallery_params).
Note: iterating over the posted params is imho definitely wrong, because if one is deleted, it will still be posted with the nested parameter _destroy set to true, so it can be deleted correctly from the database, or if a picture already existed, it will also be posted again (and not saved, since it already exists).
[EDIT] Add short solution:
use f.fields_for :pictures in your view: this will iterate over the existing pictures a gallery has, and will allow to delete/edit existing, and add new pictures to a gallery
fix your gallery_params and allow pictures_attributes (instead of the singular form)(otherwise nothing is saved)
in your controller just write #gallery.update_attributes(gallery_params) and do not iterate over params[:pictures] at all (remove that part) and it should just work (because the update_attributes will already have done this, at least if you want to iterate manually use pictures_attributes)
It looks like your gallery_params method is not permitting your pictures_attributes. You didn't post that code but I noticed in the error log Unpermitted parameter: pictures_attributes which means that your strong parameters(the gallery_params method) is filtering those parameters out.
Basically the whole point of the strong parameters is to make sure that you only pass through keys that you actually want to get passed through. So your controller is like "Nobody told me I am supposed to accecpt picture_attributes so I won't allow them through." Then your code is expecting there to be a picture object in the pictures array, but the pictures array doesn't have the picture object causing an error.
Can you post the code for gallery params? Can you also post the contents of params? Full disclosure: I don't really know rails 5 so there could be some other stuff going on.

Form_for work but doesn't save into table

I want to make a simple form_forbut that doesn't work fully.
I have two table:
Users -> has_many -> Cvs
this is my form :
<%= form_for(:cvs, action: "create", html: { method: :post }) do |f| %>
Nom : <%= f.text_field :nom %><br />
<%= f.submit %>
<% end %>
In my controller:
def create
#cv = Cv.new(cv_params)
#cv.save
end
With cv_params :
def cv_params
params.require(:cv).permit(:nom)
end
In my route.rb :
post 'createcv' => 'static_pages#createcv'
My controller is static_pages and my view is createcv
The field appear when I load the view, I put something but nothing is create in the table (there is no error). How can I correct that please?
EDIT:
The logs
Started GET "/createcv" for ::1 at 2015-06-16 17:22:03 +0200
Processing by StaticPagesController#createcv as HTML
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Cv Load (0.0ms) SELECT "cvs".* FROM "cvs" WHERE "cvs"."user_id" = ? [["user_id", 1]]
Rendered static_pages/createcv.html.erb within layouts/application (10.0ms)
Rendered layouts/_shim.html.erb (1.0ms)
Rendered layouts/_header.html.erb (2.0ms)
Rendered layouts/_footer.html.erb (1.0ms)
Completed 200 OK in 582ms (Views: 570.6ms | ActiveRecord: 0.0ms)
Started POST "/createcv" for ::1 at 2015-06-16 17:22:12 +0200
Processing by StaticPagesController#createcv as HTML
Parameters: {"utf8"=>"V", "authenticity_token"=>"28oSelskM87GZ/geLj6yl3tOrtvKktH/poBasO4pyt7I2QNKxw9HX4J+yS3cmisuzmGOGnr+6IxZdh+uQGDRDQ==", "cvs"=>{"nom"=>"hjsvqsv"}, "commit"=>"Save Cvs"}
User Load (1.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Cv Load (0.0ms) SELECT "cvs".* FROM "cvs" WHERE "cvs"."user_id" = ? [["user_id", 1]]
Rendered static_pages/createcv.html.erb within layouts/application (11.0ms)
Rendered layouts/_shim.html.erb (0.0ms)
Rendered layouts/_header.html.erb (1.0ms)
Rendered layouts/_footer.html.erb (0.0ms)
Completed 200 OK in 643ms (Views: 629.0ms | ActiveRecord: 1.0ms)
params.require(:cv).permit(:nom)
should be
params.require(:cvs).permit(:nom)
cause all params are nested inside :cvs not :cv
also, looking at your logs and route:
Processing by StaticPagesController#createcv
you need to rename your action to createcv.
Anyway, the routing in your app seems to be wrong... Unless you want it that way.
Ideally you should do something like this:
in static_pages controller, action createcv you'll initiate new CV object:
def createcv
...
#cv = Cv.new
end
and in createcv.html.erb the form would be like this:
<%= form_for #cv do |f| %>
Nom : <%= f.text_field :nom %><br />
<%= f.submit %>
<% end %>
rails will know that #cv in the form is a new object, and it will add the proper route to the form, that will point (depending on your app) to /cvs with post method.
That means when you submit the cv, action create from cv_controller should handle the rest of the process.
In this case you won't need the route you added, it should be there after you added
resources :cvs
This is just an example that might not fit your needs, cause I wouldn't know how did you named your models, controllers, etc..
The answer of Rajarshi Das is fine, only it seems to me that you want to open your form by visiting /createcv. so change your routes to:
# routes.rb
get '/createcv', to: 'static_pages#new'
post 'create', to: 'static_pages#create'
# static_pages controller
def new
#cv = Cv.new
end
def create
#cv = Cv.new(cv_params)
if #cv.save
flash[:alert] = 'Cv created!'
else
render 'new'
flash[:alert] = 'Error in form'
end
private
def cv_params
params.require(:cv).permit(:nom) # :cv must be singular
end
# static_pages/new.html.erb view
<%= form_for #cv do |f| %>
<p>
<%= f.label :nom %>
<%= f.text_field :nom %>
</p>
<%= f.submit %>
<% end %>

Bringing Form Values into a Controller - Ruby on Rails

I am trying to create a basic form where the user can change their password but needs to enter their old password in order to do it. I am having trouble verifying the user's old password. Everytime I enter an old password it says password doesn't match when I know that it does. If a replace the actual password in the authenticate field it works. How can I bring in what was entered in the form to verify the old password that was entered?
Form:
<%= form_for(#user, :url => change_password_action_path(current_user.id), html: { "role" => "form" }) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="form-group">
<%= f.label :old_password, "Old Password:", :class => "control-label" %>
<%= f.password_field :old_password, :class => "form-control" %>
</div>
<div class="form-group">
<%= f.label :password, "New Password:", :class => "control-label" %>
<%= f.password_field :password, :class => "form-control" %>
</div>
<div class="form-group">
<%= f.label :password_confirmation, "Password Confirmation:", :class => "control-label" %>
<%= f.password_field :password_confirmation, :class => "form-control" %>
</div>
<%= f.submit "Update Password", class: "btn btn-large btn-primary" %>
Controller
def change_password
#user = User.find(current_user.id)
end
def change_password_action
user = current_user.id
if User.find(user).authenticate(params[:old_password]) == false
flash[:danger] = "Password Doesnt Match: "
else
flash[:success] = "Password Match"
# Validate the new and confirm password.
end
redirect_to action: :change_password
end
Routes
get '/change_password' => 'main#change_password'
patch '/change_password_action' => 'main#change_password_action'
Rails Server Logs
Started PATCH "/change_password_action.1" for 127.0.0.1 at 2014-01-15 09:04:38 -0600
Processing by MainController#change_password_action as
Parameters: {"utf8"=>"✓", "authenticity_token"=>"yYdUx37Q7alr3SccuMVjPwCJoMgMPOaiKTesSsILlP4=", "user"=>{"old_password"=>"[FILTERED]", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Update Password"}
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'fc1baf63bac072bfefd5ed27664ece5427ad9e64' LIMIT 1
{"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"yYdUx37Q7alr3SccuMVjPwCJoMgMPOaiKTesSsILlP4=", "user"=>{"old_password"=>"test123", "password"=>"", "password_confirmation"=>""}, "commit"=>"Update Password", "controller"=>"main", "action"=>"change_password_action", "format"=>"1"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
Redirected to http://localhost:3000/change_password
Completed 302 Found in 115ms (ActiveRecord: 0.7ms)
Started GET "/change_password" for 127.0.0.1 at 2014-01-15 09:04:39 -0600
Processing by MainController#change_password as HTML
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'fc1baf63bac072bfefd5ed27664ece5427ad9e64' LIMIT 1
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
Rendered shared/_error_messages.html.erb (0.1ms)
Rendered main/change_password.html.erb within layouts/application (2.6ms)
Rendered layouts/_header.html.erb (0.5ms)
Rendered layouts/_footer.html.erb (0.0ms)
Completed 200 OK in 19ms (Views: 16.2ms | ActiveRecord: 0.4ms)
It looks like you're passing the wrong parameter into your authenticate method.
Try using params[:user][:old_password] instead of params[:old_password].
The param value you want will be under the :user key, because your form_for is using a user object.
You can also see this in your server logs where the user param in your params hash is:
"user"=>{"old_password"=>"[FILTERED]", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}

form_for filter query directing to create action

Afternoon All,
I'm trying to put a filter in my rails application but when I process the below it redirects to the create action on submit and I cannot figure out why it would pass to this action:
jobs_controller.rb
def index
#jobs = Job.all
#show_sub_nav = true
#lang = Job.find_by_sql("SELECT languages FROM jobs GROUP BY languages").map &:languages
#list = params[:languages].blank? ? Job.all : Job.find_all_by_category(params[:languages])
end
my view
<%= form_tag(jobs_path :method => 'get', :action => 'index') do %>
<%= select_tag "languages", options_for_select(#lang) %>
<%= submit_tag "Filter" %>
<% end %>
I was playing around the the form_for() with different options but it doesn't seem to make any difference and here is the log on click:
Started POST "/jobs?method=get" for 127.0.0.1 at 2013-12-16 19:35:54 +0000
Processing by JobsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"p34KrqtWpFr5xCAB+leP3YkVbJjLpDKix4BJDUZquAg=", "languages"=>"Ratke-Beatty", "commit"=>"Filter", "method"=>"get"}
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
(0.1ms) begin transaction
(0.1ms) rollback transaction
Rendered jobs/_subregion_select.html.erb (0.1ms)
Rendered jobs/_form.html.erb (38.7ms)
Rendered jobs/new.html.erb within layouts/application (39.9ms)
Rendered layouts/_navbar.html.erb (0.5ms)
Completed 200 OK in 75ms (Views: 54.2ms | ActiveRecord: 0.8ms)
It redirects because you're setting the http type to GET with this: :method => 'get'.
Generally, forms POST data so you either want :method => 'post', or if you're following the restful routes design, you don't need to specify the :method as rails is smart enough to know.
Solved it with the following:
<%= form_tag({ :action => "index"}, { :method => "get"}) do %>
Seems to work and gives me the right output.

Capybara filling in wrong fields

Weird problem.
I'm trying to test sign in, using Capybara and RSpec, but it seems that Capybara is filling in the wrong fields, so that the user getting signed in is not being authenticated.
I created the test user using FactoryGirl:
#factories.rb
FactoryGirl.define do
#...
factory :user do
name "guest"
password "pwordtest"
password_confirmation "pwordtest"
end
end
Then I wrote the following test (with a lot of "puts" stuff in it for debugging this problem):
#posts_spec.rb
describe "Valid post submission" do
it "should log in a user and let him make a post" do
User.destroy_all
visit '/access' #My Login page
user = FactoryGirl.create(:user)
puts "name"
puts user.name
fill_in :name, with: "guest" # I did these literally to make sure FactoryGirl wasn't the problem.
fill_in :password, with: "pwordtest"
click_on "Log In"
assert User.count == 1
puts "authing test"
current_path.should eq(new_post_path)
end
#...
end
In my sessions controller (more debuggery):
def create
user = User.find_by_name(params[:name])
puts "all"
puts params
puts "pre-inspect"
puts user.inspect
if user && user.authenticate(params[:password])
session[:user_id] = user.id
puts "In IF"
redirect_to new_post_path
else
flash.now[:error] = "Invalid password/username combo."
puts "there"
render 'new'
end
end
When I try to run the test, I get the following error:
name
guest
all
{"utf8"=>"✓", "name"=>"pword", "password"=>"", "commit"=>"Log In", "action"=>"create", "controller"=>"sessions"}
pre-inspect
nil
there
authing test
F
Failures:
1) Posts Valid post submission should log in a user and let him make a post
Failure/Error: current_path.should eq(new_post_path)
expected: "/posts/new"
got: "/sessions"
(compared using ==)
# ./spec/requests/posts_spec.rb:28:in `block (3 levels) in <top (required)>'
In other words, my debugging prompts suggest that the FactoryGirl user is fine, but somehow, Capybara is failing to assign those values to the right fields, so that params (after "all" in the debug prints) gets assigned "pword" as a name and "" as a password, instead of "guest" as name and "pword" as password. As a consequence, the test user isn't authenticated, and the session isn't started. This is particularly weird, cause the fields are definitely named correctly:
#sessions/new.html.erb
<div class="center_login">
<h1>Log In</h1>
<%= form_tag sessions_path do %>
<div class="field">
<%= label_tag :name %>
<%= text_field_tag :name, params[:name] %><br />
</div>
<div class="field">
<%= label_tag :password %>
<%= password_field_tag :password %><br />
</div><br>
<div class="actions"><%= submit_tag "Log In", class: "btn" %></div>
<% end %>
</div>
Any idea what's going on? Two other people and I messed around with this for an hour + and just can't figure it out.
EDIT -- It should be mentioned that when I navigate through the site as an actual person, this all works perfectly. As in, the username I put in the name field and the password I put in the password field correspond to those in the database, and I'm signed in just fine. Thus my suspicion that some Capybara failure to fill in the right thing is at fault here.
EDIT 2 -- Test.log output of one test below, per request:
Connecting to database specified by database.yml
[1m[36m (0.4ms)[0m [1mbegin transaction[0m
Started GET "/posts/new" for 127.0.0.1 at 2013-02-14 07:29:55 -0800
Processing by PostsController#new as HTML
Redirected to http://www.example.com/
Filter chain halted as :authorize rendered or redirected
Completed 302 Found in 1ms (ActiveRecord: 0.0ms)
Started GET "/" for 127.0.0.1 at 2013-02-14 07:29:55 -0800
Processing by StaticsController#resume as HTML
Rendered statics/_stars.html.erb (1.0ms)
Rendered statics/_stars.html.erb (0.4ms)
Rendered statics/_stars.html.erb (0.3ms)
Rendered statics/_stars.html.erb (0.3ms)
Rendered statics/_stars.html.erb (0.3ms)
Rendered statics/_stars.html.erb (0.3ms)
Rendered statics/_stars.html.erb (0.3ms)
Rendered statics/_stars.html.erb (0.3ms)
Rendered statics/_stars.html.erb (0.3ms)
Rendered statics/_stars.html.erb (0.3ms)
Rendered statics/_stars.html.erb (0.3ms)
Rendered statics/_skills.html.erb (14.9ms)
Rendered statics/_collapse_start.html.erb (0.6ms)
Rendered statics/_collapse_start.html.erb (0.1ms)
Rendered statics/_collapse_start.html.erb (0.1ms)
Rendered statics/_collapse_start.html.erb (0.1ms)
Rendered statics/_collapse_start.html.erb (0.1ms)
Rendered statics/resume.html.erb within layouts/application (68.4ms)
Rendered layouts/_shim.html.erb (0.2ms)
Rendered layouts/_header.html.erb (1.0ms)
Completed 200 OK in 163ms (Views: 162.3ms | ActiveRecord: 0.0ms)
[1m[35mUser Load (12.1ms)[0m SELECT "users".* FROM "users"
Started GET "/access" for 127.0.0.1 at 2013-02-14 07:29:55 -0800
Processing by SessionsController#new as HTML
Rendered sessions/new.html.erb within layouts/application (1.2ms)
Rendered layouts/_shim.html.erb (0.0ms)
Rendered layouts/_header.html.erb (0.5ms)
Completed 200 OK in 32ms (Views: 32.1ms | ActiveRecord: 0.0ms)
[1m[36m (0.1ms)[0m [1mSAVEPOINT active_record_1[0m
[1m[35mUser Exists (0.1ms)[0m SELECT 1 AS one FROM "users" WHERE LOWER("users"."name") = LOWER('guest') LIMIT 1
Binary data inserted for `string` type on column `password_digest`
[1m[36mSQL (30.0ms)[0m [1mINSERT INTO "users" ("created_at", "name", "password_digest", "updated_at") VALUES (?, ?, ?, ?)[0m [["created_at", Thu, 14 Feb 2013 15:29:55 UTC +00:00], ["name", "guest"], ["password_digest", "$2a$10$Y9NfnYjForrfufZOaqgQj.BdcHYLh.tkYomCVfHiJ4McbWMem445e"], ["updated_at", Thu, 14 Feb 2013 15:29:55 UTC +00:00]]
[1m[35m (0.1ms)[0m RELEASE SAVEPOINT active_record_1
Started POST "/sessions" for 127.0.0.1 at 2013-02-14 07:29:55 -0800
Processing by SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "name"=>"pword", "password"=>"[FILTERED]", "commit"=>"Log In"}
[1m[36mUser Load (0.1ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."name" = 'pword' LIMIT 1[0m
Rendered sessions/new.html.erb within layouts/application (0.7ms)
Rendered layouts/_shim.html.erb (0.0ms)
Rendered layouts/_header.html.erb (0.5ms)
Completed 200 OK in 21ms (Views: 2.7ms | ActiveRecord: 0.1ms)
[1m[35m (0.1ms)[0m SELECT COUNT(*) FROM "users"
[1m[36m (0.5ms)[0m [1mrollback transaction[0m
As you can see, the "parameters" passed to the sessions controller 6ish lines from the bottom include the name "pword" (and a filtered and possibly empty password), which is weird/frustrating.
EDIT 3 -- Using the most up-to-date version of Capybara, in my test group. And as of this new posting, I have run into an essentially identical problem in a spec for another controller. That is, I'll tell Capybara to fill in field 1 with "A", 2 with "B" and 3 with "C", and the params from that controller will show 1 filled with "B", 2 filled with "C" and 3 empty, as if Capybara is filling out each field prior to the one I tell it to or something.
EDIT 4 -- Following Dave S's suggestion, I took a screenshot of the sign in process (and also of the posting process, which, as stated in edit 2, has the same error).
Two different things are happening! In the login page, it looks like (because the password is blocked out), it's actually filling in the correct info (name == guest, and password == five stars, which is the same number of characters as password (and guest)), but if I save a page instead of a screenshot and click through, it goes to sessions and errors, just like the tester.
In my saved page/screenshot of the posting page, Capybara is definitely filling in the wrong fields. The name field is filled with what I said should be content, and the content field is empty. I think this is because I created new unique IDs for login but not for posting, and I'll see what happens if I do that for both. I'll also change the password to something differentiable from "guest" when blocked out, then report back.
EDIT 5 -- The new screenshots:
And the code of the two views, to give a sense of what might be different here. (I also changed the above factory code to make sense out of the (correct) password length in the screenshot.
# new posts _form.html.erb
<%= form_for(#post) do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name, id: "post_name" %>
</div>
<div class="field text-area">
<%= f.label :content %><br />
<%= f.text_area(:content, :size => '50x20', id: "post_content") %>
</div>
<div class="actions btn-group">
<%= f.submit 'Post It', class: "btn" %>
</div>
<% end %>
And login:
# login (new.html.erb in sessions)
<div class="center_login">
<h1>Log In</h1>
<%= form_tag sessions_path do %>
<div class="field">
<%= label_tag :name %>
<%= text_field_tag :name, params[:name], id: "sessions_name" %><br />
# The above name change seemed to possibly fix it. The weird thing, though, is that
# a similar change in the posts form above did NOT fix that problem.
</div>
<div class="field">
<%= label_tag :password %>
<%= password_field_tag :password %><br />
</div><br>
<div class="actions"><%= submit_tag "Log In", class: "btn" %></div>
<% end %>
</div>
Now (with name in login called seesions_name), login works 100%. The params are right, etc. But posting doesn't, because (despite my having made essentially the same change) Capybara is still filling in the wrong fields. Does any of this make the issue any clearer? I'm stumped.
EDIT 6 -- the full repo can be found here
I was just having a similar problem with testing my app's login functionality: it worked fine when I logged in manually, but login failed when testing it using Capybara.
You seem to be having some problems I didn't have, namely, Capybara filling in fields incorrectly. I'm not sure what that's due to, but you might be having more than one problem. After debugging, I found that my problem was due to a buggy user factory.
What I had was:
require 'digest/sha1'
FactoryGirl.define do
factory :user do
login 'hitchcock'
fname 'Alfred'
lname 'Hitchcock'
email 'alfred.hitchcock#example.com'
password Digest::SHA1.new << 'MacGuffin'
end
end
The field that sets the password was incorrect. This is the correct version:
password (Digest::SHA1.new << 'MacGuffin').to_s
The "password" field of the class User actually contains a password digest, not a password, but I'm working with a legacy database. In any case, I had calculated the digest of the password incorrectly, forgetting the to_s method, which caused my test cases' login attempts using username 'hitchcock' and password 'MacGuffin' to fail.
Now, looking at your factory, it seems to me you might have a similar problem. You migration file 20130206234907_create_users.rb looks like this:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.string :password_digest
t.timestamps
end
end
end
which shows you're storing the digest of the password, not the password itself, which is right and proper. However, your user factory, in file factories.rb, is:
factory :user do
name "guest"
password "pwordtest"
password_confirmation "pwordtest"
end
Your factory doesn't specify a password_digest field for the user it creates, so when in your posts_spec.rb you create a user by commanding
user = FactoryGirl.create(:user)
I'm wondering if a user is being created in the database at all, or if it is, what its password_digest field is going to be? Remember, when running tests, the contents of the test database are first cleared, so if your testing code doesn't create a valid user in the database, your login test won't work.
I had exactly this problem: Wrong fields being filled when using fill_in.
Solution was to follow the docs and use strings instead of symbols for the matchers:
I replaces this:
fill_in :email, with: email
fill_in :password, with: password
With:
fill_in "Email", with: email
fill_in "Password", with: password
And then it worked as expected
Docs: https://github.com/jnicklas/capybara#using-capybara-with-rspec

Resources