Related
I'm trying to create many copies of a message to users:
users.each do |user|
new_message = message.clone
new_message.to = user
new_message.save!
end
However, this doesn't work after the 1st user. Here's part of the error message:
SQL (0.7ms) INSERT INTO "messages" ("content", "to_id") VALUES (?, ?) [["content", "abc"], ["to_id", 1]]
(2.5ms) commit transaction
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = 2 LIMIT 1
(0.0ms) begin transaction
SQL (0.5ms) INSERT INTO "messages" ("content", "id", "to_id") VALUES (?, ?, ?) [["content", "abc"], ["id", 6], ["to_id", 2]]
SQLite3::ConstraintException: PRIMARY KEY must be unique: INSERT INTO "messages" ("content", "id", "to_id") VALUES (?, ?, ?)
(0.0ms) rollback transaction
Completed 500 Internal Server Error in 130.1ms
ActiveRecord::StatementInvalid (SQLite3::ConstraintException: PRIMARY KEY must be unique: INSERT INTO "messages" ("content", "id", "to_id") VALUES (?, ?, ?)):
As you can see, the problem is that the 2nd time the loop runs, message.clone must contain the id of the previous new_message.
What is the proper way to clone message records for many users? I can, of course, manually copy each attribute (I have a lot more than just content and to_id) into a fresh new Message object. But I'd like to know if there's a better way.
You can use dup, with which the id, created_at and updated_at are set to nil. This will ensure that Primary Key exception is not thrown, however if there are other unique validations, they will fail. You'd have to handle them separately.
users.each do |user|
new_message = message.dup
new_message.to = user
new_message.save!
end
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
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.
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.
I'm trying to do the following in my Rails 3 model:
require 'securerandom'
class Contest < ActiveRecord::Base
attr_accessor :key
before_create :generate_key
private
def generate_key
self.key = SecureRandom.hex(3)
end
end
However when I create a Contest, all the fields in my table appear to be correct except the key which remains nil in my DB.
More Info:
In my rails server log, I see the following when I create a contest through my "create contest form"
SQL (0.5ms) INSERT INTO "contests" ("category", "created_at", "description", "key", "price", "status", "time", "title", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["category", "camisas"], ["created_at", Wed, 15 Feb 2012 18:57:16 UTC +00:00], ["description", "test_description"], ["key", nil], ["price", 111], ["status", "In process"], ["time", "2sem"], ["title", "test_contest"], ["updated_at", Wed, 15 Feb 2012 18:57:16 UTC +00:00], ["user_id", 5]]
Note the ["key", nil]
But that should be correct right?, I would guess that the key will be added by the Contest.rb :before_create callback?
Maybe I'm miss-using SecureRandom?
Why are you using attr_accessor? This method is actually going to be defining both a setter and getter method for a key, keeping track of a virtual attribute.
Perhaps you meant to use attr_accessible, but even then that is unnecessary, because you're setting the attribute directly.
Really, you don't need either attr_accessor :key or attr_accessible :key in your model at all if you're just setting it like this. Remove the attr_accessor and it will work.
I think you should write attr_accessible <list accessible params> for example:
attr_accessible :key, :category