Slide 1

Slide 1 text

TO REFINE OR NOT TO REFINE Vladimir Dementyev

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

HISTORY Introduced in Ruby 2.0.0 Has been experimental until 2.1

Slide 4

Slide 4 text

“Developed my Matz’s boss, Shugo” “Initially was more powerful but JRuby…" "Koichi Sasada wants to remove Refinements” http://rubynoname.ru/posts/2017/S08E08.html *2016

Slide 5

Slide 5 text

EXAMPLES asakusarb/action_args amatsuda/database_rewinder

Slide 6

Slide 6 text

EXAMPLES

Slide 7

Slide 7 text

EXAMPLES https://github.com/rails/rails/pull/27363

Slide 8

Slide 8 text

USE CASES

Slide 9

Slide 9 text

DEPENDENCY REDUCTION module Anyway ::HashExt refine Hash do def stringify_keys! keys.each do |key| val = delete(key) val.stringify_keys! if val.is_a?(Hash) self[key.to_s] = val end end end end https://github.com/palkan/anyway_config

Slide 10

Slide 10 text

class Anyway ::Config using Anyway ::Ext ::DeepDup using Anyway ::Ext ::Hash def self.attr_config(*args, **hargs) @defaults = hargs.deep_dup defaults.stringify_keys! @config_attributes = args + defaults.keys attr_accessor(*@config_attributes) end end https://github.com/palkan/anyway_config DEPENDENCY REDUCTION

Slide 11

Slide 11 text

MODERNIZATION module ThreadFetch # Thread.fetch is only available since 2.5 refine Thread do def fetch(key, fallback = : __undef __) raise KeyError, "key not found: #{key}" if !key?(key) && fallback == : __undef __ self[key] || fallback end end end https://github.com/palkan/isolator

Slide 12

Slide 12 text

PERFECT PRIVACY if Array.instance_methods(false).include?(:sum) && !(%w[a].sum rescue false) # Using Refinements here in # order not to expose our internal method using Module.new { refine Array do alias :orig_sum :sum end } #… end https://github.com/rails/rails/pull/27363/files

Slide 13

Slide 13 text

DSL https://github.com/k-tsj/pattern-match using PatternMatch match(object) do with(pattern[, guard]) do ... end with(pattern[, guard]) do ... end ... end

Slide 14

Slide 14 text

to_proc https://github.com/palkan/clowne # Add to_proc method for lambda module LambdaAsProc refine Proc do def to_proc return self unless lambda? this = self proc { |*args| this.call(*args.take(this.arity)) } end end end

Slide 15

Slide 15 text

SYNTAX SUGAR https://github.com/palkan/test-prof using FloatDuration using StringStripHeredoc msg = <<-MSG.strip_heredoc EventProf results for #{@profiler.event} Total time: #{@profiler.total_time.duration} MSG

Slide 16

Slide 16 text

#PROTIP module Json refine Integer do def to_json to_s end end end using Json p Module.used_modules # => [Json]

Slide 17

Slide 17 text

TRUFFLE BONUS

Slide 18

Slide 18 text

PROBLEMS?

Slide 19

Slide 19 text

PROBLEMS

Slide 20

Slide 20 text

PROBLEMS module Json refine Integer do def to_json to_s end end end using Json p 1.send(:to_json) # => "1" p 1.public_send(:to_json) # => NoMethodError

Slide 21

Slide 21 text

PROBLEMS

Slide 22

Slide 22 text

KONIEC?

Slide 23

Slide 23 text

GemCheck http://gemcheck.evilmartians.io