Upgrade to Pro — share decks privately, control downloads, hide ads and more …

KWArgs — the killer Ruby feature you‘re not using

Avatar for Guyren Howe Guyren Howe
November 10, 2016

KWArgs — the killer Ruby feature you‘re not using

Keyword args have been with us since Ruby 2.0, yet they're not widely used. In this presentation, I explain how KWArgs are strictly better than positional: they enable you to write more loosely coupled and flexible code that is easier to read.

Avatar for Guyren Howe

Guyren Howe

November 10, 2016
Tweet

Other Decks in Programming

Transcript

  1. Who I am • Software developer for 20 years •

    Ruby developer for 10 • Taught R**** bootcamp • R**** & Postgres consultant Guyren G Howe
 @unclouded
 [email protected]
 http://relevantlogic.com Look for my forthcoming
 “Love your Database”
  2. What it do def foo(x, y = 3, *rest, opt2:,

    opt1: nil, **c, &block) positional
 required arg positional
 optional arg kwarg optional kwarg required positional
 args splat kwargs splat* *Turns out to be super interesting
  3. Pretty intuitive rect(x: 10, y: 20, width: 30) args =

    {x: 10, y: 20, width: 30}
 rect(args) rect(:x => 10, :y => 20, :width => 30)
  4. Pretty intuitive > h1 = {a: 1, b: 1} >

    h2 = {a: 2, c: 2} > {a: 0, **h1, **h2} => {:a=>2, :b=>1, :c=>2}
  5. Clearer Net::HTTP.new( server: 'server.com', port: 732, proxy: 'other_server.com', proxy_port: 872,


    proxy_user: 'admin', proxy_pass: 'monkey123' ) Net::HTTP.new('server.com', 732, 'other_server.com', 872, 'admin', 'monkey123')
  6. More Flexible def render_table( rows:, headers: nil ) … end

    class CompaniesController … render_table( rows: @companies, headers: @companies.first.keys ) end
  7. More Flexible def render_table( rows:, headers: nil, stripes: nil )

    … end class OrdersController … render_table( rows: @orders, stripes: '#lightblue' ) end
  8. vs Positional def render_table(rows, headers = nil, stripes = nil)

    … end class OrdersController … render_table(@orders, nil, '#lightblue') end
  9. Lots of Parameters def render_table( rows:, headers: nil, stripes: nil,

    margin: '10px', border: '1px solid black', class: 'table' ) Why not?
  10. What if? User.query( where: "name like 'harry%'", order: 'last_name ASC,

    first_name ASC', group: 'division_id', joins: 'division' )
  11. def foo(x, y = 3, *rest, opt2:, opt1: nil, **c,

    &block) kwargs splat* *Turns out to be super interesting
  12. Functional @user = User.find(user_params[:user_id]) company = @user.company @salary = calculate_salary(

    base: 20_000, per_mile: 10, **{**company.overrides, **user.overrides } ) Functional!
  13. More Flexible def index … render_table(rows: @users) end def render_table(rows:,

    **c) … rows.each do |row| render_row(row, **c) end end
  14. More Flexible def render_row(row:, **c) content_tag('tr') do row.map do |k,

    v| content_tag('td') do render partial: 'cells/' + k.to_s, locals: {thing: v, **c} end.join('') end end
  15. More Flexible … render partial: 'cells/' + k.to_s, locals: {thing:

    v, **c} … # views/cells/_last_name.html.erb <%= thing %>
  16. More Flexible def index … render_table( rows: @users, last_name_format: ->(){"<b>#{yield}</b>"}

    ) end # views/cells/_last_name.html.erb <% last_name_format ||= ->{yield} %> <%= last_name_format(thing)%> Flexible!
  17. Functional @user = User.find(user_params[:user_id]) company = @user.company @salary = calculate_salary(

    base: 20_000, per_mile: 10, **company.overrides .merge(user.overrides) ) Functional!
  18. More Flexible def index … render_table( rows: @users, last_name_format: ->(){"<b>#{yield}</b>"}

    ) end # views/cells/_last_name.html.erb <% last_name_format ||= ->{yield} %> <%= last_name_format(thing)%> Flexible!