Railstutorial.org 6.2.4 Format Validation - validation

Working my way through Hartl's Railstutorial.org, an I run into an issue getting the test to work on the Format validation with the email.
My user.rb is as follows:
class User < ActiveRecord::Base
validates :name, presence: true, length: { maximum:50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }
end
user_spec.rb is:
require 'spec_helper'
describe User do
before do
#user = User.new(name: "Example User", email: "user#example.com")
end
subject { #user }
it { should respond_to(:name) }
it { should respond_to(:email)}
it { should be_valid}
describe "when name is not present" do
before { #user.name = " " }
it { should_not be_valid }
end
describe "when email is not present" do
before { #user.email=" "}
it { should_not be_valid }
end
describe "when name is too long" do
before { #user.name="a"*51}
it {should_not be_valid}
end
describe "when email format is invalid" do
it "should be invalid" do
addresses = %w[user#foo,com user_at_foo.org
example.user#foo. foo#bar_baz.com foo#bar+baz.com]
addresses.each do |invalid_address|
#user.email = invalid_address
expect(#user).not_to be_valid
end
end
end
describe "when email format is valid" do
it "should be valid" do
addresses = %w[user#foo.COM A_US-ER#f.b.org frst.lst#foo.jp a+b#baz.cn]
addresses.each do |valid_address|
#user.email = valid_address
expect(#user).to be_valid
end
end
end
end
My error listing is as follows:
Failures:
1) User
Failure/Error: it { should be_valid}
expected #<User id: nil, name: "Example User", email: "user#example.com",
created_at: nil, updated_at: nil> to be valid, but got errors: Email is invalid
# ./spec/models/user_spec.rb:13:in 'block (2 levels) in <top (required)>'
2) User when email format is valid should be valid
Failure/Error: expect(#user).to be_valid
expected #<User id: nil, name: "Example User", email: "user#foo.COM". cre
ated_at: nil, updated_at: nil> to be valid, but got errors. Email is invalid
# ./spec/models/user_spec.rb:45:in 'block (4 levels) in <top (required)>'
# ./spec/models/user_spec.rb:43:in 'each'
# ./spec/models/user_spec.rb:43:in 'block (3 levels) in >top (required)>'
Finished in 0.03 seconds
8 examples, 2 failures
Failed examples:
rspec ./spec/models/user_spec.rb:13 # User
rspec ./spec/models/user_spec.rb:41 # User when email format is valid should be
valid
I am sure that I am missing something minor (when I have this much trouble figuring it out, it usually is minor). Would greatly appreciate any help I can get.

The exact code in the tutorial is as follows:
class User < ActiveRecord::Base
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 }
end
your VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z]+\z/i lacks some letters.

Related

Uniqueness validation for polymorphic model fails

So I have this really weird problem. Here is my model:
class Clip < ApplicationRecord
belongs_to :owner, polymorphic: true
default_scope -> { order(created_at: :desc) }
validates :address, presence: true, uniqueness: { scope: [:owner_type, :owner_id] }
before_save { self.adress=adress.split("=").last }
validates :owner, presence: true
end
and the test
test "invalid creations" do
get new_clip_path
assert_no_difference "Clip.count" do
post clips_path, params: { clip: { address: "",
description: "bum bum bum" } }
end
assert_template "clips/new"
assert_match "blank", response.body
assert_no_difference "Clip.count" do
#clip allready in db, should refure
post clips_path, params: { clip: { address: "fWNaR-rxAic",
description: "bum bum bum" } }
end
assert_template "clips/new"
assert_no_match "blank", response.body
assert_match "Address has already been taken", response.body
end
The test is passing without a problem but I just realized by accident, that I can still create clips with the same address and owner, as often as I want to. This confuses me for two reasons: a) what is wrong with this line validates :address, presence: true, uniqueness: { scope: [:owner_type, :owner_id] } and b) why does the test not fail?

ActiveRecord::AssociationTypeMismatch: User(#49785948) expected, got Hashie::Mash(#52717320)

I'm having a Grape api and I want to save nested datas.
I have a model like this :
class Vehicule < ActiveRecord::Base
before_validation :set_principal, :if =>:new_record?
belongs_to :user
accepts_nested_attributes_for :user
end
The grape api :
# app/controller/api/v1/vehicules.rb
resource :vehicules do
desc "Update a vehicule."
params do
optional :confort, type: Float, desc: ""
optional :user, type: Hash do
optional :name, type: String
end
end
put ':id' do
#authenticate! #todo
Vehicule.find(params[:id]).update(vehicule_params)
end
And here is my test file
test "PUT /api/v1/vehicules/1" do
put("/api/v1/vehicules/1", { 'confort' => 3.4, 'user' => {'name' => 'name changed'} }, :format => "json")
assert(200, last_response.status)
vehicule = Vehicule.find(1)
assert_equal('name changed', vehicule.user.name, "Le nom de l'utilisateur aurait dû changer")
end
The message is
1) Error: API::V1::VehiculesTest#test_PUT_/api/v1/vehicules/1: ActiveRecord::AssociationTypeMismatch: User(#49785948) expected, got Hashie::Mas h(#52717320)
app/controllers/api/v1/vehicules.rb:38:in `block (2 levels) in <class:Vehicu les>'
test/controllers/api/v1/vehicules_test.rb:18:in `block in <class:VehiculesTe st>'
What do I do wrong ? is it the way I'm sending the data or is it my structure/declaration ?
You have to use 'user_attributes' keyword in order to use nested attributes. So you have to change your params block like this:
params do
optional :confort, type: Float, desc: ""
optional :user_attributes, type: Hash do
optional :name, type: String
end
end
The test file have to change accordingly.

How can i return some message if before_validation method is false by Sinatra

I want to return some message that tell the user their password is not match with the confirm password field.
This is my code
post '/signup' do
user = User.new(params[:user])
if user.create_user
"#{user.list}"
else
"password not match"
end
end
require 'bcrypt'
class User < ActiveRecord::Base
include BCrypt
# This is Sinatra! Remember to create a migration!
attr_accessor :password
validates :username, presence: true, uniqueness: true
validates :email, :format => { :with => /\A[\w+\-.]+#[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i ,
:message => "Email wrong format" }
validates :email, uniqueness: true,presence: true
validates :encrypted_password, presence: true
validates :encrypted_password, length: { minimum: 6 }
before_validation :checking_confirm_password
def initialize(signup = {})
##signup = signup
super()
#username = signup["username"]
#email = signup["email"]
#password = signup["password"]
#confirm_password = signup["confirm_password"]
end
def create_user
p_p = Password.create(#password)
p_h ||= Password.new(p_p)
user_hash = {:username => #username,:email => #email, :encrypted_password => p_h}
return User.create(user_hash)
end
def list
User.all
end
private
def checking_confirm_password
if #password != #confirm_password
return false
end
end
end
So how can i specific the message that will send back to the user,
if their password is not match or the validation fail before create the dada?
Thanks!
The validations populate #user.errors with all validation errors with all validation errors by field, so you can easily return all validation errors at once like so:
post '/signup' do
user = User.new(params[:user])
if user.create_user
"#{user.list}"
else
user.errors.full_messages
end
end
Have a look at: http://edgeguides.rubyonrails.org/active_record_validations.html#working-with-validation-errors

When is the validator of email uniqueness trigerred?

I have a question about this test from the Michael Hartl tutorial :
Model:
class User < ActiveRecord::Base
.
.
.
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: true
end
Test:
require 'spec_helper'
describe User do
before do
#user = User.new(name: "Example User", email: "user#example.com")
end
.
.
.
describe "when email address is already taken" do
before do
user_with_same_email = #user.dup
user_with_same_email.email = #user.email.upcase
user_with_same_email.save
end
it { should_not be_valid }
end
end
My understanding of the uniqueness validator for the email is that it cannot be added twice in the database. But in this test, the User is just instantiated with a new, not a create.
So here is what I think happens:
#user = User.new (just in memory)
...
user_with_same_email = #user.dup we have two users in memory
...
user_with_same_email.save we are inserting the first user in the db, so it should be valid, and yet the test it { should_not be_valid } passes.
What am I getting wrong ?
What really happens:
In before:
#user = User.new (just in memory)
In the describe:
user_with_same_email = #user.dup we have two users in memory
user_with_same_email.save we are inserting the first user in the db, so it should be valid, and it is ! But that's not what's being tested here
In the it:
should_not be_valid calls .valid? on #user, and since we've just inserted an user with the same email, #user is not valid. And so the test passes.

RSpec and ActiveRecord : Examples failing while checking One To Many association

I have been developing a sample application after reading Rails 3 Tutorial book. In this application there are many Sections and each section has one Video.
Here are the artifacts of this application:
Models
class Video < ActiveRecord::Base
has_many :sections
end
class Section < ActiveRecord::Base
belongs_to :video
validates :name, presence: true, length: { maximum: 50 }
end
RSpec
require 'spec_helper'
describe Section do
let(:video) { Video.new(name: "Dummy Video Name", path: "/home/data/video/test.mov") }
before do
#section = video.sections.build(name: 'Test Section')
end
subject { #section }
# Check for attribute accessor methods
it { should respond_to(:name) }
it { should respond_to(:video) }
it { should respond_to(:video_id) }
its(:video) { should == video }
# Sanity check, verifying that the #section object is initially valid
it { should be_valid }
describe "when name is not present" do
before { #section.name = "" }
it { should_not be_valid }
end
describe "when name is too long" do
before { #section.name = "a" * 52 }
it { should_not be_valid }
end
describe "when video_id not present" do
before { #section.video_id = nil }
it { should_not be_valid }
end
...
end
And the schema definitions of both Models
..
create_table "sections", :force => true do |t|
t.string "name"
t.integer "video_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "videos", :force => true do |t|
t.string "name"
t.string "path"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
...
While running above rspec I am getting following error.
Failures:
1) Section
Failure/Error: it { should be_valid }
expected valid? to return true, got false
# ./spec/models/section_spec.rb:22:in `block (2 levels) in <top (required)>'
2) Section video
Failure/Error: its(:video) { should == video }
expected: #<Video id: nil, name: "Dummy Video Name", path: "/home/data/video/test.mov", created_at: nil, updated_at: nil>
got: nil (using ==)
# ./spec/models/section_spec.rb:19:in `block (2 levels) in <top (required)>'
I could map my requirement with User-Micropost relation describe in the book and aligned RSpec with them. I have limited knowledge on Rails and the whole echo system.
Please help me to resolve this issue and some reference to validation Models with RSpec(and shoulda) is highly appreciable.
Amit Patel
I am able to resolve this issue by saving video in before block.
Here is the snippet
before do
video.save
#section = video.sections.build(name: 'Test Section')
end
The only difference between the Micropost model spec of Rails 3 Tutorial book and the above one is , the former one is using FactoryGirl#create. From https://github.com/thoughtbot/factory_girl/wiki/How-factory_girl-interacts-with-ActiveRecord I found that FactoryGirl.create method actually creates and save instance internally. So it was working there while it was no working in my code.
If you have better insight with RSpec for ActiveRecord then please share with us.
Thanks.
Amit Patel

Resources