Say I wish to create a user from console with an email which already exists. If I do User.create(...)
Because of model validations (uniqueness in this case). create fails and the output in rails console will say: rollback transaction (user is not saved)
For the purpose of testing. Is their a way I can get the explicit error which triggered the rollback? In this case it would say something like: "ROLLBACK: email is not unique".
You can also do:
User.create!
The 'bang' will force it to show you the errors without additional steps.
You could do the following in Rails console:
>> user = User.new(...)
>> user.save
>> user.errors.messages
That way, you know what errors caused save to fail.
If you mean by using "rails console", I hope and this small example is useful for you:
Model Student (student.rb):
class Student < ApplicationRecord
validates :name, presence: true, length: {minimum: 5, maximum: 50}
end
And at Rails console ($ rails console) do something like this:
> student = Student.create(name:"alba")
(0.1ms) begin transaction
(0.1ms) rollback transaction
=> #<Student id: nil, name: "alba">
> student.errors.any?
=> true
> student.errors.full_messages
=> ["Name is too short (minimum is 5 characters)"]
Hope this helps.
Related
I am manually creating objects in the rails console using Model.new(<attributes here>). Is there an easy way to list out which attributes a model will require me to include in order for the .save call to succeed?
I am running rails 4.2.3
You can get an array of validators using Model.validators. You'll have to parse this in some way to extract those validations for presence, something like:
presence_validated_attributes = Model.validators.map do |validator|
validator.attributes if validator.is_a?(ActiveRecord::Validations::PresenceValidator)
end.compact.flatten
I found a simpler way to accomplish the same thing:
When you do a failed create you can check the error message on the object.
# app/models/price.rb
class Price < ActiveRecord::Base
validates_presence_of :value
end
# in console
p = Price.new()
=> #<Price id: nil, created_at: nil, updated_at: nil, value: nil>
p.save
=> false
p.errors.messages
=> {:value=>["can't be blank"]}
In case you the mandatory attributes with error messages
book = Book.new
book.valid?
book.errors.messages
In case you just want the name of attributes without an error message
book = Book.new
book.valid?
book.errors.messages.keys
I'm trying to populate my SQLite3 database with a simple seed file that is supposed to create a bunch o movies entries in the Film table and then create some comments to this movies that are stored in Comments table.
formats = %w(Beta VHS IMAX HD SuperHD 4K DVD BlueRay)
30.times do
film = Film.create(title: "#{Company.bs}",
director: "#{Name.name}",
description: Lorem.paragraphs.join("<br/>").html_safe,
year: rand(1940..2015),
length: rand(20..240),
format: formats[rand(formats.length)]
)
film.save
(rand(0..10)).times do
film.comments.create( author: "#{Name.name}",
title: "#{Company.bs}",
content: Lorem.sentences(3).join("<br/>").html_safe,
rating: rand(1..5)
)
end
end
Once i execute rake db:seed I inevitably get the error
ActiveRecord::RecordNotSaved: You cannot call create unless the parent is saved
and no records are added to either Films or Comments
My film.rb file is
class Film < ActiveRecord::Base
has_many :comments
validates_presence_of :title, :director
validates_length_of :format, maximum: 5, minimum:3
validates_numericality_of :year, :length, greater_than: 0
validates_uniqueness_of :title
paginates_per 4
end
The length limit on 'format' raises the error when creating a Film with formats selected from the 'format' list
ActiveRecord::RecordNotSaved: You cannot call create unless the parent is saved
This occurs when you try to save a child association (Comment) but the parent (Film) isn't saved yet.
It seems that film is not saved. Looking at the code, it appears that film = Film.create(...) is failing validations and thus film.comments.create(..) cannot proceed.
Without knowing more about which validation is failing, that's all I can say.
I would recommend using create!(...) everywhere in seeds.rb. The bang version will raise an exception if the record isn't valid and help prevent silent failures.
I am trying to insert a new record into a SQLiteDB through my Rails console. Simply using User.create().
The row does not appear in my database.The message implies that a user exists, but calling User.first returns null and checking the database shows an empty table. What am I missing?
Input:
console > User.create(name: 'don', email: 'don#gmaill.com', password: 'test', password_confirmation: 'test')
Output:
(0.1ms) begin transaction
User Exists (0.1ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = 'don#gmaill.com' LIMIT 1
(0.0ms) rollback transaction
=> #<User id: nil, name: "don", email: "don#gmaill.com", created_at: nil, updated_at: nil, password_digest: "$2a$10$3EK3L932ryjrJPFIc4E0/uzavrpkWylDRzx4Wkdwzx8d...">
User Class:
class User < ActiveRecord::Base
before_save { self.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sen,sitive: false }
has_secure_password
validates :password, length: { minimum: 6 }
end
It's not persisting the User (you can tell by the rollback statement). Looks like it's failing a uniqueness validation on the email. You can look at the errors by calling errors.full_messages on the User you tried to create, or by using create! instead of create
You are most likely validating uniqueness of email field. Hence ActiveRecord is issuing a select first to check if a record exist with the same email address, and finding one. Hence Create is not saving the new record to database.
But create returns the object anyway.
You can try this to verify this. Instead of create, try new followed by save!
console > u = User.new(name: 'don', email: 'don#gmaill.com', password: 'test', password_confirmation: 'test')
console > u.save!
To get rid of this error, first delete the record that exists in the DB
I have an ActiveRecord object and I would like to prevent it from being saved, without having permanent validations on the model. You used to be able to do something like this using errors.add but it doesn't look like it works anymore.
user = User.last
user.errors.add :name, "name doesn't rhyme with orange"
user.valid? # => true
user.save # => true
or
user = User.last
user.errors.add :base, "my unique error"
user.valid? # => true
user.save # => true
How can I prevent the user object from getting saved in Rails 3.2 without modifying it's model?
You can set errors, but do it within a validate method, e.g.:
validate :must_rhyme_with_orange
def must_rhyme_with_orange
unless rhymes_with_orange?
errors.add(:name, "doesn't rhyme with orange")
end
end
If you want to conditionally run the validation, one trick is to use attr_accessor and a guard condition:
attr_accessor :needs_rhyming
validate :must_rhyme_with_orange, :if => Proc.new {|o| o.needs_rhyming}
> u = User.last
> u.needs_rhyming = true
> u.valid? # false
Your issue is running valid? will rerun the validations.. resetting your errors.
pry(main)> u.errors[:base] << "This is some custom error message"
=> ["This is some custom error message"]
pry(main)> u.errors
=> {:base=>["This is some custom error message"]}
pry(main)> u.valid?
=> true
pry(main)> u.errors
=> {}
pry(main)>
Instead, just check if u.errors.blank?
This is a slight deviation from the original question, but I found this post after trying a few things. Rails has built in functionality to reject an object from saving if it has the _destroy attribute assigned as true. Quite helpful if you're handling model creation on the controller level.
This one really has me. I have this validation in my user model:
validates :first_class, :presence => true, :inclusion => %w(Fighter Ranger Magician)
Now, I try an example create in my console:
ruby-1.9.2-p180 :053 > new = User.create(:first_class => 'Magician')
=> #<User id: nil, ...
ruby-1.9.2-p180 :054 > new.errors
=> {:first_class=>["can't be blank", "is not included in the list"]}
Why am I getting this validation error? I SERIOUSLY cannot figure that out.
(If i remove the validation, the user gets created, but first_class is nil :O)
maybe try having attr_accessible :first_class in your model file
You have to tell rails which attributes are writeable through mass-assignment. The new method takes a parameters hash, which is considered mass-assignment. The same is true with update_attributes.
To verify, you could just make a new instance and say object.first_class = 'Magician'. If this also fails, then you know attr_accessible is not the problem.