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

KWArgs — the killer Ruby feature you‘re not using

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.

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!