class MyModel < ActiveRecord::Base self.table_name = 'my_legacy_table' self.primary_key = 'my_id' self.pluralize_table_names = false self.table_name_prefix = 'my_app' end
| Operation | Method |
|---|---|
| Create | create, new, save |
| Read | find, find_by_<attr> |
| Update | save, update_attributes |
| Delete | destroy |
user = User.new user.first_name = "Dave" user.last_name = "Thomas" user.save |
<=> |
user = User.new( :first_name => "Dave", :last_name => "Thomas" ) user.save |
user.create( :first_name => "Dave", :last_name => "Thomas" ) |
user = User.new( :first_name => "Dave", :last_name => "Thomas" ) |
|
if user.save # All is ok else # Could not save user end |
begin user.save! rescue ActiveRecord::RecordInvalid => e # Could not save user end |
| MySQL | Ruby Class |
|---|---|
| integer | Fixnum |
| clob, blob, text | String |
| float, double | Float |
| char, varchar | String |
| datetime, time | Time |
# Virtual attributes are attributes that do not correspond
# directly to database columns.
class Song < ActiveRecord::Base
def length=(minutes)
# self[:length] = minutes*60
write_attribute(:length, minutes * 60)
end
def length
# self[:length] / 60
read_attribute(:length) / 60
end
end
class User < ActiveRecord::Base
def language
read_attribute(:language) || "sv"
end
end
user = User.new(:name => "David") # user.name? is equivalent to user.name.present? # If it returns true then the name is not nil and not empty user.name? # => true anonymous = User.new(:name => "") anonymous.name? # => false
User.find(:first) # => First user object User.first # short hand for find(:first) User.find(:last) # => Last user object User.last # short hand for find(:last) User.find(:all) # => Array with all User objects User.all # short hand for find(:all) User.find(3) # => User object with id 3
User.find(:all,
:conditions =>
["first_name = ? and created_at > ?", "David", 1.year.ago])
User.find(:all,
:conditions =>
["first_name = :first_name, last_name = :last_name",
{:first_name => "David", :last_name => "Letterman"}])
User.find(:all,
:conditions => {:first_name => "Jamis", :last_name => "Buck"})
User.find(:all, :conditions => [ "category IN (?)", categories])
Post.merge_conditions(
{:title => 'Lucky Star'},
['rating IN (?)', 1..5]
)
=> "(`posts`.`title` = 'Lucky Star') AND (rating IN (1,2,3,4,5))"
# select * from users limit 1 User.find(:first) <=> User.find(:all, :limit => 1).first # select * from users where id = 1 User.find(1) <=> User.find(:all, :conditions => "users.id = 1").first
# This works User.find(:all, :conditions => ["name like ?", "%" + params[:name] + "%") # This doesn't work User.find(:all, :conditions => ["name like '%?%'", params[:name])
User.find_by_first_name "Peter"
User.find_all_by_last_name "Hanson"
User.find_by_age "20"
User.find_by_last_name("Buck",
:conditions => {:country = "Sweden", :age => 20..30})
User.find_by_first_name_and_last_name "Andreas", "Kviby"
class Article < ActiveRecord::Base
named_scope :approved, :conditions => {:status => 'approved'}
named_scope :since, lambda { |time_ago| { :conditions => ['published_at > ?', time_ago] }}
named_scope :inactive, :conditions => {:active => false} do
def activate
each { |article| article.update_attribute(:active, true) }
end
end
end
Article.approved.since(3.days.ago) # all approved articles in the last three days
Article.inactive.activate # activate all inactive articles
User.exists?(999) # => false
User.find(999) # => raises ActiveRecord::RecordNotFound
User.find_by_id(999) # => nil
User.find(:first, :conditions => {:id => 999}) # => nil
# No 'Summer' tag exists
Tag.find_or_create_by_name("Summer") # equal to Tag.create(:name => "Summer")
# Now the 'Summer' tag does exist
Tag.find_or_create_by_name("Summer") # equal to Tag.find_by_name("Summer")
# No 'Winter' tag exists
winter = Tag.find_or_initialize_by_name("Winter")
winter.new_record? # true
winter.save
order = Order.find(12) order.name = "Bill Gates" order.charge = 10000 order.save! |
<=> |
order = Order.find(13) order.update_attributes!( :name => "Bill Gates", :charge => 10000 ) |
def update_attributes(attributes)
self.attributes = attributes
save
end
def update_attributes!(attributes)
self.attributes = attributes
save!
end
user = User.find_by_name("Dave" )
user.changed? # => false
user.name = "Dave Thomas"
user.changed? # => true
user.changed # => ['name']
user.changes # => {"name"=>["dave", "Dave Thomas"]}
user.name_changed? # => true
user.name_was # => 'Dave'
user.name_change # => ['Dave', 'Dave Thomas']
user.name = 'Bill'
user.name_change # => ['Dave', 'Dave Thomas']
user.save # updates only the name in the db
user.changed? # => false
# SELECT * FROM accounts WHERE (account.`id` = 1) FOR UPDATE account = Account.find(id, :lock => true) account.status = 'disabled' account.save! # Optimistic locking with integer column lock_version in the accounts table: account1 = Account.find(4) account2 = Account.find(4) account1.update_attributes(:status => 'disabled') account2.update_attributes(:status => 'enabled') # => Raises ActiveRecord::StaleObjectError
# Instance method User#destroy User.count # => 5 u = User.find(:first) u.destroy User.count # => 4 |
|
# Class method User.destroy User.count # => 4 User.destroy(2, 3) User.count # => 2 User.exists?(2) # => false |
# Class method User.destroy_all
User.destroy_all("id >= 5")
User.count # => 1
User.destroy_all
User.count # => 0
|
def destroy(id)
if id.is_a?(Array)
id.map { |one_id| destroy(one_id) }
else
find(id).destroy
end
end
def destroy_all(conditions = nil)
find(:all, :conditions => conditions).each do |object|
object.destroy
end
end
# Post.delete_all("person_id = 5 AND (category = 'Something' OR category = 'Else')")
def delete_all(conditions = nil)
sql = "DELETE FROM #{quoted_table_name} "
add_conditions!(sql, conditions, scope(:find))
connection.delete(sql, "#{name} Delete all")
end
# Todo.delete(1)
# Todo.delete([2,3,4])
def delete(id)
delete_all([ "#{connection.quote_column_name(primary_key)} IN (?)", id ])
end
Person.minimum('age')
Person.maximum('age')
Person.sum('age')
Person.count(:conditions => ["age > ?", 25])
Person.average('age')
Person.calculate(:std, :age)
# Post.find_by_sql ["SELECT title FROM posts created_at > ?", start_date]
def find_by_sql(sql)
connection.select_all(sanitize_sql(sql), "#{name} Load").collect! { |record| instantiate(record) }
end
ActiveRecord::Base.connection.execute("delete from users")
ActiveRecord::Base.connection.select_one("select * from users where id = 1")
ActiveRecord::Base.connection.select_all("select * from users")
ActiveRecord::Base.connection.select_value("select name from users where id = 1")
ActiveRecord::Base.connection.select_values("select name from users")
class Person < ActiveRecord::Base
serialize params
end
person = Person.new
person.params = {
:height => 190,
:weight => 80,
:eye_color => 'blue'
}
person.save # Serializes the hash in YAML format in the db
class Aricle < ActiveRecord::Base # Now the body attribute can be accessed with a text method too alias_attribute :text, :body end a = Article.first a.body # => "the body" a.text # => "the body" a.text? # => true a.text = "new body" a.body # => "new body"
class User < ActiveRecord::Base delegate :street, :city, :to => :address end u = User.first u.address.street # => "Fifth Avenue" u.street # => "Fifth Avenue"
class Person < ActiveRecord::Base
def social_security
decrypt_social_security
end
# Memoize the result of the social_security method after its first evaluation.
# Must be placed after the target method definition.
memoize :social_security
end
@person = Person.new
@person.social_security # decrypt_social_security is invoked
@person.social_security # decrypt_social_security is NOT invoked
class Name
attr_reader :first, :initials, :last
def initialize(first, initials, last)
@first = first
@initials = initials
@last = last
end
def to_s
[ @first, @initials, @last ].compact.join(" ")
end
end
|
class Customer < ActiveRecord::Base
composed_of :name,
:class_name => Name,
:mapping =>
[#database ruby
[:first_name, :first],
[:initials, :initials],
[:last_name, :last]
end
|
name = Name.new("Dwight" , "D" , "Eisenhower" )
Customer.create(:credit_limit => 1000, :name => name)
customer = Customer.find(:first)
puts customer.name.first #=> Dwight
puts customer.name.last #=> Eisenhower
puts customer.name.to_s #=> Dwight D Eisenhower
customer.name = Name.new("Harry" , nil, "Truman" )
customer.save
Account.transaction do account1.deposit(100) account2.withdraw(100) end
“ActiveRecord is an example of a leaky abstraction and you need to understand the SQL that it generates to avoid gotchas such as the N+1 problem.”
– Chad Fowler