- Ruby / Rails関連
週刊Railsウォッチ(20180302)Ruby 2.6.0-preview1とWebpack 4.0リリース、爆速検索APIサービスAlgolia、Clowneでモデルをクローンほか
こんにちは、hachi8833です。Ruby生誕25周年おめでとうございます!
"Rubyはプログラミング言語の「塊魂」"は名言。
Link: ruby25/dave_thomas.en.md at master · ruby-no-kai/ruby25 https://t.co/tH54tCTytN
— Yukihiro Matzmotto (@yukihiro_matz) February 26, 2018
3月最初のウォッチ、いってみましょう。最近社内での記事つっつき会が盛り上がっていて嬉しい限りです。
Rails: 今週の改修
Rails 5.2はまだ動いています。「2月中に出したい」は叶いませんでした。以下は5.2のcommitからです。
紀元前の日付の扱いをPostgreSQLに合わせた
# activemodel/lib/active_model/type/date.rb#L44
def new_date(year, mon, mday)
- if year && year != 0
+ unless year.nil? || (year == 0 && mon == 0 && mday == 0)
::Date.new(year, mon, mday) rescue nil
end
end
つっつきボイス: 「出た〜紀元前!」「どこに使うんだろうか」「は〜ん、年を-4
みたいにできるようになったのか↓」
# activerecord/test/cases/adapters/postgresql/date_test.rb#L31
+ def test_bc_date_leap_year
+ date = Time.utc(-4, 2, 29).to_date
+ topic = Topic.create!(last_read: date)
+ assert_equal date, Topic.find(topic.id).last_read
+ end
PostgreSQLのdate
もdatetime
同様に無限値を扱えるようにした
# activerecord/lib/active_record/connection_adapters/postgresql/oid/date.rb
+# frozen_string_literal: true
+
+module ActiveRecord
+ module ConnectionAdapters
+ module PostgreSQL
+ module OID # :nodoc:
+ class Date < Type::Date # :nodoc:
+ def cast_value(value)
+ case value
+ when "infinity" then ::Float::INFINITY
+ when "-infinity" then -::Float::INFINITY
+ else
+ super
+ end
+ end
+ end
+ end
+ end
+ end
+end
つっつきボイス: 「どゆこと?」「PostgreSQLって'-infinity'::date
って書き方できるとは」「さすがぽすぐれ: 知らないと使わないだろうけど」「マイナスのInfinityもあると: そりゃそうだ」
# activerecord/test/cases/adapters/postgresql/date_test.rb#L6
+class PostgresqlDateTest < ActiveRecord::PostgreSQLTestCase
+ def test_load_infinity_and_beyond
+ topic = Topic.find_by_sql("SELECT 'infinity'::date AS last_read").first
+ assert topic.last_read.infinite?, "timestamp should be infinite"
+ assert_operator topic.last_read, :>, 0
+
+ topic = Topic.find_by_sql("SELECT '-infinity'::date AS last_read").first
+ assert topic.last_read.infinite?, "timestamp should be infinite"
+ assert_operator topic.last_read, :<, 0
+ end
「そういえばMySQLのdateは確か内部でstringになってて、マイナスすると9999みたいに9並びになっちゃう9999-99-99みたいなありえない日付のクエリでも通ってしまう」「えー」「PostgreSQLは確か型チェックか何かをやってて、9999はまだしも9999-99みたいなのになるとエラーになったと思う」
参考: MySQL 5.6マニュアル 11.3.1 DATE、DATETIME、および TIMESTAMP 型
DATETIME 値の範囲は '1000-01-01 00:00:00.000000' から '9999-12-31 23:59:59.999999' であり
MemCacheとRedisでローカルキャッシュのread_multi
とfetch_multi
をサポート
# activesupport/lib/active_support/cache/strategy/local_cache.rb#L123
+ def read_multi_entries(keys, options)
+ return super unless local_cache
+
+ local_entries = local_cache.read_multi_entries(keys, options)
+ missed_keys = keys - local_entries.keys
+
+ if missed_keys.any?
+ local_entries.merge!(super(missed_keys, options))
+ else
+ local_entries
+ end
+ end
つっつきボイス: 「RedisとかMemCacheのAPIで1個ずつアクセスするより一括で取ってくる方が速いんで、そうなるように拡張系の命令を使ったと: まあ書いてあるとおりですねw」
シリアライズのinclude:
が効かなくなることがある問題を修正
# activemodel/lib/active_model/serialization.rb#L180
unless includes.is_a?(Hash)
- includes = Hash[Array(includes).map { |n| n.is_a?(Hash) ? n.to_a.first : [n, {}] }]
+ includes = Hash[Array(includes).flat_map { |n| n.is_a?(Hash) ? n.to_a : [[n, {}]] }]
end
つっつきボイス: 「ネステッドなシリアライズかー」「ま、自分はシリアライズでJSONにしちゃうこと多いけど: ハッシュをシリアライズするよりJSONにしとけばRuby以外でも使えるし」「確かにー」
RuboCopの設定でFoo::method
スタイルを禁止に
# .rubocop.yml#L159
+# Prefer Foo.method over Foo::method
+Style/ColonMethodCall:
+ Enabled: true
RuboCopのデフォルト設定ではメソッド呼び出しの::
記法は禁止されていないんですね。
つっつきボイス: 「YAML::load
みたいな記法見たことあったな」「クラスメソッドならこの呼び方も一応できる」
::
は、定数(クラスやモジュールも含む)、コンストラクタ(Array()
やNokogiri::HTML()
など)の参照にのみ使う
Rubyスタイルガイドを読むより
Rails 6ではUTF-8エンコーディングを強制しなくなる
ここからはRails 6のmasterブランチです。
主要なWebサイトのほとんどでTLS 1.0が無効になったことで、IE8以下のブラウザの利用がどんどん困難になった。他のブラウザには影響しないので、UTF-8エンコーディングはデフォルトでは強制しないことにする。
Andrew White
つっつきボイス: 「『これでShift_JISで書けるぜ!』なんてことにはならないだろうけどね」「nil
で『強制しない』という意味なのか↓」
# actionview/lib/action_view/railtie.rb#L12
+ config.action_view.default_enforce_utf8 = nil
「昔話になっちゃうけど、ガラケー時代のエンコーディング周りはほんと地獄でしたねー: キャリアに応じてShift_JISで出力したりEUC-JPで出力したりとか、キャリアごとに顔文字変換するとか」「音符がうんこになるバグなんてのもありましたね」「そもそも携帯ネットワークはインターネットでもなければIPネットワークすらないし、RFC準拠とかなかったし」「ひえ〜」「メアドをRFC準拠の正規表現で処理したらユーザーからメアドが通らなくなったって苦情が来たり: 数字で始まったりドット2つ重ね..
みたいな非RFCなメアドが使われちゃってた」
参考: 【PHPで作る】初めての携帯サイト構築 - 第3回 携帯サイトの文字コードに気をつける
新機能: "rails routes --expanded
を追加
$ rails routes --expanded
--[ Route 1 ]------------------------------------------------------------
Prefix | high_scores
Verb | GET
URI | /high_scores(.:format)
Controller#Action | high_scores#index
--[ Route 2 ]------------------------------------------------------------
Prefix | new_high_score
Verb | GET
URI | /high_scores/new(.:format)
Controller#Action | high_scores#new
--[ Route 3 ]------------------------------------------------------------
Prefix | blog
Verb |
URI | /blog
Controller#Action | Blog::Engine
[ Routes for Blog::Engine ]
--[ Route 1 ]------------------------------------------------------------
Prefix | cart
Verb | GET
URI | /cart(.:format)
Controller#Action | cart#show
こんな感じで出せるそうです。
つっつきボイス: 「これうれしい!」「Route 1
はちょいダサかな」「いつものrails routes
だとURLがめちゃ長くなりますからね」
新機能: ActiveModel::Attributes#attributes
を追加
# activemodel/lib/active_model/attributes.rb#L69
+ def attributes
+ @attributes.to_hash
+ end
つっつきボイス: 「アトリビューツアトリビューツw」「何という名前」「その実態は#to_hash
と: ということはattributes
はハッシュじゃないのかな」「あと#to_hash
することでオブジェクトが別になるからdupしていることになる」
システムテストのスクショのパスを絶対パスに変更
ログからすぐ開くのに便利だからだそうです。
# actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb#L46
def image_path
- @image_path ||= absolute_image_path.relative_path_from(Pathname.pwd).to_s
+ @image_path ||= absolute_image_path.to_s
end
つっつきボイス: 「こういう変更は地味に大事!マジで」「Pathname.pwd
もUnixのシェルコマンドそのまんま」「先週のウォッチで出たrm_rf
みたい」
Rails
Rails 5.2.0の良スライド3本立て
- y-yagiさんのスライド2本: Rails 5.2.0について発表してきた | 日々雑記
- kamipoさんのスライド: Rails 5.2のActive Recordの改善
つっつきボイス: 「TechRachoでも5.2.0をまとめようと思ってたんですが、重要な部分はこのスライド3本でほぼ網羅されているんで、もういいかなと」「いいと思いまーす」「『ここを見ろ、以上』ということでー」
そのまま一同でしばしスライドつっつきになだれ込みました。
「apply_join_dependency
かー」「association scopeのJOINが無視されてた話とか、つらいなー」
Webpack 4.0がリリース
- Node JS 4のサポート廃止: 今後はNode >= 8.9.4で
- さよならCommonsChunkPlugin、こんにちはSplitChunksPlugin
- WebAssemblyをサポート
javascript/auto
などのModule Typeをサポートdevelopment
モードとproduction
モードを導入- webpack.config.jsでのエントリポイント定義が不要に
- ビルドの高速化
- プラグインシステムの刷新
- コマンド体系がwebpck-cliに全面移行(webpack-cliは今後インストール必須)
NoEmitOnErrorsPlugin
などの非推奨化
つっつきボイス: 「Node JS 4のサポート廃止は割りと大きいかも: これ系に依存してるのって結構あった気がする」「Zapierは"node.js v4.3.2"ってなってますね」「WebAssemblyもいいな」
書籍『99 Bottles of OOP』
名著『オブジェクト指向設計実践ガイド』でおなじみのSandi Metz女史の新刊が昨年から発売されています。ちょうど翻訳まで終えた記事「Why We Argue: Style — Sandi Metz」の末尾の広告で知りました。セールに気づけばよかった...
99 Bottles of OOP is 40% off through Dec 13 during our Half-Birthday Sale!
It's party time. 🎈🎉
Please enjoy a significant percentage of one🍻 on us.— Sandi Metz (@sandimetz) December 4, 2017
同書の章タイトルだけ自分用に雑に訳してみたのですが、場所をとるのでGistに置いてみました。
なお、同書のタイトルは以下の歌のもじりです。宴会で一気飲みを煽るときに歌うんでしょうか。
つっつきボイス: 「↑ジャケがいい」「酔っぱらいの歌ですな」
「前作『オブジェクト指向設計実践ガイド』は手続き脳が抜けきれてない私にはすごくよかったんで、くやしいけどこの本も定価で買っちゃいました」「ワタイも買ってたのに後忘れてたー」「そういえばJavaのインターフェースって特異だから、あの考え方を前提にするとRubyではどう適用したらいいのか最初よくわかんないかもしれないですね」「それはあるかも」
「たとえばPHPやPerlみたいな世界からRuby脳に変わるときにはオブジェクト指向設計ができてないといろいろ大変っすね: Rubyのライブラリがそもそもオブジェクト指向全開なものが多いし」「とにかくこういう本は一冊読んでおくべき」
参考:
ActiveRecord.no_touching
でtouchingを一時的に無効化する(RubyFlowより)
# 同記事より
user = User.find(user_id)
ActiveRecord::Base.transaction do
User.no_touching do
user.photos.find_each do |photo|
# userはtouchされない
photo.update!(some_attributes)
end
end
user.touch
end
つっつきボイス: 「む、サイトが開かない」「落ちてるかな?」
今は動いています。
参考: Rails API no_touching
KubernetesデプロイのためにRailsをリファクタリングした(RubyFlowより)
# 同記事より
require 'yaml'
require 'erb'
class ConfigParser
def self.parse(file, environment)
YAML.load(ERB.new(IO.read(file)).result)[environment]
end
end
つっつきボイス: 「Kubernetesはこれだけconfigしないといけない↓のが大変: それぞれenvをどうやって注入するかとか」「そういうコンテナサービスについて気を付けるべき点は例の超定番『The Twelve-Factor App』で言われてますね」
- ローカルアプリ
- Dockerコンテナを使うローカルアプリlocal app using docker containers
- docker-composeを使うローカルアプリ
- CapistranoをOpenStackとベアメタルサービスにデプロイ
- Kubernetesからminikubeと実際のクラスタにデプロイ
そういえばRuby25の会場でtagomorisさんが「クバネーティス」と発音していました。個人的には「クーベルネイテス」の方が何だかドイツ語っぽくてええかなという気もしたり(↓ギリシャ語由来だそうです)。
So kubernetes is pronounced /koo-ber-nay'-tace/ and means "sailing master"
Ok, that's a cool name!http://t.co/YIOwmfATQ6
— francesc (@francesc) July 11, 2014
タイムゾーン関連記事2本(Hacklinesより)
いずれも短い記事です。
# 同記事1より
class ApplicationController
around_filter :set_time_zone
private
def set_time_zone
old_time_zone = Time.zone
Time.zone = 'Asia/Kolkata' # current_user.time_zone
yield
ensure
Time.zone = old_time_zone
end
end
# 同記事2より
def in_time_zone(zone = ::Time.zone)
time_zone = ::Time.find_zone! zone
time = acts_like?(:time) ? self : nil
if time_zone
time_with_zone(time, time_zone)
else
time || self.to_time
end
end
つっつきボイス: 「うんうん、マルチロケールのアプリでこういうのやるよね: 弊社のManga Rebornでもそういうコード書いた覚えある」「記事1はTime.zone
使ってて、記事2はTime.zone
使うなin_time_zone
使えって言ってるー」
「Time.zone
ってクラス変数だった気がするんだけど、マルチスレッドだと死ぬやつじゃね?」「それともconfigか? configならスレッドスコープ」「あ、両方か↓: config.time_zone
とTime.zone
」「一時的に使うだけならTime.zone
でやるなということね」
# http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.htmlより
# application.rb:
class Application < Rails::Application
config.time_zone = 'Eastern Time (US & Canada)'
end
Time.zone # => #<ActiveSupport::TimeZone:0x514834...>
Time.zone.name # => "Eastern Time (US & Canada)"
Time.zone.now # => Sun, 18 May 2008 14:30:44 EDT -04:00
参考: Rails API in_time_zone
外部キーなしでActiveRecord関連付けを行う(RubyFlowより)
# 同記事より
def find_target
# ... あまり関係ないコードも混じってるのであしからず ...
sc = reflection.association_scope_cache(conn, owner) do
StatementCache.create(conn) { |params|
as = AssociationScope.create { params.bind }
target_scope.merge(as.scope(self, conn)).limit(1)
}
end
つっつきボイス: 「unscope
?」「unscope
は割りと使いますよ: デフォルトスコープのorderだけ消したりとか」「今はreorder
とかあるけど」
rails_refactor: 名前リファクタリングgem(Hacklinesより)
- 元記事: Rename Rails controllers, views and migrations with Rails Refactor - Fatos Morina
- リポジトリ: jcrisp/rails_refactor
https://www.youtube.com/watch?v=-sX05s0STs8
つっつきボイス: 「あー、これコントローラ名をリファクタリングするgemか」「IDEの機能一発でできるかなと思ったんですが」「できないんですねこれが: routes.rbとかビューとかあちこちリネームが必要になるんで地味ーに面倒」「ときどき直し漏れがあったり: でgit commit
するときに気づくと」
「まーGemfileに追加してまでやることかな?とは思う」「使い捨てですかね」「でもこの機能がRailsに標準で取り込まれるならわかるし、あったらすごくうれしい: rails generate rename
みたいな感じで」「あー!それ欲しいかもー!」
searchkick: ElasticsearchとRailsでインテリジェント検索(Awesome Rubyより)
- リポジトリ: ankane/searchkick
ankaneさん作のgemです。
# 同リポジトリより
# モデル
class Product < ApplicationRecord
searchkick
end
# インデックスにデータを追加
Product.reindex
# クエリ
products = Product.search("apples", fields: [:name])
products.each do |product|
puts product.name
end
つっつきボイス: 「へーこういう曖昧マッチが効くのか↓」「Elasticsearchのハンドラ的なやつっぽいけど、結構何でもできそうに見える」
- stemming -
tomatoes
matchestomato
- special characters -
jalapeno
matchesjalapeño
- extra whitespace -
dishwasher
matchesdish washer
- misspellings -
zuchini
matcheszucchini
- custom synonyms -
qtip
matchescotton swab
Clowne: Rubyモデルをクローンするgem(RubyFlowより)
- 元記事: Clowne: Clone Ruby models with a smile — Martian Chronicles, Evil Martians’ team blog
- リポジトリ: palkan/clowne
# 同記事より
# app/cloners/order_cloner.rb
class OrderCloner < Clowne::Cloner
include_association :additional_items
include_association :order_items, scope: :available
nullify :payed_at, :delivered_at
finalize do |source, record, _params|
record.promotion_id = nil if source.promotion&.expired?
record.uuid = Order.generate_uuid
record.total_cents = OrderCalculator.call(record)
end
end
Clowneは「道化師」(clown)とクローンを掛けてますね。
つっつきボイス: 「ははぁ、上の図↑みたいにリレーションがチェインしているものをクリーンにクローンできるってことか」「たとえばユーザーアカウントの項目が複数のテーブルでできていて、そのアカウントをコピーしたい、でもリレーション先のマスターはコピーしたくない、とか」
「ところで他人が書いたdupとかって基本信じたくないというのは、ありますね」「あーたしかにdeep copy的なのは自分で実装しないとコワイw」「ActiveRecordに特化してそういう部分をやりやすくしてくれるgemなんでしょう、きっと」「複雑なやつをいっぱいクローンしないといけないときとかにはありがたいかも」
「そういえばJavaだとこの手のcloneメソッドは自分で書かないといけないようになってましたね」「ですですー」
Overcommitで各種静的解析を呼んでRubyコードをlintする(Random Rubyより)
Git Hookを使ってコミット時のフックでRuboCopなどを呼んでいます。
つっつきボイス: 「社内で使ってた人がいたのを思い出したので」「Overcommitは、基本入れた方がいいですね: CIが重いとつらくなるけど」「CIがfailしたらgit commit
が失敗するようにしたり」「それはスバラシイ!」
「お、ちょうどいいところに: Overcommitって使ってみてどうでした?」「...みんなが使ってくれないと意味がないかも...」「あ確かに」「CI側をがっつり設定して、CIがfailするものをプッシュするとすごく怒られるようにしておけば、みんな自主的にこういうツールを使うようになるかも」
VAPIDでプッシュ通知
- 元記事: Using Web Push Notifications with VAPID - rossta.net
- RFC8292: VAPID -- Voluntary Application server Identification
# 同記事より
# app.rb
post '/push' do
Webpush.payload_send(
message: params[:message]
endpoint: params[:subscription][:endpoint],
p256dh: params[:subscription][:keys][:p256dh],
auth: params[:subscription][:keys][:auth],
ttl: 24 * 60 * 60,
vapid: {
subject: 'mailto:sender@example.com',
public_key: ENV['VAPID_PUBLIC_KEY'],
private_key: ENV['VAPID_PRIVATE_KEY']
}
)
end
正直、プッシュ通知しようとするサイトはむかつきますが。
つっつきボイス: 「RFCだから一応標準」「Webプッシュで認証/承認周りをやってくれるのね」
参考: Web PushをFCMとVAPIDで認証してブラウザにプッシュ通知を送る
Proxyパターンを再考する(Hacklinesより)
#prepend
をProxyパターンで使うお話です。
# 同記事より
module Proxy
require 'etc'
# Dynamically re-creates receiver's class methods, intercepts calls
# to them and checks user before invoking parent code
#
# @param receiver the class or module which has prepended this module
def self.prepended(receiver)
obj_mthds = receiver.instance_methods - receiver.superclass.instance_methods
obj_mthds.each do |m|
args = receiver.instance_method(m).parameters # => [[:req, :x], [:req, :y]]
args.map! {|x| x[1].to_s}
Proxy.class_eval do
define_method(m) do |*args|
puts "*** intercepting method: #{m}, args: #{args}"
raise "Unauthorised access!" unless Etc.getlogin == 'fred'
super(*args)
end
end
end
end
end #module
class Account
def initialize(balance)
@balance = balance
end
def deposit(amount)
@balance += amount
end
def withdraw(amount)
@balance -= amount
end
def self.interest_rate_for(a_balance)
a_balance > 10_000 ? '3.2%' : '5.5%'
end
prepend Proxy
end
つっつきボイス: 「変更前のコードの方、method_missing
してsend
するとかエグいなー: Javaのひとたちはこういうコードが許せなかったりとか?」「いやーそこまではないかもー」「これは認証のプロキシなのか!: 権限がなければraise
して、権限があればデレゲートすると」「天才か?」
「で変更後のコード↑はというと、method_missing
を使わずに、prepend
の中でclass_eval
やdefine_method
使ってやると」「たしかにー: 変更後の方がキレイ」「とってもProxyパターン」
参考: Module#prepend
CertBot: Let's Encrypt証明書をもっと楽に導入
certbot.eff.orgより: (CC BY)
Let's Encrypt Ruby on Rails and Nginxにしようかと思ってたのですが、記事中のこちらの方が気になったので。
主催しているEFFはElectronic Frontier Foundationという非営利団体です。
つっつきボイス: 「CertBotは有名っすね」「あれLet's Encrpyptコマンドじゃなかったっけ?」「↓名前変わってた...」「ややこしいのう」
Certbot クライアント(旧・Let's Encrypt クライアント)
https://letsencrypt.jp/command/より
「まあapt-cache search
してあるほうを入れればいいかとw」「多分ディストリビューション公式のパッケージ使う方がそのdistroのapache/nginxバージョンにちゃんと合わせられてるので、機能的な問題とかない限り、無理に最新にこだわらない方が安心して使えそう」
参考: Wikipedia-ja 電子フロンティア財団
dev.toは記事のソーシャル画像をこうやって自動生成している(Hacklinesより)
# 同記事より
def enter_urls
urls.each do |url|
3.times do
enter_url_and_click_preview("#{url}?#{rand(10_000)}=#{rand(10_000)}")
end
enter_url_and_click_preview(url)
end
end
つっつきボイス: 「SEO業界では記事の冒頭に何か大きい画像を置いとくとアクセスが増えるみたいなのがありますね」「神社の御札みたいなw」「まあ確かにそういう画像があると視線の取っ掛かりにはなりそう」「文字ばっかりの記事よりはデザイン的な座りもよくなりそう」「rand
かよ↑」
Railsコンソールで便利なヘルパーメソッドを書く(RubyFlowより)
オーストラリアの方だそうです。
# 同記事より
module ConsoleMethods
def load_jwt!
token = ::JWT.create(user_id: 'USER_ID_HERE')
RequestLocals.store[:jwt] = token.jwt
end
end
つっつきボイス: 「へーConsoleMethods
を拡張するとRailsコンソールでいろいろやれるのか」「Railsコンソールをそこまで使うかどうかというのはあるけど、利用頻度が高いならこうやってヘルパー化しとくといいかも」
RailsをOracleに接続する手順(RubyFlowより)
# 同記事より
default: &default
adapter: oracle_enhanced
database: "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(Host=localhost)(Port=1521))(CONNECT_DATA=(SID=xe)))"
development:
<<: *default
username: "myproject_development"
password: "myproject_development"
test:
<<: *default
username: "myproject_test"
password: "myproject_test"
production:
<<: *default
username: "myproject_production"
password: "myproject_production"
oracle-enhancedアダプタはdb:create
ができないらしいので、SQLで直接やってます。
つっつきボイス: 「来たなオラクル: 考えたくないヤツ」
Algolia: 爆速リアルタイム検索APIサービス
- 元記事: How to use Algolia without coupling to ActiveRecord::Base | Arkency Blog
- リポジトリ: algolia/algoliasearch-client-ruby
- サイト: https://www.algolia.com/
- デモサイト: https://www.algolia.com/product
とりあえずデモはめちゃめちゃ速いです。
つっつきボイス: 「そのデモサイトで適当に映画のタイトルぶっこんでみてください」「おーマジ速いわこれ!」「しかもUIカッケ~」「日本語だとあんまり引っかからないかも?」
「こういうの真面目にスクラッチから設計して作ってこれだけの性能出すのはタイヘン」「Solrとかカテゴリテーブルとか色々設計してSQLをWHERE文なりGROUP文なりを地獄のような感じで設計するとか」「有料だけどこれ使って速くなるなら使ってもええんじゃね?と思う」「裏でElasticsearchとか動いてるのかな」
redis-cell: Redisをコマンドラインで使える
redis-cell 0.2.2 is released, with some great contributions from the @CartoDB team for correctness at very fast replenish rates. Its code has also been modernized, Clippy (lint) integrated, and the latest Rustfmt conventions adopted.https://t.co/IHrTyNGR41
— Brandur (@brandur) February 28, 2018
- リポジトリ: brandur/redis-cell
とりあえず手元で動かしてみました。Java 8入れろと言われました。
つっつきボイス: 「libredis_cell.so
を読み出せる」「so
できる!」「これで差し替えっぽく使えるという感じかな」
MonitでRailsアプリを監視(RubyFlowより)
監視というとやっぱりイヌですね。
つっつきボイス: 「Monitなつかし!」「こないだSupervisor入れようと思ってたら環境古すぎてMonit入れたけどなっ」「Monitは定番、かつめちゃ歴史長い: いわゆるスーパバイザです」「↓こういう処理とか、やりたいと思うことはひととおり書ける優秀なヤツ」「configはところどころよくわからないけど」
<!-- 同記事より -->
<!-- config/deploy/shared/monit.erb -->
check host <%= fetch(:website_url) %> with address <%= fetch(:website_url) %>
if failed
icmp type echo count 5 with timeout 15 seconds
then alert
Datadog: サイト監視・分析サービス
いっぬがカワイイ。無料プランで5ホストまでできるそうです。
つっつきボイス: 「こっちの方がかわいかったので」「そこ!?」「このDatadogも定番: サービス監視/サイト監視にも使うし、メトリック監視にも使われる」
DHHとconcerns
僕がすごくかっこいいなと思うのはこういうmix-inが大量にincludeされてるコードですね https://t.co/4SXECsW7oB
— k0kubun (@k0kubun) February 21, 2018
I heard you liked concerns, so I put a few of them in Recording 😄 (This is the meta-data/meta-capabilities class for all concrete content classes in Basecamp). pic.twitter.com/XfXAdyXzJk
— DHH (@dhh) February 15, 2018
つっつきボイス: 「おー大量のconcern!」「mixinがとてもうまく書かれているとこうなる」「しかし1回しか使わないようなmixinをconcernにするかと言われると...」「ですねー」
「これ厳密にはconcernじゃないかもしれないっす: Basecampのディレクトリ構成って、app/の下にこの場合はRecordings(複数形)というディレクトリを作って、その下にこういうのが置かれていました」「へー!」「concernで置きまくるんじゃなくて、あるモデルの配下にそれ用のモジュールを入れるみたいなフォルダ構成なんで、それならまあありかなとは思いました」「あーモデル名と同じフォルダが別にあってその下に置くと: それならワカル」「つまりinclude
だけどあちこちで使われるんじゃなくて、あくまでそのモデル用のmixinか」「RuboCopの『1クラス100行制限』で怒られないためにはこのぐらい分散しないと」「例のYouTubeの番組を見た限りではそんな感じでした」
「このinclude
は互いの依存関係のあるなしに応じてきれいに書き分けられているからとても読みやすい」「ここまでキレイに書けたらスゴイ」「include
は順序変わると動かなくなったりしがちですね」
「ところでDHHのYouTubeチャンネル、早くも一週間ほど更新止まってますね(´・ω・`)」「こりゃスターウォーズばりに次回作待たされるかもww」
「あとDHHの書き方なんですが、もう全然TDDじゃないんですよ」「お?」「モデルのテストすら全部振る舞いベースで、unitテストを書かないんで、スゲーなーと」「まあ確かに、自分で書いていない、提供されている機能だけを使うんだったらそのunitテストってなくてもいいんじゃね?って思ったりするな」「おー」「実はunitテスト懐疑派w」「たとえばモデルをcreate
するテストとかは必要だと思うけど、そういうのはunitテストというより機能テストに近いんじゃないかな」
ここまでいける
今メンテしてるRailsアプリ、RubyもRailsも最新で、平均レスポンスタイムも20msで、テストも高速に走り、デプロイもかなり自動化されているという状態に来ており誰でも無限に生産性が出せる状態
— k0kubun (@k0kubun) February 27, 2018
つっつきボイス: 「ちゃんとメンテするとこのぐらいになるという見本」「しかし20msecはスゴイ」
Ruby trunkより
Ripperの新機能使いたいからnobuさんのパッチ使わせて
irbでRipperを使いたいそうです。確か今のirbはRubyで書かれた独自パーサーでした。
参考: Rubyリファレンスマニュアル Ripper
Ruby 2.5.0の「逆順バックトレース」がつらすぎる
「Railsで開発していると、バックトレースが逆順だったりそうでないところがあって頭がおかしくなりそう」だそうです。
つっつきボイス: 「何で逆順にしたんだろね?」「コールスタックを登っていく感じを出したかったとか?」
Ruby
Ruby 2.6.0-preview1がリリース(Ruby公式ニュースより)
#ruby25th 2.6.0-preview1 出たよ。 https://t.co/vekR4jz0uP
— みょうが@揚げ出しエンジニア (@mrkn) February 24, 2018
Ruby生誕25周年のその日にリリースされました。
- JITで
--jit-verbose=1
を指定可能に - 以下を含む新メソッド
- パフォーマンス向上
Proc#call
block.call
にブロックパラメータを渡した場合- ブロック渡しのパフォーマンス全般
- その他
$SAFE
がプロセスグローバルになり、0
を渡せるようになったERB.new
の引数の変更
とりあえず記念写真。
今、MJIT通の間での最新流行はやっぱり、 —jit-verbose=2、これだね。
—jit-verbose=2 —jit-save-temps。これが通の生成ソースの眺め方。— ( Φ _⊞) (@n0kada) February 26, 2018
SinatraベースのSmashingとWordPressとGitHubウィジェットでイケてるダッシュボードを作った(RubyFlowより)
マジックコメント一発でRubyを最適化
# 同記事より
# frozen_string_literal: true
HASH = {
"mike": 123
}
def getmike
HASH["mike"]
end
コメント欄で「細かい点がちょっと違うんじゃ?」とツッコまれています。
つっつきボイス: 「Ruby 2.2以降はハッシュキーのstring literalを自動でfreezeするのかー」「String.new
と空文字""
リテラルのエンコーディングは違う...だと?↓String.new
使わんけどなっ」「本編記事よりコメントの方が情報量多いかも」
String.new.encoding
# => #<encoding:ascii-8bit>
"".encoding
# => #<encoding:utf-8>
オブジェクト指向だと何ができるようになるか(Ruby Weeklyより)
これもSandi Metz女史のがっつり読み物系記事です。
Rack::Proxy
クイックツアー(RubyFlowより)
- 元記事: Rack Proxy Tour
- リポジトリ: ncr/rack-proxy
Rack Proxyはちょっと工夫するといい感じになるそうです。
- サブドメインベースで複数のアプリにパススルーする
- 移動したページへの面倒なリダイレクトルールを扱うのに便利
- 単一のAPIリクエストを複数のコンカレントバックエンドリクエストに分散し、結果をマージする
- 認証/承認をリクエストのプロキシより優先的に内部の信頼できるバックエンドに無条件に投げる
- あるドメインから別のバックエンドへのプロキシでCORSが複雑になるのを回避する
つっつきボイス: 「Rackミドルウェアでやるのは確かに簡単で便利: 裏を返すと、Nginxの設定がいかに死ぬほど特殊で面倒くさいかということでもある」「それこそApacheのmod_rewriteに匹敵する地獄感を味わえますよ」「sendmail.cfとか」
参考: Mozilla オリジン間リソース共有 (CORS)
Rubyで文字列の重複を削減する(Ruby Weeklyより)
# 同記事より
if ENV['RAILS_ENV'] != "production"
exec "RAILS_ENV=production ruby #{__FILE__}"
end
require 'memory_profiler'
MemoryProfiler.report do
# this assumes file lives in /scripts directory, adjust to taste...
require File.expand_path("../../config/environment", __FILE__)
# we have to warm up the rails router
Rails.application.routes.recognize_path('abc') rescue nil
# load up the yaml for the localization bits, in master process
I18n.t(:posts)
# load up all models so AR warms up internal caches
(ActiveRecord::Base.connection.tables - %w[schema_migrations versions]).each do |table|
table.classify.constantize.first rescue nil
end
end.pretty_print
frozen_string_literal: true
以外にもいくつかRubyの文字列のdupを防ぐ方法を試しています。
つっつきボイス: 「この+""
って書き方↓いつも不思議でしょうがないんだよなー」「どうしてこうなった感」
buffer = String.new
buffer.encoding => Encoding::ASCII-8BIT
# vs
# String @+ is new in Ruby 2.3 and up it allows you to unfreeze
buffer = +""
buffer.encoding => Encoding::UTF-8
Rubyで分散ファイル同期(Hacklinesより)
Ruby Distributed File SyncでRDFSだそうです。Dropbox的なことをやってみたかったとのこと。
つっつきボイス: 「こういうDropbox的なオープンソースソフトウェアありましたねー: 名前思い出せん...SynkThinkだ!」「割りとよくできますこれ: Win/Linuxでも使えるし」
Ruby 3のGuildとは
Ruby3のテーマとして分散処理の抽象化をどうするのかというのがあって、Guildというのを笹田耕一さんが作っているらしい。以前笹田さんに聞いたらGolangのchanですらポインタを渡すとメモリを自由に書き換えられて安全・簡単とはほど遠いので、もっと楽しく分散・並行が書けるようにしたいと言っていた
— 西村 賢🐠Coral Capital / Ken Nishimura (@knsmr) February 26, 2018
つっつきボイス: 「Guildの情報が意外に少なかったんですが、これが割りとまとまってるっぽかったので」
TruffleRuby Native
メモリ喰いの代わりに爆速で知られるTruffleRubyのネイティブオプションについての記事です。
MJIT記事の極めつけ
Ruby 2.6にマージしたJITに関する記事を書きました https://t.co/1fDlaMWMUr / I wrote an article about Ruby 2.6's JIT compiler https://t.co/9wXoOIB1g7
— k0kubun (@k0kubun) February 16, 2018
英語版まで出してます。
つっつきボイス: 「この間の翻訳記事↓より後に公開されててちょっとほっとしました」「MJITの作者自らの記事には勝てないっしょw」
こういう書き方
同僚が書いた Ruby コード、「外からアクセスしないインスタンス変数なのに attr_reader つけて内部からメソッド呼び出しする」とかしてなくて安心して読めるし変更できる
— Taiki (@taiki45) February 16, 2018
つっつきボイス: 「『とかしてなくて』w」「自分もアクセサでやっちゃったりするかなー: メンバ生で触るの怖いときとか」「まあ隠しとけと言えばそれまでだけど」
MatzのRuby25スピーチまとめ
日経でいい記事
Matzの半生が語られてそうな勢いで
これまでのRubyとこれからのRubyが事細かに書かれてる4日5時までは誰でも読めるようなので是非#Ruby25 #Matz #Rubyありがとう https://t.co/gaAjoWtl9k
— ゆっき@Moderna完全体 (@yucky_sun) March 1, 2018
週末のRuby25周年記念イベントのセッションをコンテンツとしてまとめました。10年前に比べると後方互換性を大事にしていて、それがRubyの立ち位置の変化を示してるなと思いました。Matz_botで技術的意思決定をする話ってどこまでネタなんでしょうかw@yukihiro_matz @miyagawahttps://t.co/pdSX4iQ64u
— 西村 賢🐠Coral Capital / Ken Nishimura (@knsmr) February 28, 2018
RubyKaigi 2018 CFP締め切りの駆け込みっぷりが凄い
あるあるとはいえ、笑ってしまいました。
SQL
「Why upgrade PostgreSQL?」: PostgreSQLのバージョンごとの修正点を比較表示できるサイト(Postgres Weeklyより)
つっつきボイス: 「これ便利かも」「出力はベタベタっすね...」「読みづらっ!」
(動画)KubernetesネイティブのPostgreSQL(Postgres Weeklyより)
AWS RDSがPostgreSQL 10をサポート(Postgres Weeklyより)
JavaScript
2018年のJavaScript事情(JavaScript Weeklyより)
Reduxの原則に沿ってReact.jsでフロントエンド検索ウィジェットを作る
Mozillaのsource/mapのパフォーマンスをRustとWebAssemblyで改善(JSer.infoより)
TypeScript Deep Dive
社内勉強会で TypeScript Deep Diveを読み始めた(厳密にはMacの音声再生で読み上げてもらっている)。ところどころいろんなものをdisっていて微妙に攻めてる。https://t.co/e9kYtsJM4t
— masa寿司 (@masa_iwasaki) February 26, 2018
- サイト: TypeScript Deep Dive
つっつきボイス: 「ところで音声読み上げってヒアリングの練習にいいかも」「最近の英語音声読み上げのクオリティ凄いし」
Vue.jsとVuexで自動セーブする
- 元記事: Autosaving with Vuex
CSS/HTML/フロントエンド
簡単なものはいずれ面倒になる(Frontend Weeklyより)
制約条件の理論をソフトウェアに適用する(Frontend Weeklyより)
「制約条件の理論」は経営寄りの概念だそうです。
参考: Wikipedia-ja 制約条件の理論
Utility-First CSSと関数型的CSS(Frontend Weeklyより)
Go言語だけでフロントエンドする
“Goだけで作るフロントエンド - GolangRdyJp” https://t.co/UDer51TScL
— mattn (@mattn_jp) February 27, 2018
- リポジトリ: gopherjs/vecty
先週取り上げたhttps://easydatawarehousing.github.io/ferro/にも通じそう(こちらはRubyとOpalとFerro)。
30 Seconds of CSS: CSSスニペットあんちょこサイト(GitHub Trendingより)
スニペット数はまだそんなにありませんが、1週間ほどで★1600超えです。
つっつきボイス: 「お、これも中々便利じゃん?」「この間の30 seconds of codeに通じますね」
Elm言語: ブラウザベースの純粋関数型言語
- サイト: http://elm-lang.org/
- Wikipedia-ja Elm (プログラミング言語)
- はじめに · プログラミング言語Elmの薄い本
Sandi Metz氏が最近関心を持っているとのことなので。
その他
SourceTree Windows版が更新
Diesel: Rust向けORM & クエリビルダ
@5t111111 #shinjukurb ということで、そういえば #ruby25 の懇親会で話していた Rust 製 ORM の Diesel の GitHub リポジトリです。Active Record のショーンが関わっているプロダクトなので地域.rb感ある、かつ Rust なのでとりあえずネタとして投下しておきます :-)https://t.co/Wq2s7QXaHf
— Koichi ITO (@koic) February 28, 2018
つっつきボイス: 「社内のRust勢向けにと思って」
Dockerイメージを小さくする3つのコツ
どのネットワークかと思ったら
ほとんどのネットワークはスケールフリーではない Scale-free networks are rare https://t.co/up9d9BeRRz https://t.co/JKCblIsJc8
— Haruhiko Okumura (@h_okumura) February 25, 2018
開発手法
好きな開発手法は「趣味の素振りで準備を終えておくとプロダクトはコストを掛けずに開発できる」です。
— Takafumi ONAKA (@onk) February 27, 2018
ITエンジニアには筋トレが大事
個人的にこのクソ忙しい2月末を迎えていいたいことは、一年筋トレしていて確実に体力が向上して稼働率上がっているので、筋トレで全ては解決するということです。
— masa寿司 (@masa_iwasaki) February 26, 2018
私も痛感しています。
つっつきボイス: 「筋肉といえば、ウェブ魚拓の人の筋肉の付き方はヤバイですね」「ガチムチやん...」
コアもOSもシェルも自作
Six Degrees of Wikipedia: Wikipediaの記事のつながりをグラフ表示
- サイト: https://www.sixdegreesofwikipedia.com/
- リポジトリ: jwngr/sdow
よくあるやつといえばそれまでですが、めちゃめちゃ速いです。
Hemingway.app: 英文添削できるエディタ
ちなみに世にあるエッセイ向け英文スタイルガイドの種本のほとんどは、The Elements of Styleだったりします。もう100年近いロングセラー。
論文だとChicago Manual of Styleが定番だったかな。
「パスワード無期限」が推奨に
マイクロソフトがついにパスワード無期限を推奨事項としてO365の管理画面に出してくれた!!素晴らしい!!! pic.twitter.com/GqRNv7uOqu
— Masahiko Ebisuda(胡田昌彦)|Microsoft MVP(2014~) (@ebi) February 27, 2018
番外
GitHub issueをブログ代わりに
- issue: onmyway133/blog/issues
内容よりそっちがびっくりだったので。
prompts: JSらしいプロンプト(GitHub Trendingより)
- リポジトリ: terkelg/prompts
AppleのクラウドはGoogleのクラウド
参考: Appleのクラウドサービス「iCloud」がGoogleのクラウドを利用していることが正式に明らかに - GIGAZINE
敷き詰め問題
敷き詰め問題の一種である、「出来る限り小さい正方形の中にn個の正方形をどう敷き詰めるか」という問題についてのページが面白い。https://t.co/FgxwNmFtAK
11あたりから直観的ではない形になり、30を超えてくるあたりからなぜか笑えてくる。 pic.twitter.com/d0dacLIoRL— 横山 明日希 (@asunokibou) February 25, 2018
これ系の問題はたいてい難問になってる気がします。
つっつきボイス: 「先に進むとヤケクソで並べたようなヤツとかあるなー確かに」「草」「この直感に反する感がタマラン」
「プログラマーの誓い」
- リポジトリ: Widdershin/programmers-oath
私はプログラマーとして、以下の誓約を果たすことを誓います。
* 仕事を誠実に、かつ倫理から逸れぬよう進めます。人々に害をなすいかなる要求にも従いません。
* 先人の学びを尊重し、かつ自分の学びを後進と共有します。
* プログラミングは技術であると同時に、科学であり、思いやりであり、共感でもあることを決して忘れず、精巧なアルゴリズムや技術上の論争よりも理解することの方が重要であることも決して忘れません。
* 「わかりません」と言うことを恥じず、困ったときは的確に支援を求めます。
* ユーザーのプライバシーを尊重します。プライバシー情報は、たとえ世界中が知っていようとも自分には明かされないものだからです。
* あらゆる物事を生涯にわたって注意深く扱い、自分がミスをする可能性があることを謙虚に認めます。
* コンピュータのためでなく、人間のためにコードを書くことを決して忘れません。
* 自分の書くコードや自分の行いがもたらす可能性のある結果について常に配慮し、社会的な問題と技術上の問題、どちらの困難についても一方を軽んずることなく同様に尊重いたします。
* 誇りを失わず、勤勉に仕事に専念いたします。
* 自分がいつかは間違いを犯し、間違ったまま進む可能性があることを認めます。先入観に囚われず、誰の言葉であっても決して侮ることなく尊重し注意深く耳を傾けます。
同リポジトリより: 大意
ひと目で分かるヒポクラテスの誓いのもじりですね。
蛇腹型ロボット
マヤ文字作文
ほんとすごいので時間ある人は、明日六本木AXISの地下にいってほしい…。
武蔵野美術大学の視デ所属の鈴木さんは、今回の卒制では古代マヤ文明の年表を、マヤ文字と絵を使って表現してます。驚くのは、これは模写とかじゃなくて、オリジナル。つまり自分でマヤ文字で作文し、デザインしてるんです…。 pic.twitter.com/mvNnsTsePG
— 角尾 舞 | Mai Tsunoo (@ocojo) February 26, 2018
つっつきボイス: 「そういえば最近カクヨムで読んでるこの小説↓、解説も凝ってて言語マニアにはたまらんかもですヨ」
紙辞書の早引き私も習得したいところだ。
#88 彼女は異教徒を殲滅するつもりだ - 異世界転生したけど日本語が通じなかった - カクヨム https://t.co/Tnhuz8wE1s
— Fafs F. Sashimi@neffirlexesykerl maccafirlexerl (@sashimiwiki) February 28, 2018
今週は以上です。
バックナンバー(2018年度)
週刊Railsウォッチ(20180223)Ruby25開催、Rails6のパラレルテスト、書籍「RSpecによるRailsテスト入門」更新ほか
- 20180216 Rails 5.1.5リリース、DHHのYouTubeチャンネルは必見、Ruby Toolboxが運営再開ほか
- 20180209 RubyにMJIT初マージ、高速JSON API gem、Railsにparallel-testingブランチほか
- 20180202 Rails 5.2.0 RC1と5.1.5.rc1リリース、Rails 6開発開始、メソッド絵文字化gemほか
- 20180126 Bootstrap 4登場でbootstrap_form gemが対応、PostgreSQLやnginxの設定ファイル生成サービスほか
- 20180119 derailed_benchmarks gem、PostgreSQLをGraphQL API化するPostGraphile、機械学習でモック画像をHTML化ほか
- 20180112 update_attributeが修正、ぼっち演算子
&.
はObject#try
より高速、今年のRubyカンファレンス情報ほか
今週の主なニュースソース
ソースの表記されていない項目は独自ルート(TwitterやRSSなど)です。