SlideShare a Scribd company logo
composed_of
flat_data.convert_to(rich_ruby_object)



   most material from Chad Fowler’s “Rails Recipes”, pragprog.com
The Needs
• You have a simple model attribute that
  needs additional behavior but don’t want to
  create an additional ActiveRecord model
• You need to store structured data in the
  same table as your model but treat it as a
  first-class, normalized object
composed_of
class SomeModel < ActiveRecord::Base
  composed_of :some_attribute,
    :class_name => 'SomeSpecialClass',
    :mapping => [%w(model_attr_name special_class_attr)]
end

“Add some_attribute, composed of SomeSpecialClass,
and map SomeModel’s model_attr_name field to
special_class_attr.”
CourseRecord class
class CourseRecord < ActiveRecord::Base
  composed_of :grade,
    :mapping => %w(letter_grade letter_grade)
end
Grade class
class Grade
  attr_accessor :letter_grade

  def initialize(letter_grade)
      @letter_grade = letter_grade
  end
end
class Grade
                             include Comparable
                             attr_accessor :letter_grade
 course_records
                            def initialize(letter_grade)
                               @letter_grade = letter_grade
id
                            end
course_id
                          end
student_id
letter_grade



  class CourseRecord < ActiveRecord::Base
    composed_of :grade,
      :mapping => %w(letter_grade letter_grade)
  end
Things to remember


• include Comparable and define <=> in
  order to compare composed_of classes
class Grade
                       Grade class
   include Comparable

  SORT_ORDER = ["F", "D", "D", "B", "A"].inject({}) {|h, letter|
    h.update "#{letter}-" => h.size
    h.update letter => h.size
    h.update "#{letter}+" => h.size
  }

  def <=>(other)
    SORT_ORDER[letter_grade.downcase] <=>
    SORT_ORDER[other.letter_grade.downcase]
  end
end
Things to remember

• composed_of objects are value objects and
  are immutable!
• Create a new object to change the AR
  model’s composed_of attr
Structured Data
    person        class Person < ActiveRecord::Base
id
first_name
                    composed_of :address, :mapping =>
last_name                 [ %w(address_street street),
address_street
address_city                 %w(address_city city),
address_state                %w(address_state state),
address_country
email                        %w(address_country country) ]
                  end
class Address     Address class
  attr_accessor :street, :city, :state, :country

  def initialize(street, city, state, country)
       @street = street
       @city = city
       @state = state
       @country = country
 end

 def full_address
   “#{street} #{city}, #{state} #{country}”
 end
end
The Results
•   Keep your Models DRY and put the responsibilities
    and behaviors where they belong

•   Reuse the composed_of models instead of
    repeating methods in multiple classes

•   Store structured data flatly but treat it as a first-
    class Ruby object

•   Don’t garbage-up your models with lots of
    “formatting” methods like :full_address

More Related Content

Similar to Composed of (20)

PDF
Ruby on Rails at PROMPT ISEL '11
Pedro Cunha
 
PPT
SQL.ppt
RickyLidar
 
PPT
Framework
Nguyen Linh
 
PPT
Intro to Rails ActiveRecord
Mark Menard
 
PDF
Attributes Unwrapped: Lessons under the surface of active record
.toster
 
PDF
Rails <form> Chronicle
Kyosuke MOROHASHI
 
PDF
Rapid Prototyping with PEAR
Markus Wolff
 
PDF
Implementation of EAV pattern for ActiveRecord models
Kostyantyn Stepanyuk
 
PDF
Business Rules with Brick
brian d foy
 
KEY
Building Web Service Clients with ActiveModel
pauldix
 
KEY
Building Web Service Clients with ActiveModel
pauldix
 
PDF
Where's My SQL? Designing Databases with ActiveRecord Migrations
Eleanor McHugh
 
KEY
Why ruby
rstankov
 
PDF
WTF Oriented Programming, com Fabio Akita
iMasters
 
PDF
D8 Form api
Samuel Solís Fuentes
 
PPT
UNIT 2 Structured query language commands
Bhakti Pawar
 
PDF
model.search: customize your own search logic
Tse-Ching Ho
 
KEY
Getting started with Rails (4), Season 2
RORLAB
 
KEY
Ruby/Rails
rstankov
 
Ruby on Rails at PROMPT ISEL '11
Pedro Cunha
 
SQL.ppt
RickyLidar
 
Framework
Nguyen Linh
 
Intro to Rails ActiveRecord
Mark Menard
 
Attributes Unwrapped: Lessons under the surface of active record
.toster
 
Rails <form> Chronicle
Kyosuke MOROHASHI
 
Rapid Prototyping with PEAR
Markus Wolff
 
Implementation of EAV pattern for ActiveRecord models
Kostyantyn Stepanyuk
 
Business Rules with Brick
brian d foy
 
Building Web Service Clients with ActiveModel
pauldix
 
Building Web Service Clients with ActiveModel
pauldix
 
Where's My SQL? Designing Databases with ActiveRecord Migrations
Eleanor McHugh
 
Why ruby
rstankov
 
WTF Oriented Programming, com Fabio Akita
iMasters
 
UNIT 2 Structured query language commands
Bhakti Pawar
 
model.search: customize your own search logic
Tse-Ching Ho
 
Getting started with Rails (4), Season 2
RORLAB
 
Ruby/Rails
rstankov
 

Recently uploaded (20)

PDF
ornament making and its material used for.pdf
departmentofcdft
 
PDF
Line Sizing presentation about pipe sizes
anniebuzzfeed
 
PDF
mlbrolllist2024-25 (1)ygrude4ferfssrddde
rishabh1chaurasia4
 
PDF
Hossain Kamyab on Mixing and Matching Furniture.pdf
Hossain Kamyab
 
DOCX
Amplopxxxxxxxxxvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
Lm Hardin 'Idin'
 
DOCX
BusinessPlan_redesignedf word format .docx
MohammadMaqatif
 
PPTX
Modern_Dhaka_Apartment_Interior_Design.pptx
hasansarkeraidt
 
PPT
Strengthening of an existing reinforced concrete structure.ppt
erdarshanpshah
 
PPT
UNIT- 2 CARBON FOOT PRINT.ppt yvvuvvvvvvyvy
sriram270905
 
PPTX
Web Design: Enhancing User Experience & Brand Value
ashokmakwana0303
 
PDF
Ggggggggggggggggggggroup singing.pdf.pdf
nadifalrazi3
 
PPTX
DISS-Group-5_110345.pptx Basic Concepts of the major social science
mattygido
 
PPTX
Lesson 2 Application of Induced current.pptx
hananmahjoob18
 
PPTX
VERTICAL TRANSPORTATION SYSTEMS.pptxhvcvcvvdh
jp0718076
 
PPTX
confluence of tradition in modernity- design approaches and design thinking
madhuvidya7
 
PPTX
Time_Management_Presenuuuuuuutation.pptx
Rajni Goyal
 
PPTX
Style and aesthetic about fashion lifestyle
Khushi Bera
 
PPTX
CHANDIGARH Architecture Design and Planning
FaizSaifi3
 
PPTX
lesson 02- Mang- Ruklani Wickramasinghe (2).pptx
dinalisanjala002
 
PPTX
designing in footwear- exploring the art and science behind shoe design
madhuvidya7
 
ornament making and its material used for.pdf
departmentofcdft
 
Line Sizing presentation about pipe sizes
anniebuzzfeed
 
mlbrolllist2024-25 (1)ygrude4ferfssrddde
rishabh1chaurasia4
 
Hossain Kamyab on Mixing and Matching Furniture.pdf
Hossain Kamyab
 
Amplopxxxxxxxxxvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
Lm Hardin 'Idin'
 
BusinessPlan_redesignedf word format .docx
MohammadMaqatif
 
Modern_Dhaka_Apartment_Interior_Design.pptx
hasansarkeraidt
 
Strengthening of an existing reinforced concrete structure.ppt
erdarshanpshah
 
UNIT- 2 CARBON FOOT PRINT.ppt yvvuvvvvvvyvy
sriram270905
 
Web Design: Enhancing User Experience & Brand Value
ashokmakwana0303
 
Ggggggggggggggggggggroup singing.pdf.pdf
nadifalrazi3
 
DISS-Group-5_110345.pptx Basic Concepts of the major social science
mattygido
 
Lesson 2 Application of Induced current.pptx
hananmahjoob18
 
VERTICAL TRANSPORTATION SYSTEMS.pptxhvcvcvvdh
jp0718076
 
confluence of tradition in modernity- design approaches and design thinking
madhuvidya7
 
Time_Management_Presenuuuuuuutation.pptx
Rajni Goyal
 
Style and aesthetic about fashion lifestyle
Khushi Bera
 
CHANDIGARH Architecture Design and Planning
FaizSaifi3
 
lesson 02- Mang- Ruklani Wickramasinghe (2).pptx
dinalisanjala002
 
designing in footwear- exploring the art and science behind shoe design
madhuvidya7
 
Ad

Composed of

  • 1. composed_of flat_data.convert_to(rich_ruby_object) most material from Chad Fowler’s “Rails Recipes”, pragprog.com
  • 2. The Needs • You have a simple model attribute that needs additional behavior but don’t want to create an additional ActiveRecord model • You need to store structured data in the same table as your model but treat it as a first-class, normalized object
  • 3. composed_of class SomeModel < ActiveRecord::Base composed_of :some_attribute, :class_name => 'SomeSpecialClass', :mapping => [%w(model_attr_name special_class_attr)] end “Add some_attribute, composed of SomeSpecialClass, and map SomeModel’s model_attr_name field to special_class_attr.”
  • 4. CourseRecord class class CourseRecord < ActiveRecord::Base composed_of :grade, :mapping => %w(letter_grade letter_grade) end
  • 5. Grade class class Grade attr_accessor :letter_grade def initialize(letter_grade) @letter_grade = letter_grade end end
  • 6. class Grade include Comparable attr_accessor :letter_grade course_records def initialize(letter_grade) @letter_grade = letter_grade id end course_id end student_id letter_grade class CourseRecord < ActiveRecord::Base composed_of :grade, :mapping => %w(letter_grade letter_grade) end
  • 7. Things to remember • include Comparable and define <=> in order to compare composed_of classes
  • 8. class Grade Grade class include Comparable SORT_ORDER = ["F", "D", "D", "B", "A"].inject({}) {|h, letter| h.update "#{letter}-" => h.size h.update letter => h.size h.update "#{letter}+" => h.size } def <=>(other) SORT_ORDER[letter_grade.downcase] <=> SORT_ORDER[other.letter_grade.downcase] end end
  • 9. Things to remember • composed_of objects are value objects and are immutable! • Create a new object to change the AR model’s composed_of attr
  • 10. Structured Data person class Person < ActiveRecord::Base id first_name composed_of :address, :mapping => last_name [ %w(address_street street), address_street address_city %w(address_city city), address_state %w(address_state state), address_country email %w(address_country country) ] end
  • 11. class Address Address class attr_accessor :street, :city, :state, :country def initialize(street, city, state, country) @street = street @city = city @state = state @country = country end def full_address “#{street} #{city}, #{state} #{country}” end end
  • 12. The Results • Keep your Models DRY and put the responsibilities and behaviors where they belong • Reuse the composed_of models instead of repeating methods in multiple classes • Store structured data flatly but treat it as a first- class Ruby object • Don’t garbage-up your models with lots of “formatting” methods like :full_address

Editor's Notes