How to structure a Ruby on Rails model? - ruby-on-rails

In our app's User model, we already have:
attr_accessor :remember_token, :activation_token, :reset_token
before_save :downcase_email
before_create :create_activation_digest
before_save { self.email = email.downcase }
validates :first_name, presence: true, length: { maximum: 50 }
validates :last_name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, presence: true, length: { minimum: 6 }, allow_nil: true
Now, we need to add relationship associations to the model, namely:
has_many :roles, dependent: :destroy
has_many :agendas, through: :roles
Does it matter whether we include the latter go BEFORE or AFTER the former, in the model?
If so, what is the recommended / preferred / best way?

It doesn't matter, but the important thing is to be consistent. A usual best practice is to first do all you can to declare the class' structure, before you get in to any operational details. For example:
class User < ActiveRecord::Base
attr_accessor :remember_token, :activation_token, :reset_token
has_many :roles, dependent: :destroy
has_many :agendas, through: :roles
before_save :downcase_email
before_create :create_activation_digest
before_save { self.email = email.downcase }
validates :first_name, presence: true, length: { maximum: 50 }
validates :last_name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, presence: true, length: { minimum: 6 }, allow_nil: true
end
Again, this is just one way to do things, but it's very common amongst Rails applications.

Related

ActiveModel::UnknownAttributeError: unknown attribute 'employee_id' for EmployeeSkill

Have many to many relationship but keep getting the same error: ActiveModel::UnknownAttributeError: unknown attribute 'employee_id' for EmployeeSkill. I've checked both my models and it seems like i have IDs for both so not sure what to do?
class Skill < ApplicationRecord
validates :skill_name, presence: true, length: { minimum: 3, maximum: 30}
validates_uniqueness_of :skill_name
has_many :employee_skills
has_many :employees, through: :employee_skills
end
...
class Employee < ApplicationRecord
before_save { self.email = email.downcase }
#validates :email, presence: true, length: { maximum: 30 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_many :employee_skills
has_many :skills, through: :employee_skills
end
...
class EmployeeSkill < ApplicationRecord
belongs_to :employee
belongs_to :skill
end
1) Check if in your migration files and database the corresponding id's are in place.
2) Restart the server (weird but sometimes is needed).
Your code looks good so I think is one of two cases I mention.
Regards,

Wrap multiple validations in a context

With validation context we can do:
validates :title, presence: true, on: :published
validates :content, length: { maximum: 50 }, on: :published
Is it possible to wrap multiple validations that share a context something like the following?
on: :published do
validates :title, presence: true
validates :content, length: { maximum: 50 }
end
Yes, you can group validations using the with_options method:
with_options(on: :published) do |record|
record.validates :title, presence: true
record.validates :content, length: { maximum: 50 }
end
See the Rails Guides, this article and the sources for more info.

Ruby on Rails Modelling users [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
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, length: { maximum: 255 };
format: { with: VALID_EMAIL_REGEX };
uniqueness: { case_sensitive: false },
has_secure_password:
(validates :password, presence: true, length:{ minimum: 6 } )
end
Someone help me to figure out where this syntax has an error
In your User model try this:
class User < ActiveRecord::Base
before_validation { self.email = email.downcase! }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, presence: true, length: { minimum: 6 }
end
Your model should looks like below.
class User < ActiveRecord::Base
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
before_save { self.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :password, presence: true, length:{ minimum: 6 }
has_secure_password
end
You probably also want to change this line:
before_save { self.email = email.downcase }
Into this:
before_validation { self.email = email.downcase }
The way this is going to go down is:
Validation
Before save callbacks
Actual save
So a user will use uppercase letters in his email, then save and the validations will fail because of the use of uppercase letters.
So you want to set his email to lower case letters BEFORE the validations and not after :-)

How to query scoped 'previous' and 'next' records (ActiveRecord & PostGres) rails 4.2

I am implementing something of a todo list with a user model and a List model with a date attribute.
On the user show page, I retrieve today's to do list.
How do I go about querying a user todo list for the previous and/or the next day.
All insights are welcome, thanks!
class User < ActiveRecord::Base
before_save { self.email = email.downcase }
before_save { self.username = username.downcase }
has_many :to_do_lists, dependent: :destroy
has_many :tasks, dependent: :destroy
validates_presence_of :first_name, :last_name
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(?:\.[a-z\d\-]+)*\.[a-z]+\z/i
VALID_USERNAME_REGEX = /\A[a-z_0-9]+\z/i
validates :email, presence: true,
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :username, presence: true,
format: { with: VALID_USERNAME_REGEX },
uniqueness: { case_sensitive: false }
def name
[first_name, last_name].compact.join(' ')
end
end
and the list model
class ToDoList < ActiveRecord::Base
belongs_to :user
has_many :tasks, dependent: :destroy
validates_presence_of :user_id
validates :date, presence: true,
uniqueness: {scope: :user_id}
end
Rails adds many helpful methods to Time to make this type of query quite intuitive. Since you validate that a user has only one to do list for each day:
#next_day_list = #user.to_do_lists.find_by_date(Date.today.tomorrow)
#prev_day_list = #user.to_do_lists.find_by_date(Date.today.yesterday)

Failing user validation with nested attributes and polymorphic association

This simple validation test is failing:
require 'test_helper'
class UserTest < ActiveSupport::TestCase
def setup
#user = User.new(name: "Example User",
email: "user#example.com",
character_attributes: {callsign: "example"},
password: "foobar",
password_confirmation: "foobar"
)
end
test "should be valid" do
assert #user.valid?, "#{#user.errors.messages}"
end
end
...with this message: character.sociable_id"=>["can't be blank"]
I don't understand why the user creation in UserTest is failing to make a valid User.
Each User has_one :character and each Character belongs_to a User.
The User model:
User.rb:
class User < ActiveRecord::Base
attr_accessor :remember_token, :activation_token, :reset_token
has_one :character, as: :sociable, dependent: :destroy
accepts_nested_attributes_for :character
has_secure_password
before_validation do
self.create_character unless character
end
before_save do
self.email.downcase!
end
before_create :create_activation_digest
validates :name, presence: true,
length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(?:\.[a-z\d\-]+)*\.[a-z]+\z/i
validates :email, presence: true,
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :password, length: { minimum: 6 }, allow_blank: true
validates :character, presence: true
.
.
end
The Character model:
Character.rb:
class Character < ActiveRecord::Base
belongs_to :sociable, polymorphic: true
has_many :posts, dependent: :destroy
before_save do
self.callsign.downcase!
end
validates :sociable_id, presence: true
VALID_CALLSIGN_REGEX = /\A[a-z\d\-.\_]+\z/i
validates :callsign, presence: true,
length: { maximum: 20 },
format: { with: VALID_CALLSIGN_REGEX },
uniqueness: { case_sensitive: false }
end
It should be:-
test "should be valid" do
assert #user.valid? , "#{#user.errors.messages}"
end

Resources