inactivesupport
TRANSCRIPT
株式会社永和システムマネジメントサービスプロバイディング事業部
浦嶌 啓太
InactiveSupportのご紹介
浦嶌 啓太http://twitter.com/ursm/
http://d.hatena.ne.jp/ursm/
http://haml.ursm.jp
よろしくお願いします
本日お話しすること•うちのプロジェクトのInactiveSupportを皆さんにご紹介します!
•特定のライブラリというわけではなくて•プロジェクトを進めていくうちに溜まっていったdirty hackの集まりを勝手にこう呼んでいる•本来は人様にお見せするようなものではない
InactiveSupportって?
警告本LTは、あなたのコードの可読性・メンテナンス性を損う恐れがあります
•Object#tapp•Hash#to_struct•Hash#pairs_at•Object#try•Object#irb
お品書き
Object#tapp•selfをppしてselfを返す
>> 'foo'.tapp"foo"=> "foo"
class Object def tapp require 'pp' tap { pp self } endend
(1..3).map {|i| i ** 2}.inject(&:+)
tmp = (1..3).map {|i| i ** 2}
pp tmp
tmp.inject(&:+)
(1..3).map {|i| i ** 2}.tap {|v| pp v }.inject(&:+)
(1..3).map {|i| i ** 2}.tapp.inject(&:+)
Hash#to_struct•Hashを再帰的にStructに変換する
>> s = {:foo => {:bar => 1}}.to_struct=> #<OpenStruct foo=#<OpenStruct bar=1>>
>> s.foo.bar=> 1
require 'ostruct'
class Hash def to_struct OpenStruct.new(inject({}) {|h, (k, v)| h.merge(k => v.is_a?(Hash) ? v.to_struct : v) }) endend
CONFIG[:admin][:name]
CONFIG = { :admin => { :name => 'yasuo' }, ...}
CONFIG.admin.name
CONFIG = OpenStruct.new( :admin => OpenStruct.new( :name => 'yasuo' ), ...)
CONFIG.admin.name
CONFIG = { :admin => { :name => 'yasuo' }, ...}.to_struct
参考✓Configatronというライブラリがあります✓設定格納用オブジェクトを提供する✓構造体っぽくアクセスできる✓Railsプラグインもある
Hash#pairs_at•あるHashのうち、指定したキーのペアからなるHashを生成して返す
>> h = {:a => 1, :b => 2, :c => 3}=> {:a=>1, :b=>2, :c=>3}
>> h.pairs_at(:a, :c)=> {:a=>1, :c=>3}
class Hash def pairs_at(*keys) keys.zip(values_at(*keys)).inject(self.class.new) {|h, (k, v)| h.merge(k => v) } endend
class UsersController def create u = User.new(params[:user]) ... endend
class UsersController def create u = User.new( :name => params[:user][:name], :age => params[:user][:age] ) ... endend
class UsersController def create u = User.new( params[:user].pairs_at(:name, :age) ) ... endend
class UsersController def create u = User.new( params[:user].slice(:name, :age) ) ... endend
Caution!•Rails 2.1から同様の機能を提供するHash#sliceが入りました
Object#try•selfが指定したメソッドを持っているときはそのまま実行する•持っていないときはnilを返す
>> 'foo'.try(:capitalize)=> "Foo"
>> 'foo'.try(:hoge)=> nil
class Object def try(method, *args, &block) respond_to?(method) ? send(method, *args, &block) : nil endend
<%=h @user.sector.name %>
<%=h @user.sector && @user.sector.name %>
<%=h @user.sector.try(:name) %>
•Rails 2.3から同名のメソッドが入りました•selfがnilのときだけnilを返すようになっています
Caution!
>> nil.try(:hoge)=> nil
>> 1.try(:hoge)NoMethodError: undefined method `hoge' for 1:Fixnum
Object#irb•任意のオブジェクトをコンテキストにしてirbを起動する
class UsersController def create irb ... endend
class Object def irb require 'irb' IRB.setup nil IRB::Irb.new(IRB::WorkSpace.new(binding)).tap {|i| IRB.conf[:MAIN_CONTEXT] = i.context }.eval_input endend
Caution!•それruby-debugでできるよ
余談•what_methodsというライブラリが便利です
>> 'users'.what? 'User'"users".classify == "User"=> ["classify"]>> 'User'.what? 'users'"User".tableize == "users"=> ["tableize"]
InactiveSupportの心得✓やりすぎない✓複雑なことをしない✓ドメインロジックに踏み込まない✓既存メソッドの再定義は禁じ手
まとめ✓Rubyは自由で危険な言語です✓そんなRubyが私は大好きです
http://gist.github.com/154715
ご清聴ありがとうございました