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