首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网络技术 > 网络基础 >

Rails Study(九)Associations First Part

2012-10-31 
Rails Study(9)Associations First PartRails Study(9)Associations First Part1. Why Associations?Witho

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

热点排行