Rails two step signup with devise - Errors - ruby-on-rails

I am trying to set-up a two step signup process using Devise in Rails and followed this tutorial by Claudio Marai.
When I enter the e-mail address in the form (first step), I get an error telling me there was a routing error and that it couldn't find RegistrationsController
Started POST "/users" for 127.0.0.1 at 2012-05-03 22:50:59 -0400
ActionController::RoutingError (uninitialized constant RegistrationsController):
activesupport (3.2.1) lib/active_support/inflector/methods.rb:229:in `block in constantize'
activesupport (3.2.1) lib/active_support/inflector/methods.rb:228:in `each'
activesupport (3.2.1) lib/active_support/inflector/methods.rb:228:in `constantize'
.
.
.
I figured this was due to the presence of :registrations => "registrations" in my routes.rb file as described in the first step of the tutorial. I then tried two alternatives which both resulted in the same error. First, I removed the :registrations => "registrations" from the routes.rb file. When that didn't work, I re-inserted the line and added a registrations_controller.rb to the controllers directory which looked like this:
class RegistrationsController < Devise::RegistrationsController
end
I figured the two options would have the same effect - but - I tried them anyway.
The error I got was the following:
Started POST "/users" for 127.0.0.1 at 2012-05-03 22:47:29 -0400
Processing by Devise::RegistrationsController#create as HTML
Parameters: {"utf8"=>"?", "authenticity_token"=>"ttPBRPRLVzPBHcDDKRJbimv0Yp/egdK5qBkIvBTL4Ig=", "user"=>{"email"=>"test#email.com"}, "x"=>"0", "y"=>"0"}
(0.6ms) begin transaction
User Exists (1.5ms) SELECT 1 FROM "users" WHERE "users"."email" = 'test#email.com' LIMIT 1
CACHE (0.0ms) SELECT 1 FROM "users" WHERE "users"."email" = 'test#email.com' LIMIT 1
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."confirmation_token" = '8tA1jakpAXNK4Piz7J6R' LIMIT 1
SQL (14.0ms) INSERT INTO "users" ("confirmation_sent_at", "confirmation_token", "confirmed_at", "created_at", "current_sign_in_at", "current_sign_in_ip", "email", "encrypted_password", "fb_id", "fb_token", "first_name", "last_name", "last_sign_in_at", "last_sign_in_ip", "remember_created_at", "reset_password_sent_at", "reset_password_token", "sign_in_count", "state", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["confirmation_sent_at", Thu, 03 May 2012 22:47:30 EDT -04:00], ["confirmation_token", "8tA1jakpAXNK4Piz7J6R"], ["confirmed_at", nil], ["created_at", Thu, 03 May 2012 22:47:30 EDT -04:00], ["current_sign_in_at", nil], ["current_sign_in_ip", nil], ["email", "test#email.com"], ["encrypted_password", nil], ["fb_id", nil], ["fb_token", nil], ["first_name", nil], ["last_name", nil], ["last_sign_in_at", nil], ["last_sign_in_ip", nil], ["remember_created_at", nil], ["reset_password_sent_at", nil], ["reset_password_token", nil], ["sign_in_count", 0], ["state", nil], ["updated_at", Thu, 03 May 2012 22:47:30 EDT -04:00]]
SQLite3::ConstraintException: constraint failed: INSERT INTO "users" ("confirmation_sent_at", "confirmation_token", "confirmed_at", "created_at", "current_sign_in_at", "current_sign_in_ip", "email", "encrypted_password", "fb_id", "fb_token", "first_name", "last_name", "last_sign_in_at", "last_sign_in_ip", "remember_created_at", "reset_password_sent_at", "reset_password_token", "sign_in_count", "state", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
(0.3ms) rollback transaction
Completed 500 Internal Server Error in 441ms
ActiveRecord::StatementInvalid (SQLite3::ConstraintException: constraint failed: INSERT INTO "users" ("confirmation_sent_at", "confirmation_token", "confirmed_at", "created_at", "current_sign_in_at", "current_sign_in_ip", "email", "encrypted_password", "fb_id", "fb_token", "first_name", "last_name", "last_sign_in_at", "last_sign_in_ip", "remember_created_at", "reset_password_sent_at", "reset_password_token", "sign_in_count", "state", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)):
sqlite3 (1.3.5) lib/sqlite3/statement.rb:108:in `step'
sqlite3 (1.3.5) lib/sqlite3/statement.rb:108:in `block in each'
sqlite3 (1.3.5) lib/sqlite3/statement.rb:107:in `loop'
sqlite3 (1.3.5) lib/sqlite3/statement.rb:107:in `each'
.
.
.
The above error has me really confused!
With the same form, when I add the password and password_confirmation fields, then things proceed smoothly - the user account is created and a confirmation email is sent to the user with the confirmation link.
I would appreciate any help regarding this - thanks! I am using Ruby 1.9.3-p125 and Rails 3.2.1

The issue isn't due to Rails validation, it's due to a violation of a database constraint.
More than likely, if your users table migration was generated by Devise, then the schema includes this:
"encrypted_password" varchar(128) DEFAULT '' NOT NULL
The SQL that's causing the ConstraintException includes this (elided for readability):
SQL (14.0ms) INSERT INTO "users" (..., "encrypted_password", ...) VALUES (..., ?, ...) [..., ["encrypted_password", nil], ...]
So, something is telling your database adapter to set encrypted_password = nil.
You should be able to circumvent it either be running a migration that removes the NOT NULL constraint on the encrypted_password, or do as you've done, pass in an encrypted_password, but just make sure it's empty in the first step, but present in the second step.

Related

accept_nested_attributes_for creates one extra nil record on Rails

I am using Rails as a backend and React as my front-end. On the React side, I am using fetch to do POST request to my model named schedule. I am also adding a child attributes for worker model.
Here are some code snippets that I have. I am using has_many :through relationship in rails.
My Rails models and controller:
//schedule.rb
has_many :workers, through: :rosters, dependent: :destroy
has_many :rosters, inverse_of: :schedule
//worker.rb
has_many :schedules, through: :rosters
has_many :rosters, inverse_of: :worker
//roster.rb
belongs_to :schedule
belongs_to :worker
//schedules_controller.rb
def create
#schedule = Schedule.new(schedule_params)
#workers = #schedule.rosters.build.build_worker
if #schedule.save
render json: #schedule
else
render json: #schedule, status: :unprocessable_entity
end
end
...
def schedule_params
params.permit(:date, :user_id, :workers_attributes => [:id, :name, :phone])
end
On React side:
//inside Client.js
function postSchedule(date, cb) {
return fetch(`api/schedules`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
date: date,
user_id: 1,
workers_attributes: [{name: "Iggy Test", phone: "123-456-7890"}, {name: "Iggy Test 2", phone: "987-654-3210"}]
})
}).then((response) => response.json())
.then(cb);
};
//inside main app:
postSchedule(){
Client.postSchedule(this.state.date, (schedule) => {
this.setState({schedules: this.state.schedules.concat([schedule])})
})
};
The problem that I have is, when I submit a new schedule, I expect to see a new schedule with two workers: "Iggy Test" and "Iggy Test 2". However, when I looked inside Rails, it is creating 3 workers: "Iggy Test", "Iggy Test 2", and nil.
Here is what is happening when I submit the request:
Started POST "/api/schedules" for 127.0.0.1 at 2017-05-24 09:55:16 -0700
Processing by SchedulesController#create as */*
Parameters: {"date"=>"2017-05-27T02:00:00.000Z", "user_id"=>1, "workers_attributes"=>[{"name"=>"Iggy Test", "phone"=>"
123-456-7890"}, {"name"=>"Iggy Test 2", "phone"=>"987-654-3210"}], "schedule"=>{"date"=>"2017-05-27T02:00:00.000Z", "use
r_id"=>1}}
Unpermitted parameter: schedule
(0.1ms) begin transaction
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
SQL (0.4ms) INSERT INTO "schedules" ("date", "created_at", "updated_at", "user_id") VALUES (?, ?, ?, ?) [["date", 20
17-05-27 02:00:00 UTC], ["created_at", 2017-05-24 16:55:16 UTC], ["updated_at", 2017-05-24 16:55:16 UTC], ["user_id", 1]
]
SQL (0.2ms) INSERT INTO "workers" ("name", "phone", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "Iggy
Test"], ["phone", "123-456-7890"], ["created_at", 2017-05-24 16:55:16 UTC], ["updated_at", 2017-05-24 16:55:16 UTC]]
SQL (0.2ms) INSERT INTO "rosters" ("worker_id", "created_at", "updated_at") VALUES (?, ?, ?) [["worker_id", 64], ["c
reated_at", 2017-05-24 16:55:16 UTC], ["updated_at", 2017-05-24 16:55:16 UTC]]
SQL (0.1ms) INSERT INTO "workers" ("name", "phone", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "Iggy
Test 2"], ["phone", "987-654-3210"], ["created_at", 2017-05-24 16:55:16 UTC], ["updated_at", 2017-05-24 16:55:16 UTC]]
SQL (0.1ms) INSERT INTO "rosters" ("worker_id", "created_at", "updated_at") VALUES (?, ?, ?) [["worker_id", 65], ["c
reated_at", 2017-05-24 16:55:16 UTC], ["updated_at", 2017-05-24 16:55:16 UTC]]
SQL (0.2ms) INSERT INTO "workers" ("created_at", "updated_at") VALUES (?, ?) [["created_at", 2017-05-24 16:55:16 UTC
], ["updated_at", 2017-05-24 16:55:16 UTC]]
SQL (0.2ms) INSERT INTO "rosters" ("schedule_id", "worker_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["sc
hedule_id", 57], ["worker_id", 66], ["created_at", 2017-05-24 16:55:16 UTC], ["updated_at", 2017-05-24 16:55:16 UTC]]
SQL (0.7ms) UPDATE "rosters" SET "schedule_id" = ?, "updated_at" = ? WHERE "rosters"."id" = ? [["schedule_id", 57],
["updated_at", 2017-05-24 16:55:16 UTC], ["id", 60]]
SQL (0.1ms) UPDATE "rosters" SET "schedule_id" = ?, "updated_at" = ? WHERE "rosters"."id" = ? [["schedule_id", 57],
["updated_at", 2017-05-24 16:55:16 UTC], ["id", 61]]
(2.6ms) commit transaction
Completed 200 OK in 68ms (Views: 0.8ms | ActiveRecord: 5.6ms)
The log created a schedule, then a worker (Iggy Test), then a roster (for that schedule and Iggy Test), then another worker (Iggy Test 2), then another roster (for Iggy Test 2 and that schedule) - instead of stopping, it created another worker (nil) and a roster for that nil worker.
Why is it behaving such? How can I fix it to create only the specified workers?
As a side note - if you noticed, the log says unpermitted parameter: schedule. That message disappears when I add require(:schedule) inside my schedule_params, but it would instead create only one nil worker.
accepts_nested_attributes_for is not creating an extra record. You are.
def create
#schedule = Schedule.new(schedule_params)
# This adds a worker with no attributes
#workers = #schedule.rosters.build.build_worker
if #schedule.save
render json: #schedule
else
render json: #schedule, status: :unprocessable_entity
end
end
"Unpermitted parameter: schedule" is just a warning that there was a param is in the params hash that was not whitelisted by .permit. It is logged since it could be a malicious attempt to fish for mass assignment vulnerabilities.
.require takes a single key from the params hash and raises an error if it not present and is not what you want when you have a flat params hash.
Instead you should look into why the params sent by react include both the unwrapped params and I don't get why you are sending both the unwrapped params and a "schedule"=>{"date"=>"2017-05-27T02:00:00.000Z", "user_id"=>1} hash. I don't really know React but I'm guessing it has something to do with this.state.schedules.concat([schedule])

Moved Rails app, now getting db error, possibly devise?

I recently moved my Rails app from one folder to another. It runs perfectly in the original folder. I copied everything.
I think this may be devise related, since I use it for user management, and I have the db as full read/write/execute. Any suggestions are greatly appreciated, I'm new to rails.
Without any modification, I'm now getting this error when running:
ActiveRecord::StatementInvalid in Devise::RegistrationsController#create
SQLite3::ReadOnlyException: attempt to write a readonly database: INSERT INTO "users" ("created_at", "current_sign_in_at", "current_sign_in_ip", "email", "encrypted_password", "first_name", "last_name", "last_sign_in_at", "last_sign_in_ip", "profile_name", "remember_created_at", "reset_password_sent_at", "reset_password_token", "sign_in_count", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Rails.root: /home/rails
My guess is you copied the file from a directory owned by another user. Here it complains about the user rails not being able to open the database.sqlite3.
Executing sudo chown -R rails db/ should give the rails user the access to the database.
You are the rails user right? According to /home/rails

Devise: Tries to create a record without ID

I'm new to Rails and I'm trying to create an app using devise for the authentication part. The first thing I noticed was that my tests were failing because my users fixtures hadn't an ID, so I put this on my User model
self.primary_key = :id
This helped my tests to run, but now I'm stuck on another problem. Everytime I try to add a user, the Devise controller fails with the following message:
ActiveRecord::StatementInvalid in Devise::RegistrationsController#create
SQLite3::ConstraintException: users.id may not be NULL: INSERT INTO "users" ("active", "created_at", "current_sign_in_at", "current_sign_in_ip", "default_business_id", "email", "encrypted_password", "first_name", "last_name", "last_sign_in_at", "last_sign_in_ip", "remember_created_at", "reset_password_sent_at", "reset_password_token", "sign_in_count", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Why isn't the User ID being created automatically? I'm running Devise 2 with Rails 3.2
Well, I finally found what the problem was. The users table id column was not defined as a primary key in the DB, so that was the reason why Rails wasn't assigning a value to it automatically. I don't know how it happened, since I didn't touch the migration that creates this table (this file is generated by Devise). Anyway, making a complete rollback and executing the migrations again fixed the problem. Thanks all who replied and hope this serves anyone in the future.

Rails is allowing double post request to lock database?

I'm using Valums Ajax Uploader to create a nice user interface for uploading photos in my rails app. One problem, it sometimes submits Post requests too close together, and then they cause a database locking exception which makes all the uploads fail for a while.
Here's an example of the log:
Started POST "/photos?authenticity_token=WPJo8nnJ3KSoG9O%2B%2Flz%2BPbvdtX8cmbEaVB8TidnLx5Y%3D&qqfile=IMG_0417.JPG" for 127.0.0.1 at 2012-03-06 22:39:25 -0600
Processing by PhotosController#create as HTML
Parameters: {"file"=>#<ActionDispatch::Http::UploadedFile:0x007f9e5529f518 #original_filename="IMG_0417.JPG", #content_type="application/octet-stream", #headers=nil, #tempfile=#<File:/var/folders/mf/06zfbjcn63j6p2rqvt6tc77c0000gn/T/raw-upload.20120306-53350-13pew0o>>, "authenticity_token"=>"WPJo8nnJ3KSoG9O+/lz+PbvdtX8cmbEaVB8TidnLx5Y=", "qqfile"=>"IMG_0417.JPG"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Started POST "/photos?authenticity_token=WPJo8nnJ3KSoG9O%2B%2Flz%2BPbvdtX8cmbEaVB8TidnLx5Y%3D&qqfile=IMG_0418.JPG" for 127.0.0.1 at 2012-03-06 22:39:30 -0600
Processing by PhotosController#create as HTML
Parameters: {"file"=>#<ActionDispatch::Http::UploadedFile:0x007fcfddd8d268 #original_filename="IMG_0418.JPG", #content_type="application/octet-stream", #headers=nil, #tempfile=#<File:/var/folders/mf/06zfbjcn63j6p2rqvt6tc77c0000gn/T/raw-upload.20120306-53383-1plhm8r>>, "authenticity_token"=>"WPJo8nnJ3KSoG9O+/lz+PbvdtX8cmbEaVB8TidnLx5Y=", "qqfile"=>"IMG_0418.JPG"}
"authenticity_token"=>"WPJo8nnJ3KSoG9O+/lz+PbvdtX8cmbEaVB8TidnLx5Y=", "qqfile"=>"IMG_0418.JPG"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
(0.1ms) begin transaction
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
SQL (0.6ms) INSERT INTO "photos" ("city", "comments_updated_at", "context_id", "country", "created_at", "custom_title", "description", "featured", "flagged", "focus_id", "full_downloads", "height", "image", "lat", "lng", "place", "presentation_downloads", "state", "status", "updated_at", "user_id", "width") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["city", nil], ["comments_updated_at", nil], ["context_id", nil], ["country", nil], ["created_at", Tue, 06 Mar 2012 22:39:37 CST -06:00], ["custom_title", nil], ["description", nil], ["featured", false], ["flagged", nil], ["focus_id", nil], ["full_downloads", 0], ["height", 2304], ["image", "admin_tester_630cm1715.JPG"], ["lat", nil], ["lng", nil], ["place", nil], ["presentation_downloads", 0], ["state", nil], ["status", "batch"], ["updated_at", Tue, 06 Mar 2012 22:39:37 CST -06:00], ["user_id", 1], ["width", 3072]]
SQL (0.2ms) UPDATE "users" SET "photos_count" = COALESCE("photos_count", 0) + 1 WHERE "users"."id" = 1
(0.1ms) begin transaction
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
SQL (5064.0ms) INSERT INTO "photos" ("city", "comments_updated_at", "context_id", "country", "created_at", "custom_title", "description", "featured", "flagged", "focus_id", "full_downloads", "height", "image", "lat", "lng", "place", "presentation_downloads", "state", "status", "updated_at", "user_id", "width") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["city", nil], ["comments_updated_at", nil], ["context_id", nil], ["country", nil], ["created_at", Tue, 06 Mar 2012 22:39:43 CST -06:00], ["custom_title", nil], ["description", nil], ["featured", false], ["flagged", nil], ["focus_id", nil], ["full_downloads", 0], ["height", 2304], ["image", "admin_tester_630cm171b.JPG"], ["lat", nil], ["lng", nil], ["place", nil], ["presentation_downloads", 0], ["state", nil], ["status", "batch"], ["updated_at", Tue, 06 Mar 2012 22:39:43 CST -06:00], ["user_id", 1], ["width", 3072]]
SQLite3::BusyException: database is locked: INSERT INTO "photos" ("city", "comments_updated_at", "context_id", "country", "created_at", "custom_title", "description", "featured", "flagged", "focus_id", "full_downloads", "height", "image", "lat", "lng", "place", "presentation_downloads", "state", "status", "updated_at", "user_id", "width") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
(0.3ms) rollback transaction
SQLite3::BusyException: cannot rollback transaction - SQL statements in progress: rollback transaction
Completed 500 Internal Server Error in 17749ms
ActiveRecord::StatementInvalid (SQLite3::BusyException: cannot rollback transaction - SQL statements in progress: rollback transaction):
app/controllers/photos_controller.rb:29:in `create'
app/uploaders/flash_session_cookie_middleware.rb:16:in `call'
Obviously this isn't good, if this happens with just one user uploading a few images it isn't up to production standards. So, how do you fix this? What is the right way to handle uploading and processing a file like this so that concurrency isn't a big problem?
You might want to migrate from SQLite if you're having multiple processes accessing the same database. While this is supported by SQLite, it does require a lock on the entire database to avoid corrupting data during commits. This is explained in rough terms in the SQLite FAQ.
While SQLite is great for small-scale databases and development work, it is probably not the best idea for a production grade application that sees a lot of write activity.
The good news is that converting from SQLite to MySQL or Postgres is usually very simple.
You could be hitting some kind of deadlock condition due to the way SQLite handles locking. It's also odd that your uploads would be taking such an extended period of time to process.

rails 3 accepts_nested_attributes_for not working when save

I have declared the accepts_nested_attributes_for and everything works fine but only when I save the model into the database, the nested model is not saved along the master model, anyone know why?
In my log/development.log file:
Started POST "/users/1/business_infos" for 127.0.0.1 at 2011-10-22 23:08:59 -0500
Processing by BusinessInfosController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Vw9GWH4cnr8z+PPged0mal/CVsbdBM1NcDehRb7zl7Q=", "business_info"=>{"business_name"=>"microsoft", "locations_attributes"=>{"0"=>{"address"=>"New York, NY"}, "1"=>{"address"=>""}, "2"=>{"address"=>""}}, "business_hours"=>"5am-7pm, Mon - Fri", "business_logo"=>#<ActionDispatch::Http::UploadedFile:0xa219684 #original_filename="rails.png", #content_type="image/png", #headers="Content-Disposition: form-data; name=\"business_info[business_logo]\"; filename=\"rails.png\"\r\nContent-Type: image/png\r\n", #tempfile=#<File:/tmp/RackMultipart20111022-28086-fbv7x6>>, "business_phone"=>"6666666666", "business_web_addr"=>"www.microsoft.com"}, "commit"=>"Create", "user_id"=>"1"}
[1m[36mUser Load (0.3ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1[0m [["id", "1"]]
[1m[35mSQL (4.9ms)[0m INSERT INTO "business_infos" ("business_addr", "business_hours", "business_logo", "business_name", "business_phone", "business_web_addr", "confirmed", "created_at", "multi_location", "qr_code", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["business_addr", nil], ["business_hours", "5am-7pm, Mon - Fri"], ["business_logo", "/assets/business_logo/microsoft.png"], ["business_name", "microsoft"], ["business_phone", "6666666666"], ["business_web_addr", "www.microsoft.com"], ["confirmed", nil], ["created_at", Sun, 23 Oct 2011 04:08:59 UTC +00:00], ["multi_location", nil], ["qr_code", nil], ["updated_at", Sun, 23 Oct 2011 04:08:59 UTC +00:00], ["user_id", 1]]
[1m[36mBusinessInfo Load (0.2ms)[0m [1mSELECT "business_infos".* FROM "business_infos" WHERE "business_infos"."user_id" = 1 LIMIT 1[0m
[1m[35m (1.0ms)[0m UPDATE "business_infos" SET "qr_code" = '/assets/qr_code/microsoft.png', "updated_at" = '2011-10-23 04:09:00.314348' WHERE "business_infos"."id" = 8
Redirected to http://localhost:3000/users/1
Completed 302 Found in 613ms
if you see Parameters in the log, there contains a location_attributes(location model), which is the nested attributes for business_info model, but if you see the INSERT INTO "business_infos" query, there are no insertion to the location table!
I have posted a more detailed question at this link Rails mode accepts_nested_attributes_for working properly Any clue?

Resources