FactoryGirl Rspec and SQLite3::ConstraintException - ruby-on-rails-3

I'm trying to create a few associated factories, but the Event is NOT working:
factories.rb
factory :user, class: User do
first_name 'John'
last_name 'Doe'
email { "#{first_name}.#{last_name}#example.com".downcase }
username 'johndoe'
password 'johndoe'
password_confirmation 'johndoe'
association :account_id, factory: :account
end
factory :account, class: Account do
#id is the only field
end
factory :event, class: Event do
name 'Go to the Dentist'
start_date "#{Time.now.next_month}"
end_date "#{Time.now+1.hour.next_month}"
copyright "#{Time.now.year}"
association :account_id, factory: :account
end
controller_spec.rb
before(:each) do
#request.env["devise.mapping"] = Devise.mappings[:user]
#user = FactoryGirl.create(:user_profile, :username => 'johndoe' )
sign_in #user
#acct = FactoryGirl.create(:account, :id => #user.account_id)
#event = FactoryGirl.create(:event, :account_id => #acct.id)
end
but this event line is where it all goes awry. Even if I use #user.account_id to set :account_id for event, it fails with this error:
Failure/Error: #event = FactoryGirl.create(:event, :account_id => #acct.id)
ActiveRecord::StatementInvalid:
SQLite3::ConstraintException: constraint failed: INSERT INTO "event" ("account_id", "copyright", "created_at", "deleted", "end_date", "info", "name", "start_date", "type", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
# ./spec/controllers/controller_spec.rb:13:in `block (3 levels) in <top (required)>'
Thank you very much for any advice you can offer on this!

I think the reason you are getting the constraint exception is that you have already have some data in your tables that conflicts the information you are trying to add.
You probably want to delete all data and then try the rspec test case.

Related

ActiveRecord::RecordNotUnique: SQLite3::ConstraintException: UNIQUE constraint failed: rooms.number

Could someone please help me figure this one out? It's my first week working with Rails and all my tests pass but the one below. I understand it's due to the unique constraint but I don't know what else exactly I need to do.
Error:
RoomsControllerTest#test_should_create_room:
ActiveRecord::RecordNotUnique: SQLite3::ConstraintException: UNIQUE constraint failed: rooms.number: INSERT INTO "rooms" ("number", "capacity", "created_at", "updated_at") VALUES (?, ?, ?, ?)
app/controllers/rooms_controller.rb:31:in `block in create'
app/controllers/rooms_controller.rb:30:in `create'
test/controllers/rooms_controller_test.rb:20:in `block (2 levels) in <class:RoomsControllerTest>'
test/controllers/rooms_controller_test.rb:19:in `block in <class:RoomsControllerTest>'
This is the create method in the rooms_controller:
def create
#room = Room.new(room_params)
respond_to do |format|
if #room.save
format.html { redirect_to rooms_path, notice: 'Room was successfully created.' }
format.json { render :show, status: :created, location: #room }
else
format.html { render :new }
format.json { render json: #room.errors, status: :unprocessable_entity }
end
end
end
This is the test itself:
test "should create room" do
assert_difference('Room.count') do
post rooms_url, params: { room: { capacity: #room.capacity, number: #room.number } }
end
assert_redirected_to rooms_url
end
Schema - unique:true so the same number won't get added twice:
create_table "rooms", force: :cascade do |t|
t.integer "number"
t.integer "capacity"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["number"], name: "index_rooms_on_number", unique: true
end
I reset my test db with the following commands:
bundle exec rake db:drop RAILS_ENV=test
bundle exec rake db:create RAILS_ENV=test
Thank you so much in advance!
So for some reason you already have a room with that number. My best guess is that the #room ivar used in your test is already persisted to the database. To make the test pass, you should probably avoid relying on #room or discard it entirely if you can, and pass a number of your choice instead.

ActiveRecord::StatementInvalid (SQLite3::BusyException: database is locked

I know this a duplicate question but i tried all other solutions did not work for me.
when I create new message it does not insert it in on first click and on the second click it insert the same message twice, if I look at the terminal after the first click i get
ActiveRecord::StatementInvalid (SQLite3::BusyException: database is locked: INSERT INTO "notifications" ("content", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)):
ActiveRecord::StatementInvalid (SQLite3::BusyException: database is locked: commit transaction):
solutions I tried are
ActiveRecord::Base.connection.execute("BEGIN TRANSACTION; END;")
I got unknown file attribute: B.
bundle exec rake db:reset
it cleared all my data but I still got the same results.
default: &default
adapter: sqlite3
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 10000
I tried to increase timeout but it did not work for me.
app/controllers/messages_controller.rb
class MessagesController < ApplicationController
before_action :authenticate_user!
before_action :set_conversation
def index
if current_user == #conversation.sender || current_user == #conversation.recipient
#other = current_user == #conversation.sender ? #conversation.recipient : #conversation.sender
#messages = #conversation.messages.order("created_at DESC")
else
redirect_to conversations_path, alert: "You don't have permission to view this."
end
end
def create
#message = #conversation.messages.new(message_params)
#messages = #conversation.messages.order("created_at DESC")
if #message.save
ActionCable.server.broadcast "conversation_#{#conversation.id}", message: render_message(#message)
redirect_to conversation_messages_path(#conversation)
end
end
private
def render_message(message)
self.render(partial: 'messages/message', locals: {message: message})
end
def set_conversation
#conversation = Conversation.find(params[:conversation_id])
end
def message_params
params.require(:message).permit(:context, :user_id)
end
end
This is an image from the terminal

Inverse record of a belongs_to record from a registration form not saving attributes

I have a registration form that asks for four things: the user's email, the user's name, their company's name, and a password.
The user model contains the email, name, and password fields
class User < ApplicationRecord
belongs_to :account
attr_accessor :account_attributes
accepts_nested_attributes_for :account
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
The account model contains the company's name.
class Account < ApplicationRecord
has_many :users,
:dependent => :destroy
attr_accessor :name
validates :name, presence: true
end
My registration form looks like (using slim templates):
h2
| Sign up
= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
= devise_error_messages!
.field
= f.label :email
br
= f.email_field :email, autofocus: true
.field
= f.label :name, "Your name"
br
= f.text_field :name
= f.fields_for :account_attributes do |a|
.field
= a.label :name, "Your company or organization"
br
= a.text_field :name
.field
= f.label :password
- if #minimum_password_length
em
| (
= #minimum_password_length
| characters minimum)
br
= f.password_field :password, autocomplete: "off"
.field
= f.label :password_confirmation
br
= f.password_field :password_confirmation, autocomplete: "off"
.actions
= f.submit "Sign up"
= render "devise/shared/links"
And lastly, my custom registration controller is:
class RegistrationsController < Devise::RegistrationsController
def new
super
resource.build_account
end
def create
super
resource.account ||= Account.new
resource.account.name = sign_up_params[:account_attributes]["name"]
resource.account.save
end
private
def sign_up_params
params.require(:user).permit(:first_name, :name, :email, :password, :password_confirmation, :account_attributes => [:name])
end
end
The account relation itself persists, but the account NAME does not persist. Looking at the server logs, I can see where the account is persisted but I do not see the name persisting. The strange thing is I can see in the server where it attempts to do the transaction but ultimately doesn't issue any SQL update statement (and doesn't issue a rollback indicating there is no validation error).
SQL (0.2ms) INSERT INTO "accounts" ("created_at", "updated_at") VALUES (?, ?) [["created_at", 2016-10-27 16:39:33 UTC], ["updated_at", 2016-10-27 16:39:33 UTC]]
SQL (0.2ms) INSERT INTO "users" ("name", "account_id", "created_at", "updated_at", "email", "encrypted_password") VALUES (?, ?, ?, ?, ?, ?) [["name", "dsfdsfds"], ["account_id", 32], ["created_at", 2016-10-27 16:39:33 UTC], ["updated_at", 2016-10-27 16:39:33 UTC], ["email", "dsfsdfsdf#fdsfasdfdsfsdfdsc.com"], ["encrypted_password", "$2a$11$pUhS5LGJO2VjPvlPVwj0KO6Ce5Ysr8s4Cu.R4kmsWe7CEayk7t8Fm"]]
(2.2ms) commit transaction
(0.0ms) begin transaction
(0.0ms) commit transaction
(0.0ms) begin transaction
SQL (0.3ms) UPDATE "users" SET "updated_at" = ?, "sign_in_count" = ?, "current_sign_in_at" = ?, "last_sign_in_at" = ?, "current_sign_in_ip" = ?, "last_sign_in_ip" = ? WHERE "users"."id" = ? [["updated_at", 2016-10-27 16:39:33 UTC], ["sign_in_count", 1], ["current_sign_in_at", 2016-10-27 16:39:33 UTC], ["last_sign_in_at", 2016-10-27 16:39:33 UTC], ["current_sign_in_ip", "::1"], ["last_sign_in_ip", "::1"], ["id", 36]]
(0.5ms) commit transaction
Redirected to http://localhost:3000/products
I'm tearing my hair out and I've researched every SO question I could find that's seemingly related. I can do puts sign_up_params[:account_attributes]["name"] in the controller and the name I enter into the form prints back properly, I just can't seem to assign it to the model.
The attr_accessor on the account model is what caused this. By defining an attr_accessor, I was overriding Rails built in attribute accessors for database columns.
Simply removing attr_accessor :name from the Account model fixed this.

Rails attributes not updating

I'm building an invitation system where a user can either invite a friend, setting their user.id to the sender field in the database, or request an invitation, which should set the sender to '0' (an integer field).
User model
...
has_many :invites, :class_name => 'Invitation', :foreign_key => 'sender' #sent_invitations
belongs_to :invitation
...
Invitation model
belongs_to :sender, :class_name => 'User'
has_one :recipient, :class_name => 'User'
Invitations controller
def create
#invitation = Invitation.new(invitation_params)
if current_user?
#invitation.sender = current_user
if #invitation.save
redirect_to invitations_url, notice: 'Thank you. Your invitation has been sent.'
else
render action: "new"
end
else
#invitation.sender = 0
if #invitation.save
redirect_to invitations_url, notice: 'Thank you. You request is being processed..'
else
render action: "new"
end
end
end
The invitation is being created (I can see it in the database), but the sender isn't being set. This is the output form the dev_log:
Started POST "/invitations" for 127.0.0.1 at 2016-05-14 17:49:54 -0600
Processing by InvitationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"aCasBmkfw0m1T/EwuBUlXTA/z+REEWo3Hpv2HpB9w6s=", "invitation"=>{"name"=>"john", "surname"=>"public", "recipient_email"=>"jp#sasdf.com"}, "commit"=>"Create Invitation"}
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."auth_token" = 'i__MG0iqyoIND68k6qJmvw' LIMIT 1
DEPRECATION WARNING: You're trying to create an attribute `sender_id'. Writing arbitrary attributes on a model is deprecated. Please just use `attr_writer` etc. (called from create at C:/Sites/template/app/controllers/invitations_controller.rb:38)
(0.0ms) begin transaction
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."email" = 'jp#sasdf.com' LIMIT 1
SQL (1.0ms) INSERT INTO "invitations" ("created_at", "invite_token", "name", "recipient_email", "sender", "sent_at", "surname", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?) [["created_at", Sat, 14 May 2016 23:49:55 UTC +00:00], ["invite_token", "m_1zd0UxW3W1JqoDdp1EMA"], ["name", "john"], ["recipient_email", "jp#sasdf.com"], ["sender", nil], ["sent_at", nil], ["surname", "public"], ["updated_at", Sat, 14 May 2016 23:49:55 UTC +00:00]]
(0.0ms) UPDATE "users" SET "invites_avail" = 4, "updated_at" = '2016-05-14 23:49:55.161966' WHERE "users"."id" = 2
(70.0ms) commit transaction
Redirected to http://localhost:3000/invitations
Completed 302 Found in 193.0ms (ActiveRecord: 76.0ms)
I'm stumped because #1, I'm not creating an arbitrary attribute "sender_id". The applicable column in the database is "sender", and #2, the POST isn't setting the sender id, which should either be "0" or the id of the current_user.
What am I doing wrong?
I couldn't find an answer to my question, so I monkeyed it instead.
Since I'm able to get the invitation.sender to save when the invitation is sent from a current_user, and the rest were just setting nothing (NULL) in the database, I changed the query parameters in the invitations_controller.rb to look for #invitation.sender = nil for all corporate-sent invitations.
I'll leave this up until/unless someone posts a better response. Cheers!

Rails 3: Database column won't update through active record

I haven't an issue where I can't seem to update or modify a database column in rails 3. I've never seen anything like this before and as such am sure it's something small that I'm overlooking. Please help!
IRB Output:
ruby-1.9.2-p318 :002 > User.all
User Load (0.1ms) SELECT "users".* FROM "users"
=> []
ruby-1.9.2-p318 :003 > User.create( :login => "dummy", :password => "foobar", :password_
confirmation => "foobar", :role => "user", :email => "dummy#email.com" )
(0.1ms) begin transaction
User Exists (0.1ms) SELECT 1 FROM "users" WHERE "users"."login" = 'dummy' LIMIT 1
User Exists (0.0ms) SELECT 1 FROM "users" WHERE "users"."email" = 'dummy#email.com' L
IMIT 1
SQL (0.8ms) INSERT INTO "users" ("created_at", "email", "hashed_password", "login", "
role", "salt", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["created_at", Thu, 05 Apr 2
012 02:21:00 UTC +00:00], ["email", "dummy#email.com"], ["hashed_password", "6416111c47f
a52ddfbde9e539ee6e369807bdeab"], ["login", "dummy"], ["role", nil], ["salt", "1LTzevgRHt
"], ["updated_at", Thu, 05 Apr 2012 02:21:00 UTC +00:00]]
(61.5ms) commit transaction
=> #<User id: 3, login: "dummy", role: nil, hashed_password: "6416111c47fa52ddfbde9e539
ee6e369807bdeab", email: "dummy#email.com", salt: "1LTzevgRHt", created_at: "2012-04-05
02:21:00", updated_at: "2012-04-05 02:21:00">
ruby-1.9.2-p318 :004 > u = User.first
User Load (0.2ms) SELECT "users".* FROM "users" LIMIT 1
=> #<User id: 3, login: "dummy", role: nil, hashed_password: "6416111c47fa52ddfbde9e539
ee6e369807bdeab", email: "dummy#email.com", salt: "1LTzevgRHt", created_at: "2012-04-05
02:21:00", updated_at: "2012-04-05 02:21:00">
ruby-1.9.2-p318 :005 > u.role
=> nil
ruby-1.9.2-p318 :006 > u.role = "foo"
=> "foo"
ruby-1.9.2-p318 :007 > u.role
=> "foo"
ruby-1.9.2-p318 :008 > u
=> #<User id: 3, login: "dummy", role: nil, hashed_password: "6416111c47fa52ddfbde9e539
ee6e369807bdeab", email: "dummy#email.com", salt: "1LTzevgRHt", created_at: "2012-04-05
02:21:00", updated_at: "2012-04-05 02:21:00">
Migration:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.column :login, :string
t.column :role, :string
t.column :hashed_password, :string
t.column :email, :string
t.column :salt, :string
t.timestamps
end
end
end
Schema:
ActiveRecord::Schema.define(:version => 20120318205424) do
create_table "users", :force => true do |t|
t.string "login"
t.string "role"
t.string "hashed_password"
t.string "email"
t.string "salt"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
end
Model:
require 'digest/sha1'
class User < ActiveRecord::Base
validates_length_of :login, :within => 3..40
validates_length_of :password, :within => 4..40
validates_presence_of :login, :email, :password, :password_confirmation, :salt
validates_uniqueness_of :login, :email
validates_confirmation_of :password
validates_format_of :email, :with => /^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i, :message => "Invalid email"
attr_accessor :password, :password_confirmation, :role
attr_protected :id, :salt
def self.random_string(len)
chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
newpass = ""
1.upto(len) { |i| newpass << chars[rand(chars.size-1)] }
return newpass
end
def password=(pass)
#password=pass
self.salt = User.random_string(10) if !self.salt?
self.hashed_password = User.encrypt(#password, self.salt)
end
def self.encrypt(pass, salt)
Digest::SHA1.hexdigest("#{pass}#{salt}")
end
def self.authenticate(login, pass)
u=find(:first, :conditions=>["login = ?", login])
return nil if u.nil?
if User.encrypt(pass, u.salt)==u.hashed_password
# edits wont save without this
u.password=u.password_confirmation=pass
return u
end
nil
end
def send_new_password
new_pass = User.random_string(10)
self.password = self.password_confirmation = new_pass
self.save
Notification.deliver_forgot_password(self.email, self.login, new_pass)
end
def admin?
(self.role == "admin")
end
end
SQLite Update, to show it works:
sqlite> select * from users;
3|dummy||6416111c47fa52ddfbde9e539ee6e369807bdeab|dummy#email.com|1LTzevgRHt|2012-04-05 02:21:00.752890|2012-04-05 02:21:00.752890
sqlite> select role from users;
sqlite> select role from users where login = "dummy";
sqlite> update users set role = "user" where login = "dummy";
sqlite> select role from users where login = "dummy";
user
sqlite> select * from users;
3|dummy|user|6416111c47fa52ddfbde9e539ee6e369807bdeab|dummy#email.com|1LTzevgRHt|2012-04-05 02:21:00.752890|2012-04-05 02:21:00.752890
I've been messing with this for a while... thanks for any help you can give.
EDIT on request:
ruby-1.9.2-p318 :011 > User.last.update_attributes!(:role => "foo")
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT 1
(0.1ms) begin transaction
User Exists (0.1ms) SELECT 1 FROM "users" WHERE ("users"."login" = 'dummy' AND "users"."id" != 3) LIMIT 1
User Exists (0.1ms) SELECT 1 FROM "users" WHERE ("users"."email" = 'dummy#email.com' AND "users"."id" != 3) LIMIT 1
(0.1ms) rollback transaction
ActiveRecord::RecordInvalid: Validation failed: Password is too short (minimum is 4 characters), Password can't be blank, Password confirmation can't be blank
from /home/jmervine/Development/personal/blog/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.2/lib/active_record/validations.rb:56:in `save!'
from /home/jmervine/Development/personal/blog/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.2/lib/active_record/attribute_methods/dirty.rb:33:in `save!'
from /home/jmervine/Development/personal/blog/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.2/lib/active_record/transactions.rb:246:in `block in save!'
from /home/jmervine/Development/personal/blog/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.2/lib/active_record/transactions.rb:295:in `block in with_transaction_returning_status'
from /home/jmervine/Development/personal/blog/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction'
from /home/jmervine/Development/personal/blog/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.2/lib/active_record/transactions.rb:208:in `transaction'
from /home/jmervine/Development/personal/blog/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.2/lib/active_record/transactions.rb:293:in `with_transaction_returning_status'
from /home/jmervine/Development/personal/blog/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.2/lib/active_record/transactions.rb:246:in `save!'
from /home/jmervine/Development/personal/blog/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.2/lib/active_record/persistence.rb:224:in `block in update_attributes!'
from /home/jmervine/Development/personal/blog/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.2/lib/active_record/transactions.rb:295:in `block in with_transaction_returning_status'
from /home/jmervine/Development/personal/blog/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction'
from /home/jmervine/Development/personal/blog/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.2/lib/active_record/transactions.rb:208:in `transaction'
from /home/jmervine/Development/personal/blog/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.2/lib/active_record/transactions.rb:293:in `with_transaction_returning_status'
from /home/jmervine/Development/personal/blog/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.2/lib/active_record/persistence.rb:222:in `update_attributes!'
from (irb):11
from /home/jmervine/Development/personal/blog/vendor/bundle/ruby/1.9.1/gems/railties-3.2.2/lib/rails/commands/console.rb:47:in `start'
from /home/jmervine/Development/personal/blog/vendor/bundle/ruby/1.9.1/gems/railties-3.2.2/lib/rails/commands/console.rb:8:in `start'
from /home/jmervine/Development/personal/blog/vendor/bundle/ruby/1.9.1/gems/railties-3.2.2/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'ruby-1.9.2-p318 :012 > User.last.update_attributes!(:role => "foo")
remove :role from this line attr_accessor :password, :password_confirmation, :role