Pragmatic Patterns of Ruby on Rails - Ruby Kaigi2009
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Pragmatic Patterns of Ruby on Rails - Ruby Kaigi2009

on

  • 10,348 views

 

Statistics

Views

Total Views
10,348
Views on SlideShare
9,692
Embed Views
656

Actions

Likes
18
Downloads
87
Comments
0

12 Embeds 656

http://rails.pixnet.net 431
http://ko.meadowy.net 177
http://d.hatena.ne.jp 19
https://si0.twimg.com 9
http://www.slideshare.net 7
http://lifeast.net 3
https://twimg0-a.akamaihd.net 3
http://s.deeeki.com 3
http://static.slideshare.net 1
https://twitter.com 1
http://theoldreader.com 1
http://kaorumori.iotaworks.jp 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Pragmatic Patterns of Ruby on Rails - Ruby Kaigi2009 Presentation Transcript

  • 1. Pragmatic Patterns of Ruby on Rails Yasuko OHBA( )
  • 2. what I do • developer of Rails applications • • Everyleaf Corporation
  • 3. sponsor booth • first time to be a sponsor • we serve candies • you can play ‘Romantic Ruby’ !
  • 4. my products • home accounting web service http://www.kozuchi.net • http://github.com/everyleaf/kozuchi/ tree
  • 5. personal message
  • 6. I started programming when I was 14 years old
  • 7. school for girls
  • 8. I was alone
  • 9. got the job
  • 10. find similar people
  • 11. however
  • 12. ‘enterprise’
  • 13. only activities inside the company
  • 14. other things mount up
  • 15. I was lost
  • 16. want to write codes
  • 17. that’s when..
  • 18. Ruby was given
  • 19. life becomes happier
  • 20. Ruby for enterprises
  • 21. the way to live happily writing codes
  • 22. And...
  • 23. great communities
  • 24. many friends
  • 25. thank you !!
  • 26. today’s presentation
  • 27. coding patterns with Ruby on Rails
  • 28. the target • large & complicated applications • team
  • 29. problems of large applications • different coding styles • nasty parts made
  • 30. becomes harder to maintenance
  • 31. keep your codes nice
  • 32. what is the ‘nice code’? • good design • easy to understand • easy to find something wrong
  • 33. coding patterns work fine • make and share coding patterns • add some DSL (not too much)
  • 34. efficient, of course
  • 35. what I won’t say • how to get the best performance • ActiveRecord’s alternatives
  • 36. ActiveRecord
  • 37. frankly speaking,
  • 38. I love ActiveRecord
  • 39. because
  • 40. OOP
  • 41. still able to maintenance when it gets complicated
  • 42. pragmatic
  • 43. the heart of RoR
  • 44. many AR features in this presentation
  • 45. examples
  • 46. show permitted data
  • 47. find starts from an AR object
  • 48. find a note by id /note/3 def show @note = Note.find(params[:id]) end
  • 49. find a note of the current user /note/3 @note = Note.find_by_id_and_user_id( params[:id], current_user.id) raise ActiveRecord::RecordNotFound unless @note
  • 50. /note/3 @note = Note.written_by( curret_user.id).find(params[:id])
  • 51. hard to notice the luck of condition! @note = Note.find(params[:id]) @note = Note.find_by_id_and_user_id( params[:id], current_user.id) @note = Note.written_by( current_user).find(params[:id])
  • 52. so,
  • 53. find starts from an AR object
  • 54. starts from an object def show @note = current_user.notes.find( params[:id]) end
  • 55. use the association def show @note = current_user.notes.find( params[:id]) end
  • 56. association class User < ActiveRecord::Base has_many :notes end
  • 57. easy to notice problems @note = current_user.notes.find( params[:id]) @note = Note.find(params[:id])
  • 58. easy to see who can access
  • 59. who can access @note = current_user.notes.find( params[:id])
  • 60. filters to find the starting AR object
  • 61. with the previous pattern
  • 62. most actions will use the AR object
  • 63. example; CRUD of the specified group’s notes
  • 64. • URL • /groups/15/notes • /groups/15/notes/3
  • 65. • Note has group_id class Note < ActiveRecord::Base belongs_to :group end class Group < ActiveRecord::Base has_many :notes end
  • 66. def index @group = Group.find(params[:group_id]) @notes = @group.notes.paginate(:page => params[:page]) end def show @group = Group.find(params[:group_id]) @note = @group.notes.find(params[:id]) end
  • 67. the duplicated line @group = Group.find(params[:group_id])
  • 68. write that line in a filter
  • 69. what’s the filter? • the separated logic which would be called around action • declarative
  • 70. find the group in a filter class GroupNotesController < ApplicationController before_filter :find_group .......actions ...... private def find_group @group = Group.find(params[:group_id]) end end
  • 71. DRY before_filter :find_group def index @notes = @group.notes.paginate(:page => params[:page]) end def show @note = @group.notes.find(params[:id]) end
  • 72. easy to change access control
  • 73. example; change to allow access to members only def find_group @group = current_user.groups.find( params[:group_id] end
  • 74. other merits
  • 75. secure
  • 76. safe if it starts from @group def index @notes = @group.notes.paginate(:page => params[:page]) end def show @note = @group.notes.find(params[:id]) end
  • 77. filter urges developers to use @group
  • 78. and
  • 79. readable
  • 80. you can understand the controller’s summary from name and filters
  • 81. understand the summary quickly class GroupNotesController < ApplicationController before_filter :find_group
  • 82. the points • a good controller name • readable filters
  • 83. complicated business logics
  • 84. want to write business logics in models
  • 85. because
  • 86. merits of writing business logics in models • easy to test • easy to reuse • readable, easy to find the target codes
  • 87. however
  • 88. ‘how’ matters a lot
  • 89. a bad example class MyModel < ActiveRecord::Base def do_create(params) .... def do_destroy(params) ... end
  • 90. why is it bad ? • it breaks MVC • hard to reuse
  • 91. now
  • 92. let’s move codes from controller to model in good way
  • 93. move the logic branching on parameters from C to M
  • 94. branching on parameters def update @note.attributes = params[:note] @tags = params[:auto_tagging] == '1' ? generate_tags(@note) : [] # do saving and tagging ... end
  • 95. often written in controller
  • 96. to move to model
  • 97. add an attribute for branching to the model
  • 98. the condition params[:auto_tagging] == '1'
  • 99. as an attribute of the model class Note < ActiveRecord::Base attr_accessor :auto_tagging end
  • 100. change parameters structure { :note => {.....}, :auto_tagging => '1' } { :note => { ....., :auto_tagging => '1' }}
  • 101. change the view for it <%= check_box_tag :auto_tagging %> <% form_for :note, ... do |f |%> <%= f.check_box :auto_tagging %> <% end %>
  • 102. now it’s in params[:note] def update @note.attributes = params[:note] if params[:auto_tagging] == '1' generate_tags(@note) end .....
  • 103. can branch in the model class Note < ActiveRecord::Base .... if auto_tagging ... end end
  • 104. finished to move branching
  • 105. move generate_tags next
  • 106. move the logic processing other models from C to M
  • 107. the logic processing other models def update generate_tags(@note) end private def generate_tags(note) tags = Tag.extract(note.body) note.tag_list = tags.join(',') end
  • 108. also often written in controller
  • 109. put it into model’s callback class Note < ActiveRecord::Base before_save :generate_taggings private def generate_taggings return unless auto_tagging tags = Tag.extract(body) self.tag_list = tags.join(',') end end
  • 110. what’s the model’s callback? • methods called before/after save or destroy
  • 111. Rails Model You normal method call save (validation) before_save do saving after_save
  • 112. self-directive models
  • 113. now we’ve done it ! • easy to test • easy to reuse • readable, easy to find the target codes
  • 114. other patterns • multi levels for validation • design & coding policy for STI • use owner object’s attributes in association • how to make routes.rb a little readable
  • 115. the last topic
  • 116. how to find coding patterns
  • 117. in my case
  • 118. try to choose the most natural style for RoR
  • 119. what is the most natural way in Ruby on Rails?
  • 120. 1. OOP
  • 121. express business logics as models
  • 122. always think who should do that job
  • 123. Note or User ? @note = Note.find_by_id_and_user_id( params[:id], current_user.id) @note = current_user.notes.find( params[:id])
  • 124. you can’t always decide it from tables
  • 125. decide it in objects world
  • 126. 2. follow the principles of RoR
  • 127. principles of RoR • DRY • CoC • RESTful
  • 128. accept RESTful in Ruby on Rails
  • 129. how to design controllers ?
  • 130. one controller for a type of resources
  • 131. what’s the resources?
  • 132. you can find it in URL /companies/everyleaf/notes/3
  • 133. design of controllers
  • 134. starts from design of URLs
  • 135. roughly speaking,
  • 136. Model Class 1 1..* Resource
  • 137. the point is...
  • 138. one controller should provide one resource type’s CRUD
  • 139. might have been derailed class BlogsController < ApplicationController def create_comment end def comments end def destroy_comment ...
  • 140. one more
  • 141. write codes in model’s standard flows
  • 142. standard flows • find • new → save (create) • find → save (update) • find → destroy
  • 143. inside of a flow
  • 144. new attribute = before_ build validation before_ after_ validation save validation creation after_save
  • 145. write codes in appropriate place
  • 146. where, what new attribute = before_ build validation before_ after_ validation save validation creation after_save
  • 147. try to choose the most natural style for RoR
  • 148. don’t go too far from the basic styles
  • 149. because
  • 150. it’s normal to Rails programmers
  • 151. easy to read for everyone
  • 152. for that purpose
  • 153. use Ruby’s flexibility
  • 154. summary
  • 155. in developing large & complicated application
  • 156. it’s important to keep codes nice
  • 157. for that purpose
  • 158. be aware of coding patterns, and share them
  • 159. coding patterns fitting Ruby on Rails
  • 160. make source codes easy to read for general developers
  • 161. it means easy to maintain
  • 162. thank you !