Örneğin elimizde Customer, Address, Invoice modelleri olan bir proje olsun.

Şu şekilde birbileri ile bağlantıları olsun.

#   app/model/customer.rb
class Customer < ActiveRecord::Base
  has_one :address
  has_many :invoices
end
#   app/model/address.rb
class Address < ActiveRecord::Base
  belongs_to :customer
end
#   app/model/invoice.rb
class Invoice < ActiveRecord::Base
  belongs_to :customer
end

Invoice view’lerinden birinde faturanın sahibinin adını öğrenmek isteyelim, veya faturanın sahibine ait adres tablosundan cadde, şehir.. vs. görmek isteyelim. Yani lafı uzatmadan:

@invoice.customer.name
@invoice.customer.address.street
@invoice.customer.address.city

Okurken bile insan yoruldu değil mi :P.

Law of demeter prensibine göre

  • Her yapı kendisi ile ilgili yapılarla konuşmalı, yabancı yapılarla konuşmamalı
  • Her birim diğer birimler hakkında sınırlı bilgiye sahip olmalı

Olabildiğince az nokta koymalıyız. Peki ama nasıl ?

#   app/model/customer.rb
class Customer < ActiveRecord::Base
  has_one :address
  has_many :invoices

  def street
    address.street
  end

  def city
    address.city
  end
end
#   app/model/address.rb
class Address < ActiveRecord::Base
  belongs_to :customer
end
#   app/model/invoice.rb
class Invoice < ActiveRecord::Base
  belongs_to :customer

  def customer_street
    customer.street
  end

  def customer_city
    customer.city
  end

  def customer_name
    customer.name
  end
end

Peki view’de nasıl kullanılıyor şimdi görelim.

@invoice.customer_name
@invoice.customer_street
@invoice.customer_city

Noktaları, alt tirelerle değiştirdik. Baya anlamlı, kolay okunan kod oldu işimizi görür. Fakat aklınıza malum soru geldi hemen. Modelde böyle elli tane fonksiyon mu yazacağım ben. Tabi ki hayır görelim, oynat uğuorcuumm.

#   app/model/customer.rb
class Customer < ActiveRecord::Base
  has_one :address
  has_many :invoices

  delegate :street,
           :city,
           to: :address
end
#   app/model/address.rb
class Address < ActiveRecord::Base
  belongs_to :customer
end
#   app/model/invoice.rb
class Invoice < ActiveRecord::Base
  belongs_to :customer

  delegate :street,
           :city,
           :name,
           to: :customer,
           prefix: true
end

View’de tekrar görelim.

@invoice.customer_name
@invoice.customer_street
@invoice.customer_city

delegate‘i çaktın mı işlem tamam :P

Kaynaklar

Aşkın Gedik Ruby on Rails Developer