SlideShare ist ein Scribd-Unternehmen logo
1 von 28
Downloaden Sie, um offline zu lesen
Active Support の
コア拡張機能について
2018/10/17
大手町.rb #10
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
1自己紹介
Tomoya Kawanishi a.k.a. @cuzic
エネチェンジ株式会社 チーフエンジニア
電力会社、ガス会社を切り替えるなら、エネチェンジ経由で!
一般家庭も!法人も!
Ruby関西の中の人
発表者として登壇くださる方、あとで声かけください。
第84回 Ruby関西勉強会 12月1日(土)
大手町.rb の中の人
毎月 大手町.rb の開催を予定
東京駅、各線大手町駅から直結!
Ruby の初級者がメインターゲット
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Disclaimer
大手町.rb は祝!10回!
人数がとても増えてきました!
大手町.rb は(比較的)初級者向けの勉強会
継続するためには2択!
同じネタをリピート!
初級者向けというポジションを維持
少しずつ難易度を上げていく!
いま、来てくれているオーディエンスとともに成長していく!
大手町.rb は今のオーディエンスを大切にし、
ともに成長していく道を選ぶことにしました!
2
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
今日のテーマ
Active Support のコア拡張機能について
Ruby on Rails を使っていて、
意識しているか、していないかに関わらず
みんな使っています
とはいえ、時間をとって学ぶことがあまりない
というのも事実
今日は一緒に学んでいきましょう
3
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Object#blank? と Object#present?
Ruby で 偽 なものは
nil と false 以外のすべて
ゼロ、空文字、空配列も true
present? を使うと、空文字、空配列は偽になる
4
if 0
"OK"
end
#=> "OK"
if ""
"OK"
end
#=> "OK"
if []
"OK"
end
#=> "OK"
if {}
"OK"
end
#=> "OK"
if nil
"OK"
end
#=> nil
if 0.present?
"OK"
end
#=> "OK"
if "".present?
"OK"
end
#=> nil
if [].present?
"OK"
end
#=> nil
if {}.present?
"OK"
end
#=> nil
if nil.present?
"OK"
end
#=> nil
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Object#presence
x.presence は x.present? ? x : nil と同じ意味
x.presence&.split(",")&.last のように &. (ぼっち演算子)と
組合せたり || と組合わせて使うとベンリ
5
if Rails.env.development?
email = `git config --get user.email`.chomp
email = email.presence || 'example@example.com'
name = `git config --get user.name`.chomp
name = name.presence || 'Naohiro Sakuma'
InternalUser::Admin.find_or_create_by(email: email) do |u|
u.name = name
end
end
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Object#try 、Object#try! (1/3)
nil の場合は何もしない
nil でない場合、引数の名前のメソッドを呼び出す
6
# tryメソッドを使用しない例1
unless @number.nil?
@number.next
end
# try メソッドを使用しない例2
!@number.nil? && @number.next
@number && @number.next
# tryメソッドを使用した場合
@number.try(:next)
# &. 演算子を使用した場合
@number&.next
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Object#try 、Object#try! (2/3)
メソッドがない場合、 nil を返す
メソッドがない場合、例外にしたいときは
try! を使う
7
def log_info(sql, name, ms)
# @logger.debug? メソッドが存在して、かつ true を返す場合だけ以下を実行する
# @logger.debug? がない場合もエラーにならない
if @logger.try(:debug?)
name = '%s (%.1fms)' % [name || 'SQL', ms]
@logger.debug(format_log_entry(name, sql.squeeze(' ')))
end
end
@number.try(:nest) # => nil
@number.try!(:nest) # NoMethodError: undefined method `nest' for 1:Integer
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Object#try 、Object#try! (3/3)
ブロックを渡すこともできる。この場合、
nil でない場合にのみブロックを実行する
この場合、try の返り値は ブロックの評価結果
Ruby 2.5 以降の Object#yield_self 的な使い方もできる
8
@person.try { |p|
"#{p.first_name} #{p.last_name}"
}
[["a", 1], ["b", 2]].try do |array|
array.to_h
end
=> {"a"=>1, "b"=>2}
[["a", 1], ["b", 2]].yield_self do |array|
array.to_h
end
=> {"a"=>1, "b"=>2}
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Object#deep_dup
配列、ハッシュの要素も含めて複製する
配列やハッシュでない場合は、dup と同じ結果を返す
配列やハッシュなら、ディープコピーした結果を返す
ハッシュの場合は、キーも値もディープコピーする
9
array = ['str']
duplicate = array.dup
duplicate[0].gsub!('str', 'foo')
# 要素は複製されていない。
# 一方を変更するとどちらも変更される
array # => ['foo']
duplicate # => ['foo']
array = ['str']
duplicate = array.deep_dup
duplicate[0].gsub!('str', 'foo')
# 要素も複製されている。
# 元の配列は変更されない
array # => ['str']
duplicate # => ['foo']
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Object#to_query
to_query はクエリストリングを生成するのに使える
特に Hash#to_query はクエリストリングを生成する
ときにベンリ
10
# このメソッドは、キーと値のいずれについても、必要な箇所をすべてエスケープします。
account.to_query('company[name]')
# => "company%5Bname%5D=Johnson+%26+Johnson"
# 配列にto_queryメソッドを適用した場合、to_queryを配列の各要素に適用して
# key[]をキーとして追加し、それらを"&"で連結したものを返します。
[3.4, -45.6].to_query('sample')
# => "sample%5B%5D=3.4&sample%5B%5D=-45.6"
# ハッシュもto_queryに応答しますが、異なるシグネチャを使用します。
# メソッドに引数が渡されない場合、このメソッド呼び出しは、一連のキー/値ペアを
# ソート済みの形で生成し、それぞれの値に対してto_query(key)を呼び出します。
# 続いて結果を"&"で連結します。
{c: 3, b: 2, a: 1}.to_query # => "a=1&b=2&c=3"
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Object#with_options
何度も同じ引数が出てきて、ウザいのが、、、
with_options を使うことでまとめられる
11
class Account < ApplicationRecord
has_many :customers, dependent: :destroy
has_many :products, dependent: :destroy
has_many :invoices, dependent: :destroy
has_many :expenses, dependent: :destroy
end
class Account < ApplicationRecord
with_options dependent: :destroy do |assoc|
assoc.has_many :customers
assoc.has_many :products
assoc.has_many :invoices
assoc.has_many :expenses
end
end
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Module の拡張: delegate
delegate を使うとメソッドを簡単に委譲できる。
複数の引数をとることで、複数の属性を一度に移譲できる
12
class User < ApplicationRecord
has_one :profile
def name
profile.name
end
end
class User < ApplicationRecord
has_one :profile
delegate :name, to: :profile
end
delegate :name, :age, :address, :twitter, to: :profile
# 定数 Rails に委譲する
delegate :logger, to: :Rails
# レシーバのクラスに委譲する
delegate :table_name, to: :class
# profile が nil のとき、例外を raise せず nil を返す
delegate :name, to: :profile, allow_nil: true
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Class の拡張: class_attribute
継承可能なクラス属性を定義
https://qiita.com/cuzic/items/ffd115f1e17458020b1b
13
class A
class_attribute :x
end
class B < A; end
class C < B; end
A.x = :a
B.x # => :a
C.x # => :a
B.x = :b
A.x # => :a
C.x # => :b
C.x = :c
A.x # => :a
B.x # => :b
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Class の拡張: cattr_reader、cattr_writer、cattr_accessor
cattr_accessor でクラス変数へのアクセサを定義可能
cattr_reader でリーダだけを定義
cattr_writer でライタだけを定義
14
class MysqlAdapter < AbstractAdapter
# @@emulate_booleansにアクセスできるクラスメソッドを生成する
cattr_accessor :emulate_booleans, default: true
end
module A
class B
# first_name readerは生成されない
cattr_accessor :first_name, instance_reader: false
# last_name= writerは生成されない
cattr_accessor :last_name, instance_writer: false
# reader(surname)も writer(surname=) も生成されない
cattr_accessor :surname, instance_accessor: false
end
end
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
String 拡張: 活用形 1/3 15
"table".pluralize # => "tables"
"ruby".pluralize # => "rubies"
"equipment".pluralize # => "equipment"
"tables".singularize # => "table"
"rubies".singularize # => "ruby"
"equipment".singularize # => "equipment"
"product".camelize # => "Product"
"admin_user".camelize # => "AdminUser"
"Product".underscore # => "product"
"AdminUser".underscore # => "admin_user"
"alice in wonderland".titleize # => "Alice In Wonderland"
"fermat's enigma".titleize # => "Fermat's Enigma"
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
String 拡張: 活用形 2/3 16
"name".dasherize # => "name"
"contact_data".dasherize # => "contact-data"
"Product".demodulize # => "Product"
"Backoffice::UsersController".demodulize # => "UsersController"
"Admin::Hotel::ReservationUtils".demodulize # => "ReservationUtils"
"::Inflections".demodulize # => "Inflections"
"".demodulize # => ""
"Product".deconstantize # => ""
"Backoffice::UsersController".deconstantize # => "Backoffice"
"Admin::Hotel::ReservationUtils".deconstantize # => "Admin::Hotel"
"John Smith".parameterize # => "john-smith"
"Kurt Gödel".parameterize # => "kurt-godel"
"Person".tableize # => "people"
"Invoice".tableize # => "invoices"
"InvoiceLine".tableize # => "invoice_lines"
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
String拡張:活用形 3/3 17
"people".classify # => "Person"
"invoices".classify # => "Invoice"
"invoice_lines".classify # => "InvoiceLine"
"Fixnum".constantize # => Fixnum
"name".humanize # => "Name"
"author_id".humanize # => "Author"
"author_id".humanize(capitalize: false) # => "author"
"comments_count".humanize # => "Comments count"
"_id".humanize # => "Id"
"User".foreign_key # => "user_id"
"InvoiceLine".foreign_key # => "invoice_line_id"
"Admin::Session".foreign_key # => "session_id"
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
String拡張 to_date, to_time, to_datetime
to_date で Date 型
to_time :Time型
to_datetime : DateTime 型
Time.zone.parse よりも文字数が少なく便利
18
"2010-07-27".to_date # => Tue, 27 Jul 2010
"2010-07-27 23:37:00".to_time # => 2010-07-27 23:37:00 +0200
"2010-07-27 23:37:00".to_datetime # => Tue, 27 Jul 2010 23:37:00 +0000
"2010-07-27 23:42:00".to_time(:utc) # => 2010-07-27 23:42:00 UTC
"2010-07-27 23:42:00".to_time(:local) # => 2010-07-27 23:42:00 +0200
# デフォルトは :local
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Numeric の拡張: フォーマッティング 1/3 19
Currency:
1234567890.50.to_s(:currency) # => "$1,234,567,890.50"
1234567890.506.to_s(:currency) # => "$1,234,567,890.51"
1234567890.506.to_s(:currency, precision: 3) # => "$1,234,567,890.506"
-1234567890.50.to_s(:currency, negative_format: '(%u%n)')
# => "($1,234,567,890.50)"
1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '')
# => "&pound;1234567890,50"
1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '',
format: '%n %u')
# => "1234567890,50 &pound;"
Percentage:
100.to_s(:percentage) # => "100.000%"
100.to_s(:percentage, precision: 0) # => "100%"
1000.to_s(:percentage, delimiter: '.', separator: ',') # => "1.000,000%"
302.24398923423.to_s(:percentage, precision: 5) # => "302.24399%"
1000.to_s(:percentage, locale: :fr) # => "1 000,000%"
100.to_s(:percentage, format: '%n %') # => "100.000 %"
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Numeric の拡張: フォーマッティング 2/3 20
Delimited:
12345678.to_s(:delimited) # => "12,345,678"
12345678.05.to_s(:delimited) # => "12,345,678.05"
12345678.to_s(:delimited, delimiter: '.') # => "12.345.678"
12345678.to_s(:delimited, delimiter: ',') # => "12,345,678"
12345678.05.to_s(:delimited, separator: ' ') # => "12,345,678 05"
12345678.05.to_s(:delimited, locale: :fr) # => "12 345 678,05"
98765432.98.to_s(:delimited, delimiter: ' ', separator: ',')
# => "98 765 432,98"
Rounded:
111.2345.to_s(:rounded) # => "111.235"
111.2345.to_s(:rounded, precision: 2) # => "111.23"
13.to_s(:rounded, precision: 5) # => "13.00000"
389.32314.to_s(:rounded, precision: 0) # => "389"
111.2345.to_s(:rounded, significant: true) # => "111"
111.2345.to_s(:rounded, precision: 1, significant: true) # => "100"
13.to_s(:rounded, precision: 5, significant: true) # => "13.000"
111.234.to_s(:rounded, locale: :fr) # => "111,234"
13.to_s(:rounded, precision: 5, significant: true, strip_insignificant_zeros: true)
# => "13"
389.32314.to_s(:rounded, precision: 4, significant: true) # => "389.3"
1111.2345.to_s(:rounded, precision: 2, separator: ',', delimiter: '.')
# => "1.111,23"
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Numeric の拡張: フォーマッティング 3/3 21
Human-friendly size in Bytes:
123.to_s(:human_size) # => "123 Bytes"
1234.to_s(:human_size) # => "1.21 KB"
1234567.to_s(:human_size) # => "1.18 MB"
1234567890.to_s(:human_size) # => "1.15 GB"
1234567890123.to_s(:human_size) # => "1.12 TB"
1234567890123456.to_s(:human_size) # => "1.1 PB"
1234567890123456789.to_s(:human_size) # => "1.07 EB"
1234567.to_s(:human_size, precision: 2) # => "1.2 MB"
483989.to_s(:human_size, precision: 2) # => "470 KB"
1234567.to_s(:human_size, precision: 2, separator: ',') # => "1,2 MB"
1234567890123.to_s(:human_size, precision: 5) # => "1.1228 TB"
524288000.to_s(:human_size, precision: 5) # => "500 MB"
Human-friendly format:
123.to_s(:human) # => "123"
1234.to_s(:human) # => "1.23 Thousand"
1234567.to_s(:human) # => "1.23 Million"
1234567890.to_s(:human) # => "1.23 Billion"
1234567890123.to_s(:human) # => "1.23 Trillion"
1234567890123456.to_s(:human) # => "1.23 Quadrillion"
489939.to_s(:human, precision: 2) # => "490 Thousand"
489939.to_s(:human, precision: 4) # => "489.9 Thousand"
1234567.to_s(:human, precision: 4,
significant: false) # => "1.2346 Million"
1234567.to_s(:human, precision: 1, separator: ',',
significant: false) # => "1,2 Million"
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Enumerable の拡張: sum
Enumerable#sum : 合計値を計算
空配列の場合のデフォルト値も指定できる。
数値でなくても、 + メソッドを使って sum を計算
22
[1, 2, 3].sum # => 6
(1..100).sum # => 5050
[[1, 2], [2, 3], [3, 4]].sum # => [1, 2, 2, 3, 3, 4]
%w(foo bar baz).sum # => "foobarbaz"
{a: 1, b: 2, c: 3}.sum # => [:b, 2, :c, 3, :a, 1]
[].sum(1) {|n| n**3} # => 1
(1..3).sum{|n| n**3} #=> 36
(1..3).sum(1){|n| n**3} #=> 36
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Enumerable の拡張: 抽出
exclude? で要素が含まれていないときの判定ができる
without を使うと、指定した要素を除外できる
pluck メソッドで、指定したキーに基づく配列を返す
23
# exclude? は、include? の逆の動作
to_visit << node if visited.exclude?(node)
# without
["David", "Rafael", "Aaron", "Todd"].without("Aaron", "Todd") # => ["David", "Rafael"]
# pluck
[{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name) # => ["David",
"Rafael", "Aaron"]
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Hash の拡張: 抽出
Hash#reverse_merge はデフォルト設定のときに便利
except で不要な要素の除外、slice で必要な要素の抽出ができる
extract は、ハッシュから取り除いた上でそのキーのペアを返す
compact を使うと値が nil の要素を除外できる
24
# デフォルト値が左側で、右側がカスタマイズする引数
# 同じキーがあれば、右側が優先される
options = {length: 30, omission: "..."}.merge(options)
# reverse_merge を使うとデフォルト値が右側になり、見やすい
options = options.reverse_merge(length: 30, omission: "...")
# 破壊的に変更する
options.reverse_merge!(length: 30, omission: "...")
{a: 1, b: 2}.except(:a) # => {:b=>2}
{a: 1, b: 2, c: 3}.slice(:a, :c)
# => {:a=>1, :c=>3}
hash = {a: 1, b: 2}
rest = hash.extract!(:a) # => {:a=>1}
hash # => {:b=>2}
{a: 1, b: 2, c: nil}.compact # => {a: 1, b: 2}
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
Hash の拡張: stringify、symbolize
文字列とシンボルの両方がキーになりえるとき、
stringify、symbolize で片方に寄せると扱いやすい
with_indifference_access を使うと
文字列とシンボルのどちらでも使えるようにできる
25
{nil => nil, 1 => 1, a: :a}.stringify_keys
# => {"" => nil, "1" => 1, "a" => :a}
{nil => nil, 1 => 1, "a" => "a"}.symbolize_keys
# => {nil=>nil, 1=>1, :a=>"a"}
{nil => nil, 1 => 1, "nested" => {"a" => 3, 5 => 5}}.deep_symbolize_keys
# => {nil=>nil, 1=>1, nested:{a:3, 5=>5}}
{a: 1}.with_indifferent_access["a"] # => 1
# 文字列とシンボルの両方がありえる場合に、ベンリ
def rewrite_path(options)
options = options.symbolize_keys
options.update(options[:params].symbolize_keys) if options[:params]
...
end
大手町.rb #10 発表資料 「Active Support のコア拡張機能について」
まとめ
今日は Active Support のコア拡張機能について、
ピックアップして、紹介しました。
個人的には特に Object の拡張機能をよく使います
blank?、present?、presence、with_options
あと、 Hash の拡張もベンリです。
to_query、reverse_merge、except、slice、
with_indifferent_access
ドキュメントを熟読しましょう!
気が付かなかった発見がたくさんあります。
私自身、たくさんありました
特に Rails Guide と Ruby on Rails API は必読です。
https://railsguides.jp/
https://api.rubyonrails.org/
26
ご清聴ありがとう
ございました

Weitere ähnliche Inhalte

Was ist angesagt?

WordPress関数の処理コストを考えよう
WordPress関数の処理コストを考えようWordPress関数の処理コストを考えよう
WordPress関数の処理コストを考えよう
Naoki Matsuda
 
すごいHaskell読書会 in 大阪 #4 「第6章 モジュール」
すごいHaskell読書会 in 大阪 #4 「第6章 モジュール」すごいHaskell読書会 in 大阪 #4 「第6章 モジュール」
すごいHaskell読書会 in 大阪 #4 「第6章 モジュール」
Shin Ise
 
FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -
Akio Katayama
 

Was ist angesagt? (19)

Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014
Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014
Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014
 
Django boodoo
Django boodooDjango boodoo
Django boodoo
 
WordPress関数の処理コストを考えよう
WordPress関数の処理コストを考えようWordPress関数の処理コストを考えよう
WordPress関数の処理コストを考えよう
 
【GCPUG滋賀】BigQueryでさるでもわかるSQL(20190323)
【GCPUG滋賀】BigQueryでさるでもわかるSQL(20190323)【GCPUG滋賀】BigQueryでさるでもわかるSQL(20190323)
【GCPUG滋賀】BigQueryでさるでもわかるSQL(20190323)
 
すごいHaskell読書会 in 大阪 #4 「第6章 モジュール」
すごいHaskell読書会 in 大阪 #4 「第6章 モジュール」すごいHaskell読書会 in 大阪 #4 「第6章 モジュール」
すごいHaskell読書会 in 大阪 #4 「第6章 モジュール」
 
RailsエンジニアのためのSQLチューニング速習会
RailsエンジニアのためのSQLチューニング速習会RailsエンジニアのためのSQLチューニング速習会
RailsエンジニアのためのSQLチューニング速習会
 
WordPress のキャッシュ機構
WordPress のキャッシュ機構WordPress のキャッシュ機構
WordPress のキャッシュ機構
 
ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~
ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~
ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~
 
Rで触れる日本経済~RでVAR編~
Rで触れる日本経済~RでVAR編~Rで触れる日本経済~RでVAR編~
Rで触れる日本経済~RでVAR編~
 
202008 のの会@関数Talk 23rd @function-talk-in-notesknows-workshop
202008 のの会@関数Talk 23rd @function-talk-in-notesknows-workshop202008 のの会@関数Talk 23rd @function-talk-in-notesknows-workshop
202008 のの会@関数Talk 23rd @function-talk-in-notesknows-workshop
 
10分で分かるr言語入門ver2.9 14 0920
10分で分かるr言語入門ver2.9 14 0920 10分で分かるr言語入門ver2.9 14 0920
10分で分かるr言語入門ver2.9 14 0920
 
202009 のの会@関数Talk 24th @function-talk-in-notesknows-workshop
202009 のの会@関数Talk 24th @function-talk-in-notesknows-workshop202009 のの会@関数Talk 24th @function-talk-in-notesknows-workshop
202009 のの会@関数Talk 24th @function-talk-in-notesknows-workshop
 
第7回社内勉強会「Code Sucks - 人の振り見て我が振り直せ」
第7回社内勉強会「Code Sucks - 人の振り見て我が振り直せ」第7回社内勉強会「Code Sucks - 人の振り見て我が振り直せ」
第7回社内勉強会「Code Sucks - 人の振り見て我が振り直せ」
 
FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -
 
「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~
「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~
「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~
 
Zend Frameworkで始める携帯サイト
Zend Frameworkで始める携帯サイトZend Frameworkで始める携帯サイト
Zend Frameworkで始める携帯サイト
 
objective-c propertyの属性について
objective-c propertyの属性についてobjective-c propertyの属性について
objective-c propertyの属性について
 
これからのpre_get_postsの話をしよう
これからのpre_get_postsの話をしようこれからのpre_get_postsの話をしよう
これからのpre_get_postsの話をしよう
 
Gorinphp0729
Gorinphp0729Gorinphp0729
Gorinphp0729
 

Ähnlich wie Active Support のコア拡張機能について

月間10億pvを支えるmongo db
月間10億pvを支えるmongo db月間10億pvを支えるmongo db
月間10億pvを支えるmongo db
Yuji Isobe
 
ゲットーの斜め上をゆくWebアプリケーションフレームワークの開発
ゲットーの斜め上をゆくWebアプリケーションフレームワークの開発ゲットーの斜め上をゆくWebアプリケーションフレームワークの開発
ゲットーの斜め上をゆくWebアプリケーションフレームワークの開発
emasaka
 
丸山先生レクチャーシリーズ2007-2008
丸山先生レクチャーシリーズ2007-2008丸山先生レクチャーシリーズ2007-2008
丸山先生レクチャーシリーズ2007-2008
Yoichiro Tanaka
 
Ruby Sapporo Night Vol4
Ruby Sapporo Night Vol4Ruby Sapporo Night Vol4
Ruby Sapporo Night Vol4
Koji SHIMADA
 

Ähnlich wie Active Support のコア拡張機能について (20)

【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第2回 ‟変数と型„
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第2回 ‟変数と型„【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第2回 ‟変数と型„
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第2回 ‟変数と型„
 
月間10億pvを支えるmongo db
月間10億pvを支えるmongo db月間10億pvを支えるmongo db
月間10億pvを支えるmongo db
 
20171103 pg con-jp-lt-plpgsql
20171103 pg con-jp-lt-plpgsql20171103 pg con-jp-lt-plpgsql
20171103 pg con-jp-lt-plpgsql
 
20120317 IT系勉強会 in 神戸
20120317 IT系勉強会 in 神戸20120317 IT系勉強会 in 神戸
20120317 IT系勉強会 in 神戸
 
Proposed boost b_tree_library(ja)
Proposed boost b_tree_library(ja)Proposed boost b_tree_library(ja)
Proposed boost b_tree_library(ja)
 
ゲットーの斜め上をゆくWebアプリケーションフレームワークの開発
ゲットーの斜め上をゆくWebアプリケーションフレームワークの開発ゲットーの斜め上をゆくWebアプリケーションフレームワークの開発
ゲットーの斜め上をゆくWebアプリケーションフレームワークの開発
 
Functional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.jsFunctional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.js
 
とあるプロジェクトのつらみなコード
とあるプロジェクトのつらみなコードとあるプロジェクトのつらみなコード
とあるプロジェクトのつらみなコード
 
丸山先生レクチャーシリーズ2007-2008
丸山先生レクチャーシリーズ2007-2008丸山先生レクチャーシリーズ2007-2008
丸山先生レクチャーシリーズ2007-2008
 
Ruby で高速なプログラムを書く
Ruby で高速なプログラムを書くRuby で高速なプログラムを書く
Ruby で高速なプログラムを書く
 
SQLマッピングフレームワーク「Kobati」のはなし
SQLマッピングフレームワーク「Kobati」のはなしSQLマッピングフレームワーク「Kobati」のはなし
SQLマッピングフレームワーク「Kobati」のはなし
 
PostgreSQL 9.5 新機能紹介
PostgreSQL 9.5 新機能紹介PostgreSQL 9.5 新機能紹介
PostgreSQL 9.5 新機能紹介
 
PostgreSQL 10 新機能 @オープンセミナー香川 2017
PostgreSQL 10 新機能 @オープンセミナー香川 2017PostgreSQL 10 新機能 @オープンセミナー香川 2017
PostgreSQL 10 新機能 @オープンセミナー香川 2017
 
Tokyo r33 beginner
Tokyo r33 beginnerTokyo r33 beginner
Tokyo r33 beginner
 
Reactive Programming
Reactive ProgrammingReactive Programming
Reactive Programming
 
Ruby Sapporo Night Vol4
Ruby Sapporo Night Vol4Ruby Sapporo Night Vol4
Ruby Sapporo Night Vol4
 
シラサギハンズオン 大阪
シラサギハンズオン 大阪シラサギハンズオン 大阪
シラサギハンズオン 大阪
 
Favtile ~never write JS again~
Favtile ~never write JS again~Favtile ~never write JS again~
Favtile ~never write JS again~
 
textsearch_jaで全文検索
textsearch_jaで全文検索textsearch_jaで全文検索
textsearch_jaで全文検索
 
シラサギハンズオン 東京
シラサギハンズオン 東京シラサギハンズオン 東京
シラサギハンズオン 東京
 

Mehr von Tomoya Kawanishi

Ruby ビジネス創出展 Ruby初心者向けプログラミングセミナー
Ruby ビジネス創出展 Ruby初心者向けプログラミングセミナーRuby ビジネス創出展 Ruby初心者向けプログラミングセミナー
Ruby ビジネス創出展 Ruby初心者向けプログラミングセミナー
Tomoya Kawanishi
 

Mehr von Tomoya Kawanishi (20)

英単語の覚え方
英単語の覚え方英単語の覚え方
英単語の覚え方
 
ENECHANGE社での Scout APM 利用事例
ENECHANGE社での Scout APM 利用事例ENECHANGE社での Scout APM 利用事例
ENECHANGE社での Scout APM 利用事例
 
エンジニア転職のノウハウ
エンジニア転職のノウハウエンジニア転職のノウハウ
エンジニア転職のノウハウ
 
Ruby の文字列について
Ruby の文字列についてRuby の文字列について
Ruby の文字列について
 
Ruby on Rails のキャッシュ機構について
Ruby on Rails のキャッシュ機構についてRuby on Rails のキャッシュ機構について
Ruby on Rails のキャッシュ機構について
 
Ruby初心者からよく質問されること
Ruby初心者からよく質問されることRuby初心者からよく質問されること
Ruby初心者からよく質問されること
 
RubyGems と Bundler について
RubyGems と Bundler についてRubyGems と Bundler について
RubyGems と Bundler について
 
Ruby の正規表現について
Ruby の正規表現についてRuby の正規表現について
Ruby の正規表現について
 
Ruby での外部コマンドの実行について
Ruby での外部コマンドの実行についてRuby での外部コマンドの実行について
Ruby での外部コマンドの実行について
 
Ruby のワンライナーについて
Ruby のワンライナーについてRuby のワンライナーについて
Ruby のワンライナーについて
 
AWS のコスト管理をちゃんとしたくてやったこと
AWS のコスト管理をちゃんとしたくてやったことAWS のコスト管理をちゃんとしたくてやったこと
AWS のコスト管理をちゃんとしたくてやったこと
 
PostgreSQL のイケてるテクニック7選
PostgreSQL のイケてるテクニック7選PostgreSQL のイケてるテクニック7選
PostgreSQL のイケてるテクニック7選
 
HTTPと Webクローリングについて
HTTPと WebクローリングについてHTTPと Webクローリングについて
HTTPと Webクローリングについて
 
Rake
RakeRake
Rake
 
Active record query interface
Active record query interfaceActive record query interface
Active record query interface
 
Ruby ビジネス創出展 Ruby初心者向けプログラミングセミナー
Ruby ビジネス創出展 Ruby初心者向けプログラミングセミナーRuby ビジネス創出展 Ruby初心者向けプログラミングセミナー
Ruby ビジネス創出展 Ruby初心者向けプログラミングセミナー
 
RubyのDir、File、IO について
RubyのDir、File、IO についてRubyのDir、File、IO について
RubyのDir、File、IO について
 
Thread の利用事例紹介
Thread の利用事例紹介Thread の利用事例紹介
Thread の利用事例紹介
 
Ruby の制御構造とリテラルについて
Ruby の制御構造とリテラルについてRuby の制御構造とリテラルについて
Ruby の制御構造とリテラルについて
 
Ruby の String のメソッドについて
Ruby の String のメソッドについてRuby の String のメソッドについて
Ruby の String のメソッドについて
 

Kürzlich hochgeladen

Kürzlich hochgeladen (12)

知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native Integrations
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 

Active Support のコア拡張機能について

  • 2. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 1自己紹介 Tomoya Kawanishi a.k.a. @cuzic エネチェンジ株式会社 チーフエンジニア 電力会社、ガス会社を切り替えるなら、エネチェンジ経由で! 一般家庭も!法人も! Ruby関西の中の人 発表者として登壇くださる方、あとで声かけください。 第84回 Ruby関西勉強会 12月1日(土) 大手町.rb の中の人 毎月 大手町.rb の開催を予定 東京駅、各線大手町駅から直結! Ruby の初級者がメインターゲット
  • 3. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Disclaimer 大手町.rb は祝!10回! 人数がとても増えてきました! 大手町.rb は(比較的)初級者向けの勉強会 継続するためには2択! 同じネタをリピート! 初級者向けというポジションを維持 少しずつ難易度を上げていく! いま、来てくれているオーディエンスとともに成長していく! 大手町.rb は今のオーディエンスを大切にし、 ともに成長していく道を選ぶことにしました! 2
  • 4. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 今日のテーマ Active Support のコア拡張機能について Ruby on Rails を使っていて、 意識しているか、していないかに関わらず みんな使っています とはいえ、時間をとって学ぶことがあまりない というのも事実 今日は一緒に学んでいきましょう 3
  • 5. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Object#blank? と Object#present? Ruby で 偽 なものは nil と false 以外のすべて ゼロ、空文字、空配列も true present? を使うと、空文字、空配列は偽になる 4 if 0 "OK" end #=> "OK" if "" "OK" end #=> "OK" if [] "OK" end #=> "OK" if {} "OK" end #=> "OK" if nil "OK" end #=> nil if 0.present? "OK" end #=> "OK" if "".present? "OK" end #=> nil if [].present? "OK" end #=> nil if {}.present? "OK" end #=> nil if nil.present? "OK" end #=> nil
  • 6. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Object#presence x.presence は x.present? ? x : nil と同じ意味 x.presence&.split(",")&.last のように &. (ぼっち演算子)と 組合せたり || と組合わせて使うとベンリ 5 if Rails.env.development? email = `git config --get user.email`.chomp email = email.presence || 'example@example.com' name = `git config --get user.name`.chomp name = name.presence || 'Naohiro Sakuma' InternalUser::Admin.find_or_create_by(email: email) do |u| u.name = name end end
  • 7. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Object#try 、Object#try! (1/3) nil の場合は何もしない nil でない場合、引数の名前のメソッドを呼び出す 6 # tryメソッドを使用しない例1 unless @number.nil? @number.next end # try メソッドを使用しない例2 !@number.nil? && @number.next @number && @number.next # tryメソッドを使用した場合 @number.try(:next) # &. 演算子を使用した場合 @number&.next
  • 8. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Object#try 、Object#try! (2/3) メソッドがない場合、 nil を返す メソッドがない場合、例外にしたいときは try! を使う 7 def log_info(sql, name, ms) # @logger.debug? メソッドが存在して、かつ true を返す場合だけ以下を実行する # @logger.debug? がない場合もエラーにならない if @logger.try(:debug?) name = '%s (%.1fms)' % [name || 'SQL', ms] @logger.debug(format_log_entry(name, sql.squeeze(' '))) end end @number.try(:nest) # => nil @number.try!(:nest) # NoMethodError: undefined method `nest' for 1:Integer
  • 9. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Object#try 、Object#try! (3/3) ブロックを渡すこともできる。この場合、 nil でない場合にのみブロックを実行する この場合、try の返り値は ブロックの評価結果 Ruby 2.5 以降の Object#yield_self 的な使い方もできる 8 @person.try { |p| "#{p.first_name} #{p.last_name}" } [["a", 1], ["b", 2]].try do |array| array.to_h end => {"a"=>1, "b"=>2} [["a", 1], ["b", 2]].yield_self do |array| array.to_h end => {"a"=>1, "b"=>2}
  • 10. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Object#deep_dup 配列、ハッシュの要素も含めて複製する 配列やハッシュでない場合は、dup と同じ結果を返す 配列やハッシュなら、ディープコピーした結果を返す ハッシュの場合は、キーも値もディープコピーする 9 array = ['str'] duplicate = array.dup duplicate[0].gsub!('str', 'foo') # 要素は複製されていない。 # 一方を変更するとどちらも変更される array # => ['foo'] duplicate # => ['foo'] array = ['str'] duplicate = array.deep_dup duplicate[0].gsub!('str', 'foo') # 要素も複製されている。 # 元の配列は変更されない array # => ['str'] duplicate # => ['foo']
  • 11. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Object#to_query to_query はクエリストリングを生成するのに使える 特に Hash#to_query はクエリストリングを生成する ときにベンリ 10 # このメソッドは、キーと値のいずれについても、必要な箇所をすべてエスケープします。 account.to_query('company[name]') # => "company%5Bname%5D=Johnson+%26+Johnson" # 配列にto_queryメソッドを適用した場合、to_queryを配列の各要素に適用して # key[]をキーとして追加し、それらを"&"で連結したものを返します。 [3.4, -45.6].to_query('sample') # => "sample%5B%5D=3.4&sample%5B%5D=-45.6" # ハッシュもto_queryに応答しますが、異なるシグネチャを使用します。 # メソッドに引数が渡されない場合、このメソッド呼び出しは、一連のキー/値ペアを # ソート済みの形で生成し、それぞれの値に対してto_query(key)を呼び出します。 # 続いて結果を"&"で連結します。 {c: 3, b: 2, a: 1}.to_query # => "a=1&b=2&c=3"
  • 12. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Object#with_options 何度も同じ引数が出てきて、ウザいのが、、、 with_options を使うことでまとめられる 11 class Account < ApplicationRecord has_many :customers, dependent: :destroy has_many :products, dependent: :destroy has_many :invoices, dependent: :destroy has_many :expenses, dependent: :destroy end class Account < ApplicationRecord with_options dependent: :destroy do |assoc| assoc.has_many :customers assoc.has_many :products assoc.has_many :invoices assoc.has_many :expenses end end
  • 13. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Module の拡張: delegate delegate を使うとメソッドを簡単に委譲できる。 複数の引数をとることで、複数の属性を一度に移譲できる 12 class User < ApplicationRecord has_one :profile def name profile.name end end class User < ApplicationRecord has_one :profile delegate :name, to: :profile end delegate :name, :age, :address, :twitter, to: :profile # 定数 Rails に委譲する delegate :logger, to: :Rails # レシーバのクラスに委譲する delegate :table_name, to: :class # profile が nil のとき、例外を raise せず nil を返す delegate :name, to: :profile, allow_nil: true
  • 14. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Class の拡張: class_attribute 継承可能なクラス属性を定義 https://qiita.com/cuzic/items/ffd115f1e17458020b1b 13 class A class_attribute :x end class B < A; end class C < B; end A.x = :a B.x # => :a C.x # => :a B.x = :b A.x # => :a C.x # => :b C.x = :c A.x # => :a B.x # => :b
  • 15. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Class の拡張: cattr_reader、cattr_writer、cattr_accessor cattr_accessor でクラス変数へのアクセサを定義可能 cattr_reader でリーダだけを定義 cattr_writer でライタだけを定義 14 class MysqlAdapter < AbstractAdapter # @@emulate_booleansにアクセスできるクラスメソッドを生成する cattr_accessor :emulate_booleans, default: true end module A class B # first_name readerは生成されない cattr_accessor :first_name, instance_reader: false # last_name= writerは生成されない cattr_accessor :last_name, instance_writer: false # reader(surname)も writer(surname=) も生成されない cattr_accessor :surname, instance_accessor: false end end
  • 16. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 String 拡張: 活用形 1/3 15 "table".pluralize # => "tables" "ruby".pluralize # => "rubies" "equipment".pluralize # => "equipment" "tables".singularize # => "table" "rubies".singularize # => "ruby" "equipment".singularize # => "equipment" "product".camelize # => "Product" "admin_user".camelize # => "AdminUser" "Product".underscore # => "product" "AdminUser".underscore # => "admin_user" "alice in wonderland".titleize # => "Alice In Wonderland" "fermat's enigma".titleize # => "Fermat's Enigma"
  • 17. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 String 拡張: 活用形 2/3 16 "name".dasherize # => "name" "contact_data".dasherize # => "contact-data" "Product".demodulize # => "Product" "Backoffice::UsersController".demodulize # => "UsersController" "Admin::Hotel::ReservationUtils".demodulize # => "ReservationUtils" "::Inflections".demodulize # => "Inflections" "".demodulize # => "" "Product".deconstantize # => "" "Backoffice::UsersController".deconstantize # => "Backoffice" "Admin::Hotel::ReservationUtils".deconstantize # => "Admin::Hotel" "John Smith".parameterize # => "john-smith" "Kurt Gödel".parameterize # => "kurt-godel" "Person".tableize # => "people" "Invoice".tableize # => "invoices" "InvoiceLine".tableize # => "invoice_lines"
  • 18. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 String拡張:活用形 3/3 17 "people".classify # => "Person" "invoices".classify # => "Invoice" "invoice_lines".classify # => "InvoiceLine" "Fixnum".constantize # => Fixnum "name".humanize # => "Name" "author_id".humanize # => "Author" "author_id".humanize(capitalize: false) # => "author" "comments_count".humanize # => "Comments count" "_id".humanize # => "Id" "User".foreign_key # => "user_id" "InvoiceLine".foreign_key # => "invoice_line_id" "Admin::Session".foreign_key # => "session_id"
  • 19. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 String拡張 to_date, to_time, to_datetime to_date で Date 型 to_time :Time型 to_datetime : DateTime 型 Time.zone.parse よりも文字数が少なく便利 18 "2010-07-27".to_date # => Tue, 27 Jul 2010 "2010-07-27 23:37:00".to_time # => 2010-07-27 23:37:00 +0200 "2010-07-27 23:37:00".to_datetime # => Tue, 27 Jul 2010 23:37:00 +0000 "2010-07-27 23:42:00".to_time(:utc) # => 2010-07-27 23:42:00 UTC "2010-07-27 23:42:00".to_time(:local) # => 2010-07-27 23:42:00 +0200 # デフォルトは :local
  • 20. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Numeric の拡張: フォーマッティング 1/3 19 Currency: 1234567890.50.to_s(:currency) # => "$1,234,567,890.50" 1234567890.506.to_s(:currency) # => "$1,234,567,890.51" 1234567890.506.to_s(:currency, precision: 3) # => "$1,234,567,890.506" -1234567890.50.to_s(:currency, negative_format: '(%u%n)') # => "($1,234,567,890.50)" 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '') # => "&pound;1234567890,50" 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u') # => "1234567890,50 &pound;" Percentage: 100.to_s(:percentage) # => "100.000%" 100.to_s(:percentage, precision: 0) # => "100%" 1000.to_s(:percentage, delimiter: '.', separator: ',') # => "1.000,000%" 302.24398923423.to_s(:percentage, precision: 5) # => "302.24399%" 1000.to_s(:percentage, locale: :fr) # => "1 000,000%" 100.to_s(:percentage, format: '%n %') # => "100.000 %"
  • 21. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Numeric の拡張: フォーマッティング 2/3 20 Delimited: 12345678.to_s(:delimited) # => "12,345,678" 12345678.05.to_s(:delimited) # => "12,345,678.05" 12345678.to_s(:delimited, delimiter: '.') # => "12.345.678" 12345678.to_s(:delimited, delimiter: ',') # => "12,345,678" 12345678.05.to_s(:delimited, separator: ' ') # => "12,345,678 05" 12345678.05.to_s(:delimited, locale: :fr) # => "12 345 678,05" 98765432.98.to_s(:delimited, delimiter: ' ', separator: ',') # => "98 765 432,98" Rounded: 111.2345.to_s(:rounded) # => "111.235" 111.2345.to_s(:rounded, precision: 2) # => "111.23" 13.to_s(:rounded, precision: 5) # => "13.00000" 389.32314.to_s(:rounded, precision: 0) # => "389" 111.2345.to_s(:rounded, significant: true) # => "111" 111.2345.to_s(:rounded, precision: 1, significant: true) # => "100" 13.to_s(:rounded, precision: 5, significant: true) # => "13.000" 111.234.to_s(:rounded, locale: :fr) # => "111,234" 13.to_s(:rounded, precision: 5, significant: true, strip_insignificant_zeros: true) # => "13" 389.32314.to_s(:rounded, precision: 4, significant: true) # => "389.3" 1111.2345.to_s(:rounded, precision: 2, separator: ',', delimiter: '.') # => "1.111,23"
  • 22. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Numeric の拡張: フォーマッティング 3/3 21 Human-friendly size in Bytes: 123.to_s(:human_size) # => "123 Bytes" 1234.to_s(:human_size) # => "1.21 KB" 1234567.to_s(:human_size) # => "1.18 MB" 1234567890.to_s(:human_size) # => "1.15 GB" 1234567890123.to_s(:human_size) # => "1.12 TB" 1234567890123456.to_s(:human_size) # => "1.1 PB" 1234567890123456789.to_s(:human_size) # => "1.07 EB" 1234567.to_s(:human_size, precision: 2) # => "1.2 MB" 483989.to_s(:human_size, precision: 2) # => "470 KB" 1234567.to_s(:human_size, precision: 2, separator: ',') # => "1,2 MB" 1234567890123.to_s(:human_size, precision: 5) # => "1.1228 TB" 524288000.to_s(:human_size, precision: 5) # => "500 MB" Human-friendly format: 123.to_s(:human) # => "123" 1234.to_s(:human) # => "1.23 Thousand" 1234567.to_s(:human) # => "1.23 Million" 1234567890.to_s(:human) # => "1.23 Billion" 1234567890123.to_s(:human) # => "1.23 Trillion" 1234567890123456.to_s(:human) # => "1.23 Quadrillion" 489939.to_s(:human, precision: 2) # => "490 Thousand" 489939.to_s(:human, precision: 4) # => "489.9 Thousand" 1234567.to_s(:human, precision: 4, significant: false) # => "1.2346 Million" 1234567.to_s(:human, precision: 1, separator: ',', significant: false) # => "1,2 Million"
  • 23. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Enumerable の拡張: sum Enumerable#sum : 合計値を計算 空配列の場合のデフォルト値も指定できる。 数値でなくても、 + メソッドを使って sum を計算 22 [1, 2, 3].sum # => 6 (1..100).sum # => 5050 [[1, 2], [2, 3], [3, 4]].sum # => [1, 2, 2, 3, 3, 4] %w(foo bar baz).sum # => "foobarbaz" {a: 1, b: 2, c: 3}.sum # => [:b, 2, :c, 3, :a, 1] [].sum(1) {|n| n**3} # => 1 (1..3).sum{|n| n**3} #=> 36 (1..3).sum(1){|n| n**3} #=> 36
  • 24. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Enumerable の拡張: 抽出 exclude? で要素が含まれていないときの判定ができる without を使うと、指定した要素を除外できる pluck メソッドで、指定したキーに基づく配列を返す 23 # exclude? は、include? の逆の動作 to_visit << node if visited.exclude?(node) # without ["David", "Rafael", "Aaron", "Todd"].without("Aaron", "Todd") # => ["David", "Rafael"] # pluck [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name) # => ["David", "Rafael", "Aaron"]
  • 25. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Hash の拡張: 抽出 Hash#reverse_merge はデフォルト設定のときに便利 except で不要な要素の除外、slice で必要な要素の抽出ができる extract は、ハッシュから取り除いた上でそのキーのペアを返す compact を使うと値が nil の要素を除外できる 24 # デフォルト値が左側で、右側がカスタマイズする引数 # 同じキーがあれば、右側が優先される options = {length: 30, omission: "..."}.merge(options) # reverse_merge を使うとデフォルト値が右側になり、見やすい options = options.reverse_merge(length: 30, omission: "...") # 破壊的に変更する options.reverse_merge!(length: 30, omission: "...") {a: 1, b: 2}.except(:a) # => {:b=>2} {a: 1, b: 2, c: 3}.slice(:a, :c) # => {:a=>1, :c=>3} hash = {a: 1, b: 2} rest = hash.extract!(:a) # => {:a=>1} hash # => {:b=>2} {a: 1, b: 2, c: nil}.compact # => {a: 1, b: 2}
  • 26. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 Hash の拡張: stringify、symbolize 文字列とシンボルの両方がキーになりえるとき、 stringify、symbolize で片方に寄せると扱いやすい with_indifference_access を使うと 文字列とシンボルのどちらでも使えるようにできる 25 {nil => nil, 1 => 1, a: :a}.stringify_keys # => {"" => nil, "1" => 1, "a" => :a} {nil => nil, 1 => 1, "a" => "a"}.symbolize_keys # => {nil=>nil, 1=>1, :a=>"a"} {nil => nil, 1 => 1, "nested" => {"a" => 3, 5 => 5}}.deep_symbolize_keys # => {nil=>nil, 1=>1, nested:{a:3, 5=>5}} {a: 1}.with_indifferent_access["a"] # => 1 # 文字列とシンボルの両方がありえる場合に、ベンリ def rewrite_path(options) options = options.symbolize_keys options.update(options[:params].symbolize_keys) if options[:params] ... end
  • 27. 大手町.rb #10 発表資料 「Active Support のコア拡張機能について」 まとめ 今日は Active Support のコア拡張機能について、 ピックアップして、紹介しました。 個人的には特に Object の拡張機能をよく使います blank?、present?、presence、with_options あと、 Hash の拡張もベンリです。 to_query、reverse_merge、except、slice、 with_indifferent_access ドキュメントを熟読しましょう! 気が付かなかった発見がたくさんあります。 私自身、たくさんありました 特に Rails Guide と Ruby on Rails API は必読です。 https://railsguides.jp/ https://api.rubyonrails.org/ 26