Reference
Overriding accessors
class Song < ActiveRecord::Base
# Uses an integer of seconds to hold the length of the song
def length=(minutes)
write_attribute(:length, minutes.to_i * 60)
end
def length
read_attribute(:length) / 60
end
end
See: http://api.rubyonrails.org/classes/ActiveRecord/Base.html
Callbacks
- after_create
- after_initialize
- after_validation
- after_save
- after_commit### Serialize
class User < ActiveRecord::Base
serialize :preferences
end
user = User.create(
preferences: {
'background' => 'black',
'display' => 'large'
}
)
You can also specify a class option as the second parameter that’ll raise an exception if a serialized object is retrieved as a descendant of a class not in the hierarchy.
# Only Hash allowed!
class User < ActiveRecord::Base
serialize :preferences, Hash
end
# Reading it raises SerializationTypeMismatch
user = User.create(preferences: %w(one two three))
User.find(user.id).preferences
Other tricks### Where interpolation
where('name = ?', 'John')
where(['name = :name', { name: 'John' }])
Joining
# Basic joins
Student.joins(:schools).where(schools: { type: 'public' })
Student.joins(:schools).where('schools.type' => 'public' )
# Multiple associations
Article.joins(:category, :comments)
# Nested associations
Article.joins(comments: :guest)
# SQL
Author.joins(
'INNER JOIN posts ' +
'ON posts.author_id = authors.id ' +
'AND posts.published = "t"'
)
Mass updates
# Updates person id 15
Person.update 15, name: "John", age: 24
Person.update [1,2], [{name: "John"}, {name: "foo"}]
Callbacks
- Guides: callbacks ### Errors
record.errors.valid? # → false
record.errors # → { :name => ["can't be blank"] }
record.errors.messages # → { :name => ["can't be blank"] }
record.errors[:name].any?
Other API
Custom validations
class Person < ActiveRecord::Base
validate :foo_cant_be_nil
def foo_cant_be_nil
errors.add(:foo, 'cant be nil') if foo.nil?
end
end
Validation
class Person < ActiveRecord::Base
# Presence
validates :name, presence: true
# Acceptance
validates :terms, acceptance: true
# Confirm
validates :email, confirmation: true
# Unique
validates :slug, uniqueness: true
validates :slug, uniqueness: { case_sensitive: false }
validates :holiday, uniqueness: { scope: :year, message: 'yearly only' }
# Format
validates :code, format: /regex/
validates :code, format: { with: /regex/ }
# Length
validates :name, length: { minimum: 2 }
validates :bio, length: { maximum: 500 }
validates :password, length: { in: => 6..20 }
validates :number, length: { is: => 6 }
# Include/exclude
validates :gender, inclusion: %w(male female)
validates :gender, inclusion: { in: %w(male female) }
validates :lol, exclusion: %w(xyz)
# Numeric
validates :points, numericality: true
validates :played, numericality: { only_integer: true }
# ... greater_than, greater_than_or_equal_to,
# ... less_than, less_than_or_equal_to
# ... odd, even, equal_to
# Validate the associated records to ensure they're valid as well
has_many :books
validates_associated :books
# Length (full options)
validates :content, length: {
minimum: 300,
maximum: 400,
tokenizer: lambda { |str| str.scan(/\w+/) },
too_short: "must have at least %{count} words",
too_long: "must have at most %{count} words" }
# Multiple
validates :login, :email, presence: true
# Conditional
validates :description, presence: true, if: :published?
validates :description, presence: true, if: lambda { |obj| .. }
validates :title, presence: true, on: :save # :save | :create | :update
end
Polymorphic associations
class Post
has_many :attachments, as: :parent
end
class Image
belongs_to :parent, polymorphic: true
end
And in migrations:
create_table :images do |t|
t.references :post, polymorphic: true
end
Top comments (0)