Categories
Rails

Ruby On Rails: models

$ rails generate model User name:string email:string
invoke active_record
create db/migrate/_create_users.rb
create app/models/user.rb invoke rspec
create spec/models/user_spec.rb

Note: Make sure you assign what attributes of your model will be accessible for edit, otherwise Ruby assumes all of them are, and this can be a security hole:

class User < ActiveRecord::Base
attr_accessible :name, :email

Note: on rails 4.1, the attr_accessible method moved to the controllers. The reason being: some apps run into issues where different models wanted to use attr_accessible params in different ways, so these make more sense to be at the controller level.

email_regex = /A[w+-.]+@[a-zd-.]+.[a-z]+z/i
validates(:name, :presence => true, :length => { :maximum => 50 })
validates :email, :presence => true, :format => { :with => email_regex }, :uniqueness => {:case_sensitive => false}
validates :password, :presence => true, :confirmation => true, :length => { :within => 6..40 }

end

The above creates getters and setters for the attributes name and email in that specific model.

Validates adds automatic data validation to the model. Notice how the email address validation takes a regular expression to do this. Notice how password and password confirmation fields are generated in the same line

In order to view and interact with the new model, we need a controller, router and view files, like the ones below:
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
end

def new
@title = “Sign up”
end
end

SampleApp::Application.routes.draw do
resources :users
match ‘/signup’, :to => ‘users#new’
. . .
end

Note: if you do the above in the route, remove: get “users/new”

Inside the models, if you specify the following, your queries will follow the order specified:

default_scope lambda { order('categories.name') }

If you don’t want to be too broad, and you want to be able to choose your scope, you can enhance your model with a scope:

scope :published, lambda { where("articles.published_at IS NOT NULL") }
  scope :draft, lambda { where("articles.published_at IS NULL") }
  scope :recent, lambda { published.where("articles.published_at > ?",
1.week.ago.to_date)}
  scope :where_title, lambda { |term| where("articles.title LIKE ?", "%#{term}%") }

And then, you can do queries like:
Article.published
Article.where_title(“Active”)

If you want to make some of the model’s methods static, so they can be called off the Model’s class (instead of from an instance of the model), you need to use the “self” key. For example, to make the “authenticate” method available off User.authenticate(), you can specify it inside the model as follows:

def self.authenticate(email, password)
user = find_by_email(email)
return user if user && user.authenticated?(password)
end

Leave a Reply

Your email address will not be published. Required fields are marked *