ActiveModel presence validation fails - validation

I have created a model (called PhoneNumber) that is not backed by a database table:
class PhoneNumber
include ActiveModel::Validations
attr_accessor :pnumber
validates :pnumber, presence: true, on: :create #=> { :message => " cannot be blank" }
validates :pnumber, numericality: true, on: :create
end
I am testing it in the console like this:
2.0.0-p451 :001 > example = PhoneNumber.new
=> #<PhoneNumber:0x007f839c90c690>
2.0.0-p451 :002 > example.valid?
=> true
2.0.0-p451 :003 > example.pnumber
=> nil
As you can see, the empty PhoneNumber is considered valid even if the :pnumber attribute is nil, i.e. the validation is not working. How to fix it?

Long story short, on: :create does not work in this context.
Usually validations are not tied to actions anyways, so you're good with just removing it.
Have a good one,
Jan

Related

shoulda matcher and conditional validation errors

Here I use the attribute :new_record to set the condition for validation.
attr_accessor :new_record
validates :email, presence: true, email: true, unless: :new_record?
def new_record?
#new_record || true
end
if the new_record? == true, the email validation will be skipped and new user is valid.
I wrote this test:
it { expect(subject).to validate_presence_of(:email) }
and it returns error:
Failure/Error: it { expect(subject).to validate_presence_of(:email) }
User did not properly validate that :email cannot be empty/falsy.
After setting :email to ‹nil›, the matcher expected the User to be
invalid, but it was valid instead.
Note that this test run perfectly if there is no condition added to the validation. Also, the code work well in production.
I also have tried
before(:each) do
subject.new_record = true
end
or
`before { allow(subject).to receive(:new_record?).and_return(true) }`
Can any one help?

DEPRECATION WARNING: The `Validator#setup` instance method is deprecated and will be removed on Rails 4.2

I don't know what this warning is ? Please suggest something.
Given below is part of my application code.
It gives me error on statement with validates_date line.
Rails suggest me the do something like:
class MyValidator < ActiveModel::Validator
def initialize(options={})
super
options[:class].send :attr_accessor, :custom_attribute
end
end
This is the code of application below:
class Patient < ActiveRecord::Base
searchkick index_name: "patients",text_start: [:first_name,:last_name]
after_update :reindex
has_secure_password
has_many :addresses
has_many :vitals
has_attached_file :avatar, :styles => { :medium => "150x150>", :thumb => "50x50>" }, :default_url => "app/assets/images/missing.png"
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
validates :email, email_format: {message: "Invalid email format" }
validates_uniqueness_of :email
validates :password_digest, presence: true, confirmation: true, length: {minimum: 8,message:"Must be of atleast 8 characters"}
validates :first_name, presence: true, format: { with: /\A[a-zA-Z]+\z/, message: "First Name should contain only alphabets"}
validates :last_name, presence: true, format: { with: /\A[a-zA-Z]+\z/, message: "Last Name should contain only alphabets" }
validates_date :dob,:before => lambda { Date.current }, presence: true
validates :password_digest, presence: true, confirmation: true, length: {minimum: 8,message:"Must be of atleast 8 characters"}
validates :primary_phone_no, presence: true,numericality: {only_integer: true}
end
You don't need to worry right now. I see from validates_date you are using the validates_timeliness gem - it's that gem that is currently throwing the deprecation warning.
It is an open issue on that gem and it's being worked on - this is the current open issue: https://github.com/adzap/validates_timeliness/pull/114
I suggest you just wait until they fix it and then update the gem. It's just a warning and won't stop anything working right now.

Two-page sign-up process in rails?

I'm attempting to create a rails app where a user will sign up, then immediately be directed to fill out a profile with more detailed information.
I'm currently attempting this by having both a users and a profile model, with a has_one/belongs_to relationship between the two models.
I'm having trouble with createing the profile for the user. Tests fail with undefined methodprofiles' for #when testing the creation, and using an automated profile builder calledsample_data.rake`:
namespace :db do
desc "Fill database with sample data"
task :populate => :environment do
Rake::Task['db:reset'].invoke
admin = User.create!(:name => "name name",
:email => "fakename#fake.com",
:password => "password",
:password_confirmation => "password")
admin.toggle!(:admin)
99.times do |n|
name = Faker::Name.name
email = Faker::Internet.email
password = "password"
User.create!(:name => name,
:email => email,
:password => password,
:password_confirmation => password)
end
User.all.each do |user|
User.profiles.create(:city => Faker::Address.city,
:state => Faker::Address.us_state_abbr,
...
)
end
end
end
Also fails on
I'm having trouble with createing the profile for the user. Tests fail with undefined method 'profiles'
profiles_controller.rb is:
class ProfilesController < ApplicationController
before_filter :authenticate, :only => [:create, :edit]
def create
#profile = current_user.profiles.build(params[:profile])
if #profile.save
flash[:success] = "Profile Created!"
redirect_to root_path
else
render 'pages/home'
end
end
def edit
end
end
profile.rb is
class Profile < ActiveRecord::Base
attr_accessible :city, :state, ...
belongs_to :user
validates :city, :presence => true
validates :state, :presence => true
...
end
Can anyone see what I'm doing wrong? Is there a way to merge all the items I need under "users", validate the presence of all the required information, and have the signup process be two pages?
Other suggestions for this?
Why do you do this?
1.times do...end
You dont need that.
The failure comes up because you need to create ONE profile, not profiles, for one certain user.
So try this:
User.all.each do |user|
user.create_profile(:city => "bla", ...)
end
In you controller the same. You have just one profile, using singular will help out.

OmniAuth triggering validations

I am using OmniAuth in an application that requires authentication.
I have 3 ways for users to authenticate:
Create an account on my site
Facebook via OmniAuth
Twitter via OmniAuth
For option 1 I have validations in the form of:
validates_presence_of :email, :role
validates_presence_of :password, :if => :password_required
validates_presence_of :password_confirmation, :if => :password_required
validates_length_of :password, :within => 4..40, :if => :password_required
validates_confirmation_of :password, :if => :password_required
validates_length_of :email, :within => 3..100
validates_uniqueness_of :email, :case_sensitive => false
validates_format_of :email, :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
validates_format_of :role, :with => /[A-Za-z]/
The problem is that when I allow a user to login via twitter/facebook for the first time an Account is created, the validations are triggered, and fail.
For example:
ActiveRecord::RecordInvalid - Validation failed: Password can't be blank, Password is too short (minimum is 4 characters), Password confirmation can't be blank:
This makes sense as OmniAuth created accounts will not be submitting a password but i'm not sure exactly how i should make my model aware of this and skip (specific?) validations.
If it's of any use, the full account.rb model is here: http://pastie.org/private/wzpftprrzfg42uifetfhpa
Thanks a lot!!
try to extract the condition into the encrypt_password method from here, this line seems incorrect:
# Callbacks
before_save :encrypt_password, :if => :password_required
can you also copy-paste stack trace please?

ActionMailer 3 without Rails

I'm writing a small Ruby program that will pull records from a database and send an HTML email daily. I'm attempting to use ActionMailer 3.0.3 for this, but I'm running in to issues. All the searching I've done so far on using ActionMailer outside of Rails applies to versions prior to version 3. Could someone point me in the right direction of where to find resources on how to do this? Here's where I am so far on my mailer file:
# lib/bug_mailer.rb
require 'action_mailer'
ActionMailer::Base.delivery_method = :file
class BugMailer < ActionMailer::Base
def daily_email
mail(
:to => "example#mail.com",
:from => "example#mail.com",
:subject => "testing mail"
)
end
end
BugMailer.daily_email.deliver
I'm definitely stuck on where to put my views. Every attempt I've made to tell ActionMailer where my templates are has failed.
I guess I should also ask if there's a different way to go about accomplishing this program. Basically, I'm doing everything from scratch at this point. Obviously what makes Rails awesome is it's convention, so is trying to use parts of Rails on their own a waste of time? Is there a way to get the Rails-like environment without creating a full-blown Rails app?
After some serious debugging, I found how to configure it.
file mailer.rb
require 'action_mailer'
ActionMailer::Base.raise_delivery_errors = true
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => "domain.com.ar",
:authentication => :plain,
:user_name => "test#domain.com.ar",
:password => "passw0rd",
:enable_starttls_auto => true
}
ActionMailer::Base.view_paths= File.dirname(__FILE__)
class Mailer < ActionMailer::Base
def daily_email
#var = "var"
mail( :to => "myemail#gmail.com",
:from => "test#domain.com.ar",
:subject => "testing mail") do |format|
format.text
format.html
end
end
end
email = Mailer.daily_email
puts email
email.deliver
file mailer/daily_email.html.erb
<p>this is an html email</p>
<p> and this is a variable <%= #var %> </p>
file mailer/daily_email.text.erb
this is a text email
and this is a variable <%= #var %>
Nice question! It helped me to understand a bit more how Rails 3 works :)
It took me a while to get this to work in (non-)Rails 4. I suspect it's just because I have ':require => false' all over my Gemfile, but I needed to add the following to make it work:
require 'action_view/record_identifier'
require 'action_view/helpers'
require 'action_mailer'
Without the above code, I kept getting a NoMethodError with undefined method 'assign_controller'.
After that, I configured ActionMailer as follows:
ActionMailer::Base.smtp_settings = {
address: 'localhost', port: '25', authentication: :plain
}
ActionMailer::Base.default from: 'noreply#example.com'
ActionMailer::Base.raise_delivery_errors = true
ActionMailer::Base.logger = Logger.new(STDOUT)
ActionMailer::Base.logger.level = Logger::DEBUG
ActionMailer::Base.view_paths = [
File.join(File.expand_path("../../", __FILE__), 'views', 'mailers')
# Note that this is an Array
]
The templates go in lib/<GEM_NAME>/views/mailers/<MAILER_CLASS_NAME>/<MAILER_ACTION_NAME>.erb (MAILER_ACTION_NAME is the public instance method of your mailer class that you call to send the email).
Lastly, don't forget to put this in your spec_helper:
ActionMailer::Base.delivery_method = :test

Resources