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
Related
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
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.
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.
In a Ruby on Rails 3 application, I have invitations. Here is the model:
class TeamInvitation < ActiveRecord::Base
belongs_to :team
validates :email, :presence => true, :format => RFC822::EMAIL
validates_uniqueness_of :email, :scope => :team_id
end
How can I refactor the uniqueness validation to include it into the validates method?
According to the documentation, the key :uniqueness should be a boolean, but in my case i want specify the scope. How can I do that (if possible)?
Have you tried this?
:uniqueness => { :scope => :team_id }
I haven't, but I know other ones can accept a hash. Might be worth a shot.
you can try :uniqueness => true
I use Rails 3.0.0.beta4
I want to add a validation on uniqueness on two attributes, that means that my model is valid if the couple of 'recorded_at' and 'zipcode' is unique.
On one attribute here is the syntax
validates :zipcode, :uniqueness => true
thanks
In Rails 2, I would have written:
validates_uniqueness_of :zipcode, :scope => :recorded_at
In Rails 3:
validates :zipcode, :uniqueness => {:scope => :recorded_at}
For multiple attributes:
validates :zipcode, :uniqueness => {:scope => [:recorded_at, :something_else]}
Multiple Scope Parameters:
class TeacherSchedule < ActiveRecord::Base
validates_uniqueness_of :teacher_id, :scope => [:semester_id, :class_id]
end
http://apidock.com/rails/ActiveRecord/Validations/ClassMethods/validates_uniqueness_of
This should answer Greg's question.
Dont work for me, need to put scope in plural
validates_uniqueness_of :teacher_id, :scopes => [:semester_id,
:class_id]