`
sillycat
  • 浏览: 2496076 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Rails Study(9)Associations First Part

阅读更多
Rails Study(9)Associations First Part

1. Why Associations?
Without Associations, we will configure and use the models like this:
class Customer < ActiveRecord::Base
end
class Order < ActiveRecord::Base
end

When we want to create an order
@order = Order.create(:order_date => Time.now, :customer_id => @customer.id)

consider deleting a customer
@orders = Order.find_all_by_customer_id(@customer.id)
@orders.each do |order|
   order.destroy
end
@customer.destroy

With association.
class Customer < ActiveRecord::Base
  has_manyrders, :dependent => :destroy
end

class Order < ActiveRecord::Base
   belongs_to :customer
end

@order = @customer.orders.create(:order_date => Time.now)
@customer.destroy

2. The Types of Associations
belongs_to
has_one
has_many
has_many :through
has_one :through
has_and_belongs_to_many

2.1 The belongs_to Association
Each order can be assigned to exactly one customer.
class Order < ActiveRecord::Base
   belongs_to :customer
end

2.2 The has_one Association
one supplier has only one account.

class Supplier < ActiveRecord::Base
  has_one :account
end

2.3 The has_many Association
You'll often find this association on the "other side" of a belongs_to association.
Customers have orders or not.

class Customer < ActiveRecord::Base
    has_manyrders
end

2.4 The has_many :through Association
Consider a medical practice where patients make appointments to see physicians.
class Physician < ActiveRecord::Base
     has_many :appointments
     has_many :patients, :through => :appointments
end

class Appointment < ActiveRecord::Base
    belongs_to :physician
    belongs_to :patient
end

class Patient < ActiveRecord::Base
   has_many :appointments
   has_many :physicians, :through => :appointments
end

If a document has many sections, and a section has many paragraphs.

class Document < ActiveRecord::Base
   has_many :sections
   has_many :paragraphs, :through => :sections
end

class Section < ActiveRecord::Base
    belongs_to :document
    has_many :paragraphs
end

class Paragraph < ActiveRecord::Base
    belongs_to :section
end

2.5 The has_one :through Association
Each supplier has one account, each account is associated with one account history.
class Supplier < ActiveRecord::Base
    has_one :account
    has_one :account_history, :through => :account
end

class Account < ActiveRecord::Base
   belongs_to :supplier
   has_one :account_history
end

class AccountHistory < ActiveRecord::Base
    belongs_to :account
end

2.6 The has_and_belongs_to_many Association
Application includes assemblies and parts, each assembly having many parts and each part appearing in many assembilies.
class Assembly < ActiveRecord::Base
     has_and_belongs_to_many :parts
end

class Part < ActiveRecord::Base
     has_and_belongs_to_many :assemblies
end

assemblies   ------> assemblies_parts <-----------    parts
id                                    assembliy_id                                 id
name                            part_id                                              part_number

2.7 Choosing Between belongs_to and has_one
It makes more sense to say that a supplier owns an account than that an account owns a supplier.
class Supplier < ActiveRecord::Base
    has_one :account
end

class Account < ActiveRecord::Base
    belongs_to :supplier
end

2.8 Choosing Between has_many :through and has_and_belongs_to_many
The simplest rule of thumb is that you should set up a has_many :through relationship if you need to work with the
relationship model as an independent entity. If there is no need for relationship model, it may be simpler to set up
a has_and_belongs_to_many relationship.

2.9 Polymorphic Associations
You might have a picture model that belongs to either an employee model or a product model.

class Picture < ActiveRecord::Base
    belongs_to :imageable, :polymorphic => true
end

class Employee < ActiveRecord::Base
    has_many :pictures, :as => :imageable
end

class Product < ActiveRecord::Base
    has_many :pictures, :as => :imageable
end

employees   -------> pictures                <---------------------products
id                                    id                                                             id
name                            name                                                     name
                                        imageable_id
                                        imageable_type

The migration class can be:
class CreatePictures < ActiveRecord::Migration
     def self.up
          create_table :pictures do |t|
              t.string :name
              t.integer :imageable_id
              t.string :imageable_type
              t.timestamps
          end
     end
end

class CreatePicture < ActiveRecord::Migration
     def self.up
         create_table :pictures do |t|
            t.string :name
            t.references :imageable, :polymorphic => true
            t.timestamps
         end
     end
end

2.10 Self Joins
Relationships such as between manager and subordinates.
class Employee < ActiveRecord::Base
has_many :subordinates, :class_name => "Employee", :foreign_key => "manager_id"
belongs_to :manager, :class_name => "Employee"
end

retrieve @employee.subordinates @employee.manager

3 Tips, Tricks, and Warnings
3.1 Controlling Caching
customer.orders                       #retrieves orders from the db
customer.orders.size             #uses the cached copy of orders
customer.orders.empty?     #uses the cached copy of orders
customer.orders(true).empty? #discards the cached, goes back to the db

3.2 Avoiding Name Collisions
attributes or connection are bad names for associations.

3.3 Updating the Schema
3.3.1 Creating Foreign Keys for belongs_to Associations
class Order < ActiveRecord::Base
belongs_to :customer
end

class CreateOrders < ActiveRecord::Migration
def self.up
  create_tablerders do |t|
   t.datetimerder_date
   t.string        rder_number
   t.integer      :customer_id
  end
end
end

3.3.2 Creating Join Tables for has_and_belongs_to_many Associations
Creating the assemblies_parts table.

class CreateAssemblyPartJoinTable < ActiveRecord::Migration
def self.up
  create_table :assemblies_parts, :id => false do |t|
   t.integer :assembly_id
   t.integer :part_id
  end
end
end

3.4 Controlling Association Scope
classes in the same module

module MyApplication
module Business
  class Supplier < ActiveRecord::Base
   has_one :account
  end

  class Account < ActiveRecord::Base
   belongs_to :supplier
  end
end
end

module MyApplication
module Business
  class Supplier < ActiveRecord::Base
   has_one :account, :class_name => "MyApplication::Billing::Account"
  end
end

module Billing
  class Account < ActiveRecord::Base
   belongs_to :supplier, :class_name => "MyApplication::Business::Supplier"
  end
end
end

4. snip..

references:
http://guides.rubyonrails.org/association_basics.html
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics