rubyenrails2007 - dr nic williams - diy syntax
DESCRIPTION
Many features of rails give you beautiful syntax - here's some ideas to create your ownTRANSCRIPT
![Page 1: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/1.jpg)
Dr Nicdrnicwilliams.com
DIY Syntax
![Page 2: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/2.jpg)
$ irb>> $KCODE = "u" >> "\303\274"=> "ü"
![Page 3: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/3.jpg)
Isn’t this nicer?
>> U00FC=> "ü"
![Page 4: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/4.jpg)
$ sudo gem install charesc$ irb>> $KCODE = "u" >> require 'rubygems'>> require 'charesc'>> "charesc is made by Martin D#{U00FC}rst"=> "charesc is made by Martin Dürst">> U00FC=> "ü">> "\303\274"=> "ü"
charesc
![Page 5: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/5.jpg)
ActiveRecords
SELECT * FROM conferences WHERE (start_date > '2007-06-07')
# But, much nicer is...
![Page 6: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/6.jpg)
ActiveRecords
SELECT * FROM conferences WHERE (start_date > '2007-06-07')
# But, much nicer is...
Conference.find(:all, :conditions => [‘start_date > ?’,Date.today])
![Page 7: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/7.jpg)
Active RecordsSELECT conferences."id" AS t0_r0,
conferences."name" AS t0_r2, ..., conference_sessions."id" AS t1_r0, conference_sessions."conference_id" AS t1_r1, ...
FROM conferences LEFT OUTER JOIN conference_sessions ON conference_sessions.conference_id = conferences.id WHERE (start_date < '2007-05-26')
# But, definitely easier and nicer is...
![Page 8: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/8.jpg)
Active RecordsSELECT conferences."id" AS t0_r0,
conferences."name" AS t0_r2, ..., conference_sessions."id" AS t1_r0, conference_sessions."conference_id" AS t1_r1, ...
FROM conferences LEFT OUTER JOIN conference_sessions ON conference_sessions.conference_id = conferences.id WHERE (start_date < '2007-05-26')
# But, definitely easier and nicer is...
Conference.find(:all, :conditions => ['start_date < ?', Date.today], :include => :conference_sessions)
![Page 9: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/9.jpg)
ActiveRecords - no SQL ... + marshalling to objects
SexySyntax
![Page 10: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/10.jpg)
SexySyntax
Convenient Code
![Page 11: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/11.jpg)
Schemascreate_table :conferences do |t| t.fkey :user t.string :name, :limit => 50 t.text :description t.date :start_date, :end_date t.auto_datesend
# instead of...
I can never remember SQL syntax
![Page 12: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/12.jpg)
Schemascreate_table :conferences do |t| t.fkey :user t.string :name, :limit => 50 t.text :description t.date :start_date, :end_date t.auto_datesend
# instead of...
Look up SQL onI can never remember SQL syntax
![Page 13: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/13.jpg)
CompositePrimary Keys
ProductHistory.find(:first, :conditions => ['id = ? and start_date = ?', 56, Date.new(2000,5,5)])
# rather...
What about Ruby syntax improving on other Ruby syntax?
![Page 14: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/14.jpg)
CompositePrimary Keys
ProductHistory.find(:first, :conditions => ['id = ? and start_date = ?', 56, Date.new(2000,5,5)])
# rather...
What about Ruby syntax improving on other Ruby syntax?
ProductHistory.find(56, Date.new(2000,5,5))
class ProductHistory < ActiveRecord::Base set_primary_keys :id, :start_dateend
![Page 15: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/15.jpg)
What’s this do? #1Nice syntax can quickly tell you want the code will does
@user.conference_sessions_for(@conference)
![Page 16: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/16.jpg)
What’s this do? #1Nice syntax can quickly tell you want the code will does
@user.conference_sessions_for(@conference)# Returns all ConferenceSessions# for a user at a conference
![Page 17: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/17.jpg)
What’s this do? #2
@conference_attendees.map_id_and_login_and_full_name
![Page 18: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/18.jpg)
What’s this do? #2
@conference_attendees.map_id_and_login_and_full_name
# map {|att| [att.id, att.login, att.full_name]}
![Page 19: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/19.jpg)
User.find(params[:id])
What’s this do? #3
![Page 20: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/20.jpg)
User.find(params[:id])
What’s this do? #3
@to_user = @target_db::User.find(params[:id])
![Page 21: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/21.jpg)
User.find(params[:id])
What’s this do? #3
@to_user = @target_db::User.find(params[:id])@to_user.update(@from_db::User.find(params[:id]))
![Page 22: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/22.jpg)
User.find(params[:id])
What’s this do? #3
@to_user = @target_db::User.find(params[:id])
# Copies a User from one database to another
# see Magic Multi-Connection# http://magicmodels.rubyforge.org
@to_user.update(@from_db::User.find(params[:id]))
![Page 23: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/23.jpg)
Let’s see how they work...
![Page 24: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/24.jpg)
What’s this do? #1Nice syntax can quickly tell you want the code will does
@user.conference_sessions_for(@conference)
![Page 25: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/25.jpg)
What’s this do? #1Nice syntax can quickly tell you want the code will does
@user.conference_sessions_for(@conference)# Returns all ConferenceSessions# for a user at a conference
![Page 26: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/26.jpg)
class User < ActiveRecord::Base has_many :conference_sessions
def conference_sessions_for(conference) conference_sessions.find(:all, :conditions => ['conference_id = ?', conference]) endend
What’s this do? #1
No meta-magic, but it gives nice syntax
![Page 27: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/27.jpg)
What’s this do? #2
@attendees.map_by_id_and_login_and_full_name
# map {|att| [att.id, att.login, att.full_name]}
![Page 28: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/28.jpg)
@users = User.find(:all)@users.map {|user| user.login} # => ['drnic', 'topfunky', 'dhh']
Cute ways to use #map
![Page 29: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/29.jpg)
@users = User.find(:all)@users.map {|user| user.login} # => ['drnic', 'topfunky', 'dhh']
Cute ways to use #map
@users.map &:login# => ['drnic', 'topfunky', 'dhh']
![Page 30: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/30.jpg)
@users = User.find(:all)@users.map {|user| user.login} # => ['drnic', 'topfunky', 'dhh']
Cute ways to use #map
@users.map &:login# => ['drnic', 'topfunky', 'dhh']
# but it gets ugly when you chain them...
@users.map(&:login).map(&:size) # => [5, 8, 3]
![Page 31: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/31.jpg)
# So, instead [email protected](&:login).map(&:size)
# We might [email protected]_login.map_size
Cute ways to use #map
![Page 32: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/32.jpg)
def method_missing(method_id, *arguments) pattern = /^find_(all_by|by)_([_a-zA-Z]\w*)$/ if match = pattern.match(method_id.to_s) finder = determine_finder(match)
# from active_record/base.rb, line 1190
Remember find_by_xxx ?
![Page 33: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/33.jpg)
def method_missing(method, *args, &block) pattern = /(map|select|...)_by_([\w\_]+\??)/ if (match = method.match(pattern)) iterator, callmethod = match[1], match[2]
# changed ‘find’ to ‘map’ # or select, reject, each, collect...
Dissecting the request
![Page 34: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/34.jpg)
# continued...iterator, callmethod = match[1], match[2]self.send(iterator) {|obj| obj.send callmethod }
# @array.map_by_foo# callmethod => ‘foo’# #foo invoked on each element of Array
Iterating the request
![Page 35: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/35.jpg)
# continued...iterator, callmethod = match[1], match[2]callmethods = callmethod.split('_and_')callmethods.map do |callmethod| self.send(iterator) {|obj| obj.send callmethod }end
# @array.map_by_foo_and_bar# callmethods => [‘foo’, ‘bar’]# #foo and #bar invoked on each element of Array
Iterating many callmethods
![Page 36: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/36.jpg)
# for complete source:
$ gem install map_by_method$ mate $RUBYGEMS_PATH/map_by_method-0.6.0/lib/map_by_method.rb
map_by_method gem
![Page 37: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/37.jpg)
# for complete source:
$ gem install map_by_method$ mate $RUBYGEMS_PATH/map_by_method-0.6.0/lib/map_by_method.rb
map_by_method gem
# add the following to your ~/.irbrcrequire 'map_by_method'
![Page 38: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/38.jpg)
User.find(params[:id])
What’s this do? #3
![Page 39: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/39.jpg)
User.find(params[:id])
What’s this do? #3
@to_user = @target_db::User.find(params[:id])
![Page 40: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/40.jpg)
User.find(params[:id])
What’s this do? #3
@to_user = @target_db::User.find(params[:id])@to_user.update(@from_db::User.find(params[:id]))
![Page 41: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/41.jpg)
User.find(params[:id])
What’s this do? #3
@to_user = @target_db::User.find(params[:id])
# Copies a User from one database to another
# see Magic Multi-Connection# http://magicmodels.rubyforge.org
@to_user.update(@from_db::User.find(params[:id]))
![Page 42: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/42.jpg)
MagicMulti-Connections
@db::User.find(params[:id])
![Page 43: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/43.jpg)
@db::User.find(params[:id])
# but I would have preferred...
User.find(params[:id]).from_db(@db)
MMC - alternate ideas
![Page 44: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/44.jpg)
@db::User.find(params[:id])
# but I would have preferred...
User.find(params[:id]).from_db(@db)
MMC - alternate ideas
# but we’d need FindProxies # like AssociationProxies
![Page 45: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/45.jpg)
But what does this mean?
@db::User
![Page 46: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/46.jpg)
class creator helperclass Module def create_class(class_name, superclass = Object, &block) klass = Class.new superclass, &block self.const_set class_name, klass endend
>> module Connection; end>> Connection.create_class 'User'=> Connection::User
![Page 47: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/47.jpg)
class creator helperclass Module def create_class(class_name, superclass = Object, &block) klass = Class.new superclass, &block self.const_set class_name, klass endend
>> module Connection; end>> Connection.create_class 'User'=> Connection::User
@db::User
![Page 48: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/48.jpg)
But...the class...“when to create it?”
When you ask for it!
![Page 49: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/49.jpg)
const_missing
class Module alias :old_const_missing :const_missing
def const_missing(const_id) return old_const_missing(const_id) rescue nil target_class = "::\#{const_id}".constantize rescue nil raise NameError.new("bad constant \#{const_id}") unless target_class create_class(const_id, target_class) endend
![Page 50: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/50.jpg)
const_missing
class Module alias :old_const_missing :const_missing
def const_missing(const_id) return old_const_missing(const_id) rescue nil target_class = "::\#{const_id}".constantize rescue nil raise NameError.new("bad constant \#{const_id}") unless target_class create_class(const_id, target_class) endend
magic multi-connections
![Page 51: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/51.jpg)
Picks up root classesclass Person; end
module Remote establish_connection :otherend
>> Remote::Person.superclass=> Person
![Page 52: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/52.jpg)
class Module def const_missing(const_id) return old_const_missing(class_id) rescue nil table_name = DrNicMagicModels::Schema.models[const_id] raise NameError.new("bad constant #{const_id}") unless table_name create_class(class_id, ActiveRecord::Base) do set_table_name table_name end endend
const_missing
“Does the class name match to a table name?”
![Page 53: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/53.jpg)
class Module def const_missing(const_id) return old_const_missing(class_id) rescue nil table_name = DrNicMagicModels::Schema.models[const_id] raise NameError.new("bad constant #{const_id}") unless table_name create_class(class_id, ActiveRecord::Base) do set_table_name table_name end endend
const_missing
dr nic’s magic models
“Does the class name match to a table name?”
![Page 54: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/54.jpg)
const_missing
>> U00FC=> "ü"
![Page 55: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/55.jpg)
const_missing
def const_missing(const) if const.to_s =~ /^((U( [0-9ABCEF][0-9A-F]{3} # general BMP | D[0-7][0-9A-F]{2} # excluding surrogates | [1-9A-F][0-9A-F]{4} # planes 1-15 | 10 [0-9A-F]{4} # plane 16 ) )* ) $/ix unescaped = $1.split(/[Uu]/)[1..-1].collect do |hex| hex.to_i(16) end.pack('U*')
![Page 56: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/56.jpg)
Convenient Code
SexySyntax
![Page 57: RubyEnRails2007 - Dr Nic Williams - DIY Syntax](https://reader034.vdocument.in/reader034/viewer/2022042623/54823234b079592e0c8b4723/html5/thumbnails/57.jpg)
drnicwilliams.com
by Dr Nic
Enjoy En !