So I have a userMigration file which creates the rows in the table manually. This called in the initialization stage. Also, on that particular table I have validations on how the user's details should be (length, uniqueness etc).
Migration.rb
Models::Persistence::User.create({:email => 'testuser#cs.com',
:username => 'testuser#cs.com',
:first => '',
:last => 'User',
:password => 'Test123!!',
:bio => 'User, student',
# :user_id => 3,
# :photoURL => "http://link",
:created_by => 1})
My models file for users:
module Persistence
# Models persistent User data
class User < ActiveRecord::Base
include Songkick::OAuth2::Model::ResourceOwner
validates :bio, length: {maximum: 500}
validates_uniqueness_of :email
validates :email, :presence => true, :allow_nil => false
validates_format_of :email,:with => /\A[^#\s]+#([^#\s]+\.)+[^#\s]+\z/
validates :first, :presence => true, :allow_nil => false, length: {maximum: 100}
validates_format_of :first, :with => /[a-zA-Z]/
When I change the userMigration data and put in values which do not meet the validation criteria, the rows with that data is still created. (The first name in nil in the migration file but the row is still created in the db.) Is there a way to make print out an error at this stage?
Try using the bang version: create! - it throws an error if the record is invalid.
http://guides.rubyonrails.org/active_record_validations.html#when-does-validation-happen-questionmark
Rails 3 - DB seed data validation
Related
I want to start persisting data that was (intentionally) not being persisted before.
The model originally looked like this:
class Inquiry
include ActiveAttr::Model
include ActiveAttr::MassAssignment
attribute :name
attribute :email
attribute :phone
attribute :company
attribute :content
attr_accessor :name, :email, :phone, :company, :content
validates :name, :presence => true
validates :email, :presence => true, :format => {:with => /^([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})$/i }
validates :phone, allow_blank: true, :format => {:with => /^\+?([\d]{10,13})?$/}
validates :content, :presence => true
end
I ran a migration to create an inquiries table and changed the model file to look like this:
class Inquiry < ActiveRecord::Base
attr_accessible :name, :email, :phone, :company, :content
validates :name, :presence => true
validates :email, :presence => true, :format => {:with => /^([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})$/i }
validates :phone, allow_blank: true, :format => {:with => /^\+?([\d]{10,13})?$/}
validates :content, :presence => true
end
I realized my models didn't have a created_at or updated_at field so I ran a migration and placed 'change_table(:inquiries) { |t| t.timestamps }' in the change method.
Now when I run my specs I get the following error:
Can't mass-assign protected attributes: id, created_at, updated_at
I would like to remedy this problem by modifying what already exists rather than deleting the model, dropping the table, and Rails generating a new model. I know I can pass id, created_at, and updated_at into attr_accessible but I would like to preserve Active Record's default behavior of handling their assignment automatically and preventing mass assignment.
I'm creating a sample_app with railstutorial.org and I have a small problem with creating a new User in Rails 4.
I'm in a chapter 6: http://ruby.railstutorial.org/chapters/modeling-users#sec-the_model_file
After creating a new user in Rails console for example:
user = User.new(name: "Example", email: "email#example.com")
I got:
#<User id: 2, name: nil, email: nil, created_at: "2013-12-29 19:53:25", updated_at: "2013-12-29 19:53:25">
So that's mean, that I've just created a new user with nil params, but I initialized a name and email....
but when I type:
user.name
I got:
user.name
=> "Example"
also in sqlite3 data browser application I see only an empty columns.
My user.rb looks like:
class User < ActiveRecord::Base
attr_accessor :name, :email
email_regex = /\A[\w.\-]+#[a-z+\d\-.]+\.+[a-z]+\z/i
validates :name, :presence => true,
:length => {maximum: 50}
#:uniqueness => true
validates :email, :presence => true,
:format => {with: email_regex},
:uniqueness => {:case_sensitive => false}
end
So what's wrong? Any idea how to fix that?
Remove the attr_accessor line altogether, the Rails tutorial doesn't use it, and you don't need it.
Problem solved :)
As for why that doesn't work with accessor but it does with writer, I don't know, but you can definitely do the tutorial for now without getting stuck on that detail.
You are confusing attr_accessor with attr_accessible.
attr_accessor is used to create setter and getter methods, which is why you are able to retrieve the results from user.name.
attr_accessible is used to white-list attributes for mass-assignment, essentially allowing you to pass those parameters up through the ORM.
In your case, the creation of these getter and setter methods are overriding the default methods that ActiveRecord::Base has already created for you. Use of attr_accessor would be for a variable that is not already defined by the columns in your table.
class User < ActiveRecord::Base
attr_accessible :name, :email
email_regex = /\A[\w.\-]+#[a-z+\d\-.]+\.+[a-z]+\z/i
validates :name, :presence => true,
:length => {maximum: 50}
#:uniqueness => true
validates :email, :presence => true,
:format => {with: email_regex},
:uniqueness => {:case_sensitive => false}
end
I have a text field that can be empty when created, but not when updated.
How can I do that in rails: Different validation rules depending on action?
The idea behind this, is to allow an admin to create a blank issue ticket, to be filled by a user.
Here is my original model (issue.rb):
class Issue < ActiveRecord::Base
attr_accessible :content, :status
validates :content, :presence => true, :length => { :maximum => 2048 }
validates :status, :inclusion => { :in => %w(WAITING REJECTED ON OFF) }
belongs_to :user
end
How can I set :presence => true of :content only when updating, but not when creating?
Thanks in advance.
You can use :on => :create in your validation statement.
Like in this question.
I'm a newbie watching a Lynda.com video about rails 3. The teacher creates a method like this to find a user
def name
"#{first_name} #{last_name}"
end
He says this will return first name and last name for this user, but I don't understand how this function accesses first_name last_name, since there is no call to a database or no form parameters.
I know that without looking at the whole application it will be impossible for you to explain this, but you may be able to guess what this function might be dependent on.
this is the whole AdminUser model
require 'digest/sha1'
class AdminUser < ActiveRecord::Base
# To configure a different table name
# set_table_name("admin_users")
has_and_belongs_to_many :pages
has_many :section_edits
has_many :sections, :through => :section_edits
attr_accessor :password
EMAIL_REGEX = /^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i
# standard validation methods
# validates_presence_of :first_name
# validates_length_of :first_name, :maximum => 25
# validates_presence_of :last_name
# validates_length_of :last_name, :maximum => 50
# validates_presence_of :username
# validates_length_of :username, :within => 8..25
# validates_uniqueness_of :username
# validates_presence_of :email
# validates_length_of :email, :maximum => 100
# validates_format_of :email, :with => EMAIL_REGEX
# validates_confirmation_of :email
# new "sexy" validations
validates :first_name, :presence => true, :length => { :maximum => 25 }
validates :last_name, :presence => true, :length => { :maximum => 50 }
validates :username, :length => { :within => 8..25 }, :uniqueness => true
validates :email, :presence => true, :length => { :maximum => 100 },
:format => EMAIL_REGEX, :confirmation => true
# only on create, so other attributes of this user can be changed
validates_length_of :password, :within => 8..25, :on => :create
before_save :create_hashed_password
after_save :clear_password
scope :named, lambda {|first,last| where(:first_name => first, :last_name => last)}
scope :sorted, order("admin_users.last_name ASC, admin_users.first_name ASC")
attr_protected :hashed_password, :salt
def name
"#{first_name} #{last_name}"
end
def self.authenticate(username="", password="")
user = AdminUser.find_by_username(username)
if user && user.password_match?(password)
return user
else
return false
end
end
# The same password string with the same hash method and salt
# should always generate the same hashed_password.
def password_match?(password="")
hashed_password == AdminUser.hash_with_salt(password, salt)
end
def self.make_salt(username="")
Digest::SHA1.hexdigest("Use #{username} with #{Time.now} to make salt")
end
def self.hash_with_salt(password="", salt="")
Digest::SHA1.hexdigest("Put #{salt} on the #{password}")
end
private
def create_hashed_password
# Whenever :password has a value hashing is needed
unless password.blank?
# always use "self" when assigning values
self.salt = AdminUser.make_salt(username) if salt.blank?
self.hashed_password = AdminUser.hash_with_salt(password, salt)
end
end
def clear_password
# for security and b/c hashing is not needed
self.password = nil
end
end
The method "name" is not finding a user from the database, however the variables inside it (first_name and last_name) are read from the corresponding database table fields. In this case assuming the usual rails conventions are followed you will find a database table called "AdminUsers" and inside it some fields of which one is first_name and another is second_name.
How this all works and why it is so can be found in the Ruby on Rails documentation for ActiveRecord
In my model I've got a couple of methods to populate attributes of an Invoice before it is validated:
validates :account_id, :presence => true
validates :account_address, :presence => true
validates :number, :presence => true
validates :number, :uniqueness => true, :scope => :client_id
before_validation :generate_number, :associate_addresses, :on => :create
def generate_number
self.number = self.client.invoices.count + 1
end
def associate_addresses
self.account_address = self.account.addresses.first
end
And in the controller:
#invoice = #account.invoices.build(:client_id => #client.id)
if #invoice.save
#it saved
end
My problem is that the associate_addresses and generate_number methods only fire if I remove the :scope => :client_id argument on the :number validation.
Why would it skip the before_validation callbacks due to this?
Working in Rails 3.0.3
Thanks!
Thanks.
Don't know why it's skipping the before_validation methods, but to scope a uniqueness validation in Rails 3 you should use the following syntax:
validates :number, :presence => true, :uniqueness => { :scope => :client_id }
I guess that your syntax is making it try to add a scope validation, which doesn't exist. Probably there's a Rails bug that makes that skip the before_validation methods.