class A | class B | Foreign keys | Mapping |
---|---|---|---|
class User has_one :weblog end |
class Weblog belongs_to :user end |
weblogs.user_id | One user maps to zero or one weblog |
class Weblog has_many :posts end |
class Post belongs_to :weblog end |
posts.weblog_id | One weblog maps to zero or more posts |
class Post has_and_belongs_to_many :categories end |
class Category has_and_belongs_to_many :posts end |
categories_posts.post_id categories_posts.category_id | Any number of posts maps to any number of categories |
has_one :credit_card, :dependent => :destroy has_one :credit_card, :dependent => :nullify has_one :last_comment, :class_name => "Comment", :order => "posted_on" has_one :project_manager, :class_name => "Person", :conditions => "role = 'project_manager'" has_one :attachment, :as => :attachable # Polymorphic association
class LineItem < ActiveRecord::Base belongs_to :paid_order, :class_name => 'Order', :foreign_key => 'order_id', :conditions => 'paid_on is not null' belongs_to :product end |
li = LineItem.find(1) li.product = Product.new( :name => 'Programming Ruby Book' ) li.save li.build_product( :name => 'MacBook Pro' ) # invokes Product.new li.create_product( :name => 'SoundsSticks II' ) # build_product + save |
has_many :comments, :order => "posted_on" has_many :comments, :include => :author has_many :people, :class_name => "Person", :conditions => "deleted = 0", :order => "name" has_many :tracks, :order => "position", :dependent => :destroy has_many :comments, :dependent => :nullify has_many :tags, :as => :taggable has_many :subscribers, :through => :subscriptions, :source => :user has_many :subscribers, :class_name => "Person", :finder_sql => 'SELECT DISTINCT people.* ' + 'FROM people p, post_subscriptions ps ' + 'WHERE ps.post_id = #{id} AND ps.person_id = p.id ' + 'ORDER BY p.first_name'
firm.clients # (similar to Clients.find :all, :conditions => "firm_id = #{id}") firm.clients<< firm.clients.delete firm.clients= firm.client_ids firm.client_ids= firm.clients.clear firm.clients.empty? # (similar to firm.clients.size == 0) firm.clients.count firm.clients.find # (similar to Client.find(id, :conditions => "firm_id = #{id}")) firm.clients.build # (similar to Client.new("firm_id" => id)) firm.clients.create # (similar to c = Client.new("firm_id" => id); c.save; c)
blog = User.find(1).weblog blog.posts.count # => 0 blog.posts << Post.new(:title => "Hi, this is my first post!") blog.posts.count # => 1 blog.posts.find(:conditions => ["created_at > ?", 1.minute.ago]) = blog.posts.first
# Requires a join table create_table :categories_posts, :id => false do t.column :category_id, :integer, :null => false t.column :post_id, :integer, :null => false end # Indices for performance add_index :categories_posts, [:category_id, :post_id] add_index :categories_posts, :post_id product = Product.find_by_name "MacBook Pro" category = Category.find_by_name("Laptops") product.categories.count # => 0 category.products.count # => 0 product.categories << category product.categories.count # => 1 category.products.count # => 1
class Article < ActiveRecord::Base has_many :readings has_many :users, :through => :readings, :uniq => true end class User < ActiveRecord::Base has_many :readings has_many :articles, :through => :readings end class Reading < ActiveRecord::Base belongs_to :article belongs_to :user end |
user = User.find(1) article = Article.find(1) Reading.create( :rating => 3, :read_at => Time.now, :article => article, :user => user ) article.users.first == user |
class Article < ActiveRecord::Base has_many :happy_users, :through => :readings, :source => :user, :conditions => "readings.rating >= 4" end article = Article.find(1) article.happy_users
class User < ActiveRecord::Base has_many :articles, :through => :readings do def rated_at_or_above(rating) find :all, :conditions => ['rating >= ?', rating] end end end user = User.find(1) good_articles = user.articles.rated_at_or_above(4)
create_table :images, :force => true do |t| t.string :comment t.string :file_path t.integer :has_image_id t.string :has_image_type end |
class Image < ActiveRecord::Base belongs_to :has_image, :polymorphic => true end class User < ActiveRecord::Base has_one :image, :as => :has_image end class Post < ActiveRecord::Base has_one :image, :as => :has_image end |
create_table :people, :force => true do |t| t.string :type # common attributes t.string :name t.string :email # attributes for type=Customer t.decimal :balance, :precision => 10, :scale => 2 # attributes for type=Employee t.integer :reports_to t.integer :dept # attributes for type=Manager # - none - end
class Person < ActiveRecord::Base end class Customer < Person end class Employee < Person belongs_to :boss, :class_name => "Employee", :foreign_key => :reports_to end class Manager < Employee end
wilma = Manager.create( :name => 'Wilma Flint', :email =>"wilma@here.com", :dept => 23) Customer.create( :name => 'Bert Public', :email => "b@public.net", :balance => 12.45) barney = Employee.new( :name => 'Barney Rub', :email => "barney@here.com", :dept => 23) barney.boss = wilma barney.save! |
manager = Person.find_by_name("Wilma Flint") puts manager.class #=> Manager puts manager.email #=> wilma@here.com puts manager.dept #=> 23 customer = Person.find_by_name("Bert Public") puts customer.class #=> Customer puts customer.email #=> b@public.net puts customer.balance #=> 12.45 |
class Parent < ActiveRecord::Base has_many :children, :order => :position end class Child < ActiveRecord::Base belongs_to :parent acts_as_list :scope => :parent end
parent = Parent.new %w{ One Two Three Four}.each do |name| parent.children.create(:name => name) end parent.save def display_children(parent) # Passing true forces reload puts parent.children(true).map do |child| child.name end.join(", ") end
display_children(parent) #=> One, Two, Three, Four puts parent.children[0].first? #=> true two = parent.children[1] puts two.lower_item.name #=> Three puts two.higher_item.name #=> One parent.children[0].move_lower display_children(parent) #=> Two, One, Three, Four parent.children[2].move_to_top display_children(parent) #=> Three, Two, One, Four parent.children[2].destroy display_children(parent) #=> Three, Two, Four
create_table :categories, :force => true do |t| t.string :name t.integer :parent_id end class Category < ActiveRecord::Base acts_as_tree :order => "name" end
root = Category.create(:name =>"Books") fiction = root.children.create(:name =>"Fiction") non_fiction = root.children.create(:name =>"NonFiction") non_fiction.children.create(:name =>"Computers") non_fiction.children.create(:name =>"Science") non_fiction.children.create(:name =>"ArtHistory") fiction.children.create(:name =>"Mystery") fiction.children.create(:name =>"Romance") fiction.children.create(:name =>"ScienceFiction")
display_children(root) # Fiction, Non Fiction sub_category = root.children.first puts sub_category.children.size #=> 3 display_children(sub_category) #=> Mystery, Romance, Science Fiction non_fiction = root.children.find(:first, :conditions => "name = 'Non Fiction'") display_children(non_fiction) #=> Art History, Computers, Science puts non_fiction.parent.name #=> Books
# Joins posts, authors, comments # in a single select @posts = Post.find(:all, :conditions => "posts.title like '%ruby%'", :include => [:author, :comments]) <% for post in @posts %> <%= post.author.name %>: <%= post.title %> Comments: <% for comment in post.comments %> <%= comment.body %> <% end %> <% end %
create_table :posts do ... t.integer comments_count end class Post < ActiveRecord::Base has_many :comments end class Comment < ActiveRecord::Base belongs_to :post, :counter_cache => true end
class Project # Possible callbacks: :after_add, :before_add, :after_remove, :before_remove has_and_belongs_to_many :developers, :after_add => [:evaluate_velocity, Proc.new { |p, d| p.shipping_date = Time.now}] def evaluate_velocity(developer) ... end end