週刊Railsウォッチ(20180223)Ruby25開催、Rails6のパラレルテスト、書籍「RSpecによるRailsテスト入門」更新ほか

こんにちは、hachi8833です。いよいよ明日はRuby25ですね。名札忘れないようにしないと。

Rails: 今週の改修

今週は公式情報の他、Rails 6向けのmasterブランチからも見繕いました。文字列のfreeze化やシンボル化によるパフォーマンス向上作業が盛んなようです。

#create_or_find_by先週取り上げたのでなしです。


つっつきボイス: 「う、先週は#create_or_find_byのあたりチェックできなかったー」

Railsのテストをパラレル化

miniTestのパラレルexecutorを直接使っているとのことなのでminiTest用ですね。サムズアップ👍が大量に付いてます。

class ActiveSupport::TestCase
  parallelize(workers: 2)
end
class ActiveSupport::TestCase
  parallelize(workers: 2)

  parallelize_setup do |worker|
    # create a db w/ worker. Runs after processes are forked
  end

  parallelize_teardown do |worker|
    # delete the test databases or other cleanup. Runs before processes are closed
  end
end

つっつきボイス: 「やっぱりminiTestかー」「話逸れるんですが、こういう見出しを見るとRailsアプリのテストの話なのかRailsフレームワークそのもののテストの話なのかつい考えちゃいますね」

ActiveJob引数のカスタムシリアライズ

class MySpecialSerializer
  class << self
    # Check if this object should be serialized using this serializer
    def serialize?(object)
      object.is_a? MySpecialValueObject
    end

    # Convert an object to a simpler representative using supported object types
    # Recommended representative is a Hash with a specific key. Keys can be of basic types only
    def serialize(object)
      {
        key => ActiveJob::Serializers.serialize(object.value)
        'another_attribute' => ActiveJob::Serializers.serialize(object.another_attribute)
      }
    end

    # Check if this serialized value be deserialized using this serializer
    def deserialize?(object)
      object.is_a?(Hash) && object.keys == [key, 'another_attribute']
    end

    # Convert serialized value into a proper object
    def deserialize(object)
      value = ActiveJob::Serializers.deserialize(object[key])
      another_attribute = ActiveJob::Serializers.deserialize(object['another_attribute'])
      MySpecialValueObject.new value, another_attribute
    end

    # Define this method if you are using a hash as a representative.
    # This key will be added to a list of restricted keys for hashes. Use basic types only
    def key
      "_aj_custom_my_special_value_object"
    end
  end
end

上のようなカスタムシリアライザを書いて以下のように引数で渡せるようになりました。

ActiveJob::Base.add_serializers(MySpecialSerializer)

つっつきボイス: 「この引数部分がっつり書き直したそうです」「ジョブ自体のシリアライザを自分で書けるようになったのか!」「今までジョブの方でシリアライズしていたのが、こうやって共通部分で自由にシリアライズできるようにするというのはいかにもオブジェクト指向的」

RedisCacheStoreのコネクションプールをサポート


つっつきボイス: 「Railsのコネクションプールの話、前にもウォッチで取り上げたような気がするけど別の話だったかな…」「それはDBのコネクションプールでは?」「あ、それでした」「connection_poolってgem初めて見たナ」

# activesupport/lib/active_support/cache.rb#:163
+      class << self
+        private
+          def retrieve_pool_options(options)
+            {}.tap do |pool_options|
+              pool_options[:size] = options.delete(:pool_size) if options[:pool_size]
+              pool_options[:timeout] = options.delete(:pool_timeout) if options[:pool_timeout]
+            end
+          end
+
+          def ensure_connection_pool_added!
+            require "connection_pool"
+          rescue LoadError => e
+            $stderr.puts "You don't have connection_pool installed in your application. Please add it to your Gemfile and run bundle install"
+            raise e
+          end
+      end

関係ありませんが、conversationの末尾でよそのリポジトリがぴょこっと顔を出していますね。

Rails 6ではRuby 2.4.1以降が必須に

2.4.0までの"symbol_from_string".to_sym.dupバグを避けるためだそうです。

# activesupport/lib/active_support/core_ext/object/duplicable.rb#L76
 class Symbol
   begin
-    :symbol.dup # Ruby 2.4.x.
-    "symbol_from_string".to_sym.dup # Some symbols can't `dup` in Ruby 2.4.0.
+    :symbol.dup
+
+    # Some symbols couldn't be duped in Ruby 2.4.0 only, due to a bug.
+    # This feature check catches any regression.
+    "symbol_from_string".to_sym.dup
   rescue TypeError

同時に、ActiveSupportのHash#transform_valuesが非推奨化されています。

# activesupport/lib/active_support/core_ext/hash/transform_values.rb#L3
-class Hash
-  # Returns a new hash with the results of running +block+ once for every value.
-  # The keys are unchanged.
-  #
-  #   { a: 1, b: 2, c: 3 }.transform_values { |x| x * 2 } # => { a: 2, b: 4, c: 6 }
-  #
-  # If you do not provide a +block+, it will return an Enumerator
-  # for chaining with other methods:
-  #
-  #   { a: 1, b: 2 }.transform_values.with_index { |v, i| [v, i].join.to_i } # => { a: 10, b: 21 }
-  def transform_values
-    return enum_for(:transform_values) { size } unless block_given?
-    return {} if empty?
-    result = self.class.new
-    each do |key, value|
-      result[key] = yield(value)
-    end
-    result
-  end unless method_defined? :transform_values
+require "active_support/deprecation"

今週の他の修正でも2.4.1+対応のものが目立ちます。


つっつきボイス: 「Rails 6はRuby 2.4.1以降か」「今はいくつ以上だったかな: こういうのはたいていRailsガイドのGetting Start的なところに書いてあるはず: カレントの5.1系はRuby 2.2.2以降、と」

「(見学の方に)軽く説明すると、その昔Rubyは1.8から1.9になるときにbreaking changesが結構発生したことがあったんですよ: ハッシュの順序が保証されたのとかはかなり大きかった」「その頃にうちの会社でRailsを使い始めたんですが、それ以降のRubyではそこまで大きな変更は起きてないですね」

「RailsではRubyの機能を拡張して使っているところがあちこちにあるんですが、そうした機能の一部が後にRubyの方に採用されるなんてこともちょくちょくあったりしますね」「Rubyだと配列の#first#lastが取れるんですが、RailsのActiveSupportだと#second#thirdなんてのも取れます」「一種のジョークですけど#forty_twoなんてのもありますね」

「Rubyはバージョンアップされるたびに速くなってますね」「私のオレオレRailsアプリでも、2.5にアップグレードしただけで体感できましたね」

参考: Wikipedia-ja: 42

参考: Hash#transform_values

Ruby 2.5のString#-@でパフォーマンス改善

# actionpack/lib/action_dispatch/journey/scanner.rb#L37
+        # takes advantage of String @- deduping capabilities in Ruby 2.5 upwards
+        # see: https://bugs.ruby-lang.org/issues/13077
+        def dedup_scan(regex)
+          r = @ss.scan(regex)
+          r ? -r : nil
+        end

つっつきボイス: 「dedup!聞いたことない言葉」「雰囲気は伝わるかなー」「stringのdedupの方だったか」

ちょっと紛らわしいですが、String#-@は単項演算子を再定義するときの-@という記法とは別です。

- self -> String | self
self が freeze されている文字列の場合、self を返します。 freeze されていない場合は元の文字列の freeze された (できる限り既存の) 複製を返します
https://docs.ruby-lang.org/ja/2.5.0/method/String/i/=2d=40.htmより

#13077で当初#fstringというメソッド名が提案され、最終的にString#-@に落ち着いたようです。

fstringというメソッド名は確かによくない」「でも-ならいいのか?という疑問はある」

「今さらですが、単項演算子の再定義って+@-@ぐらいしか見たことなかったけど、他にもできる記号あるんですね↓」「[]なんかも再定義できるのがいい」

# https://docs.ruby-lang.org/ja/latest/doc/spec=2foperator.html より
    |  ^  &  <=>  ==  ===  =~  >   >=  <   <=   <<  >>
    +  -  *  /    %   **   ~   +@  -@  []  []=  ` ! != !~

ivarをシンボルにしてdupを減らす

# activesupport/lib/active_support/core_ext/class/attribute.rb#L98
       singleton_class.silence_redefinition_of_method("#{name}?")
       define_singleton_method("#{name}?") { !!public_send(name) } if instance_predicate

-      ivar = "@#{name}"
+      ivar = "@#{name}".to_sym

       singleton_class.silence_redefinition_of_method("#{name}=")
       define_singleton_method("#{name}=") do |val|

(ドキュメント)結合テストでのActiveStorageファイルクリーンアップはこういう感じで

# guides/source/active_storage_overview.md#L559
+Discarding Files Stored During Integration Tests
+-------------------------------------------
+
+Similarly to System Tests, files uploaded during Integration Tests will not be
+automatically cleaned up. If you want to clear the files, you can do it in an
+`after_teardown` callback. Doing it here ensures that all connections created
+during the test are complete and you won't receive an error from Active Storage
+saying it can't find a file.
+
+```ruby
+module ActionDispatch
+  class IntegrationTest
+    def remove_uploaded_files
+      FileUtils.rm_rf(Rails.root.join('tmp', 'storage'))
+    end
+
+    def after_teardown
+      super
+      remove_uploaded_files
+    end
+  end
+end
+```

Railsガイドの更新です。


つっつきボイス: 「ところで↑上の#rm_rfっていうRubyのメソッド名はアツいですねー: Unix使ってれば意味は間違いなくわかるんだけど」「心がざわつく名前…」「そこがRubyっぽいとも言える」

Object#blank?のモンキーパッチを削除

# activesupport/lib/active_support/values/time_zone.rb#L3
 require "tzinfo"
 require "concurrent/map"
-require "active_support/core_ext/object/blank"

rails gで名前空間が指定されていると不要なルーティングが生成されていたのを修正

# railties/lib/rails/generators/rails/controller/controller_generator.rb#L17
       def add_routes
         return if options[:skip_routes]
+        return if actions.empty?
         route generate_routing_code
       end

つっつきボイス: 「これはrails gの挙動ですね」「ぱっと見で実行時の話かと思ってた: 失礼しましたー」

# railties/test/generators/controller_generator_test.rb#L112
+  def test_does_not_add_routes_when_action_is_not_specified
+    run_generator ["admin/dashboard"]
+    assert_file "config/routes.rb" do |routes|
+      assert_no_match(/namespace :admin/, routes)
+    end
+  end

ActiveSupport::MultibyteのUnicodeテーブルを削除

# activesupport/lib/active_support/multibyte/unicode.rb#L14
       # The Unicode version that is supported by the implementation
-      UNICODE_VERSION = "9.0.0"
+      UNICODE_VERSION = RbConfig::CONFIG["UNICODE_VERSION"]

大文字小文字変換などの対応をRubyに任せることにしたようです。ごっそり削除されています。


つっつきボイス: 「へー、UNICODE_VERSION = RbConfig::CONFIG["UNICODE_VERSION"]なんて書き方できるのか!Rubyすごい」「RubyのUnicode実装がよくなったから今後はそっちを信用するようになった、と」「今まではRails側でその場しのぎ的な対応してたみたいですね」「ハングルがらみのパッチなんかも削除されてる」

Rails

Railsのビューをもっとオブジェクト指向っぽくするには(RubyFlowより)

#同記事より
--order
  |--views
  |  |--partials
  |  |  `--status_history.slim
  |  |  `--calls_history.slim
  |  |  `--cart.slim
  |  |  `--contact_information.slim
  |  |  `--shipping.slim
  |  `--show.slim
  `--cell.rb
/ show.slim

= render(‘partials/status_history.slim’)
= render(‘partials/calls_history.slim’)
= render(‘partials/contact_information.slim’)
= render(‘partials/cart.slim’)
= render(‘partials/shipping.slim’)

つっつきボイス: 「ビューでオブジェクト指向…?w」「あーなるほど、ビューのパーシャルをなるべくオブジェクト単位にしようぜって話か」「まあ管理画面ぐらいならわかるけど、これやると画面デザインに制限がかかっちゃうから難しいところではある」
「『オブジェクト指向』というほどでもない気はするなー」「タイトルのviewが『見た目』の掛け言葉になってるのかもしれないですね: オブジェクト指向『っぽい』みたいな」

「ちなみにパーシャルは作りすぎるとレンダリングのパフォーマンスが激落ちしますヨ: やるならちゃんとキャッシュに乗せるとかしないと」

Value ObjectとRails 5のAttributes APIでRubyの文字列リテラルを消し去る(RubyFlowより)

「やりすぎではない、と思う」そうです。

# 同記事より
class Plan::Channel < ApplicationRecord
  TYPES = %w(
    direct
    broker
    correspondent
    bdr
    non_funded_origination
  ).freeze

  self.inheritance_column = nil

  belongs_to :plan

  TYPES.each do |type|
    scope type, -> { where(type: "#{type}") }
  end

  attribute :tiers, Plan::Channel::Tiers::Type.new
  attribute :calculation_method, Plan::Channel::CalculationMethod::Type.new
end

つっつきボイス: 「ははーんenumの扱い的な話か、わかるわかる」「ちなみに自分はstring literalの方が楽でいいじゃんと思う派で、kazzさんはValue Object派」「何とw」
「(見学者の方から)freezeって定数化ですか?」「freezeは定数化ではなくて変更できなくするやつですね: Rubyを真面目にやるとわかると思いますが、恐ろしいほど動的にいろんなものが変わるんで、特に宣言的なものはこうやってfreezeするんですよ」
「で、Value Objectを使うとモデルがこうやってすっきり書ける↓、と」

# 同記事より
class Plan::Channel < ApplicationRecord
  belongs_to :plan

  Plan::Channel::Source.values.each do |source|
    scope source, -> { where(source: "#{source}") }
  end

  attribute :tiers, Plan::Channel::Tiers::Type.new
  attribute :calculation_method, Plan::Channel::CalculationMethod::Type.new
  attribute :source, Plan::Channel::Source::Type.new
end

Railsのafter_commitRubyFlowより)

おなじみEvilmartiansがdev.toに記事書いてますね。

# 同記事より
def pay(user, order_params)
  Order.transaction do
    order = order.new(order_params)
    order.save!

    ActiveRecord::Base.connection.add_transaction_record(
      AfterCommitWrap.new { PaymentsService.charge!(user, order) }
    )
  end
end

つっつきボイス: 「モデル側にafter_commitがなくても、こんなふうにトランザクションの外でadd_transaction_recordafter_commit的なものを仕込めるってことか: これはキワドイ」

「ところでRuby界隈ってVladimirって名前の人を複数見かける気がしません?」「ロシア系ですごく多い名前ですね: あだ名化するとVlad(ブラッド)」

バックグラウンドジョブのログをいい感じに取る(RubyFlowより)

# 同記事より
module WithJobLogging
  def log_retryable_job(jid, job_type, user_id = nil)
    create_async_job_log(jid, job_type, user_id) unless async_job_log(jid)
    yield
    mark_job_as_finished(jid)
  end

  def create_async_job_log(jid, job_type, user_id = nil)
    AsyncJobLog.create(
      jid: jid,
      state: 'started',
      job_type: job_type,
      user_id: user_id
    )
  end

  def async_job_log(jid)
    AsyncJobLog.find_by(jid: jid)
  end

  def mark_job_as_finished(jid)
    async_job_log(jid).finished!
  end
end

つっつきボイス: 「ログってワーカーが複数になると混じっちゃうんで、テーブルに保存すればレコード単位になることは保証できる: たぶんそういうのをやりたいんだと思う」「まあfluentdとか使えば何の問題もなくできるやつ」
「ところがこれだとトランザクションが失敗したときみたいな異常時にログを取りようがないんですね」「なのでファイルに出すログも必要: 生ログを追うのは大変だけど」

isolator: DBトランザクションからアトミックでないやりとりを検出するgem

# 同リポジトリより
# HTTP calls within transaction
User.transaction do
  user = User.new(user_params)
  user.save!
  # HTTP API call
  PaymentsService.charge!(user)
end

#=> raises Isolator::HTTPError

# background job
User.transaction do
  user.update!(confirmed_at: Time.now)
  UserMailer.successful_confirmation(user).deliver_later
end

#=> raises Isolator::BackgroundJobError

つっつきボイス: 「SQLのトランザクション内で、HTTPアクセスみたいなSQLから外れるものがあったら検出してくれるということか」「raiseしちゃっていいんだろうか?検出だからCIで使うんだろうけど」「お、ここ↓で設定できる: よしよし」「なかなかよさそうなgem」

# 同リポジトリより
Isolator.configure do |config|
  # Specify a custom logger to log offenses
  config.logger = nil

  # Raise exception on offense
  config.raise_exceptions = false # true in test env

  # Send notifications to uniform_notifier
  config.send_notifications = false
end

「Everyday Rails – RSpecによるRailsテスト入門」が更新


leanpub.com/everydayrailsrspec-jpより


つっつきボイス: 「RSpec 3.6やRails 5.1に対応したそうです」「RSpec本って当たりの本と、量が多い割に中身の薄いハズレの本があった気がするんだけど、これはどっちだったかな: 当たりの方だった!」「@jnchitoさんの翻訳本ですね」

私も以前買ってたので早速更新版PDFをダウンロードしました。

action_args: Railsコントローラが受け取るparamsをシグネチャ的に扱えるgem

# 同リポジトリより
class UsersController < ApplicationController
  # the `page` parameter is optional
  def index(page: nil)
    @users = User.page(page).per(50)
  end
end

つっつきボイス: 「はてブで反響呼んでますね」「ブコメにもあるけど、これはうまくハマるときれいだけど、そうじゃない場合は微妙かなーと思ってます」「これもブコメにありますが、Railsに最初からあればよかったのかも」

Active Adminの月間ダウンロード数が昨年の倍に(RubyFlowより)


同記事より


つっつきボイス: 「Active Adminは割りと定番: ただデフォルトのままだとproductionで使いづらいのはどの管理画面gemでも変わらないですけどね」

text diffを%で得る(RubyFlowより)


blog.botreetechnologies.comより

以下のライブラリを使っているそうです。


つっつきボイス:Levenshtein distance、聞いたことぐらいはあったかも: 実務じゃ使わないだろうけど」「このアルゴリズム知らなかった…Needleman/Wunschで文字単位diffやったことはあったけど」

「いろんなdiff距離がある: HealedSealedがどれだけ似てるか↓みたいな感じ」「それにしてもtextっていうgem名はググラビリティなさすぎw」「探して欲しくないんでしょうかね」

# threedaymonk/text
white = Text::WhiteSimilarity.new
white.similarity('Healed', 'Sealed')   # 0.8
white.similarity('Healed', 'Help')     # 0.25

FaktoryワーカーをAWS Fargateにデプロイする(Hacklinesより)

昨年末のウォッチで取り上げたFaktoryが流行りつつあるようです。


つっつきボイス: 「AWS Fargateはつい最近リリースされたサービスですね: ECSみたいに自前で建てなくてもコンテナだけで動かせる、GoogleのGKEに近いやつだったと思う」

参考: AWS Fargate — サーバーやクラスターの管理が不要なコンテナの実行
参考: Google Kubernetes Engine — Google Cloud 上の Kubernetes を利用してコンテナ化されたアプリケーションをデプロイ、管理、スケール

Railsアプリの「ハードモード」アップグレード(Hacklinesより)

この間ウォッチで紹介したUpgrading a Rails application incrementally(現在翻訳中)を先に読むと倍楽しめるそうです。


つっつきボイス: 「Railsのアップグレードは常にハードモードだけどな(キリッ」「Rails 3.2から4.2のアップグレードだと、大きい壁は2つぐらいあったかな」「これがRails 3.0だと、3.0と3.1の間にとてつもなく高い壁がある: アセットパイプライン周りとか」
「『rebase、rebase、rebase』…」「俺たちこんなにつらかったよ、っていうつらみレポート」

ActiveSupportとReactを使ったRailsチャットアプリを10分で作る(Ruby Weeklyより)


engineering.musefind.comより

health_check: シンプルなヘルスチェックgem

昨日のBPS社内勉強会でリバースプロキシ絡みのヘルスチェックについて言及されたので貼ってみました。

curl localhost:3000/health_check
success

curl localhost:3000/health_check/all.json
{"healthy":true,"message":"success"}

curl localhost:3000/health_check/database_cache_migration.xml
<?xml version="1.0" encoding="UTF-8"?>
<hash>
  <healthy type="boolean">true</healthy>
  <message>success</message>
</hash>

つっつきボイス: 「ヘルスチェックのフォーマットがリバースプロキシと合うならこういうのを使ってもいいかも: ぶっちゃけ自分で書いたヘルスチェックの方がRackから直接返すからフットプリント小さいけど」
「ヘルスチェックの処理が重くてアプリサーバーまで遅くなると本末転倒だし、かといって頻度を下げると検出も遅れるのでそういう設定は悩みどころではある」

log_analyzer: CLIベースのRails簡易ログアナライザ(RubyFlowより)


igorkasyanchuk/log_analyzerより


つっつきボイス: 「もしかして似たようなのがいっぱいあるのかなとは思いつつ貼ってみました」「お、悪くなさそう: 少なくともgrepで頑張って集計するよりはずっといい」「まともに運用で使うならNewRelicとか使うべきだけど、developmentで入ってれば使うかも」「常備薬的にとりあえず入れておいて損はない感じですね」

DHHツイートより

今回YouTubeチャンネルのシリーズを始めた動機はまさにそれ。中級プログラマーが「ベストプラクティス」を無批判に盲信することについて疑問を呈したい。

どんなベストプラクティスでも、それと真逆のアプローチの方が有効な場合がある。そういう方面を追求しなくなったら開発者の成長はそこで止まる。ベストプラクティスと呼ばれているものの大半は、別の時代や言語や分野から「カーゴカルト」的に(=よく吟味されずに)持ち込まれたものであり、そこにはサービスの進歩はない。
ツイートの大意


つっつきボイス: 「デザインパターンぐらいのレベルならベストプラクティスもありうるけど、もっと大きな設計になってくると何がベストかはそのときで違ってくるというのはありますね」

Ruby trunkより

MJITがらみのissue

RubyGems高速化のためにiseq読み込みやキャッシュをコアに置きたい

File#path.tainted?File#to_path.tainted?が元の汚染状態を反映していない — 進行中

# 上より
#!/usr/bin/ruby -w
$SAFE = 1
path = './myfile.txt'
file = File.open(path, 'r')
File.exist?(file.path)
./to-path.rb:5:in `exist?': Insecure operation - exist? (SecurityError)
  from ./to-path.rb:5:in `<main>'

つっつきボイス:taint使ったことなかった」「へえぇこんなメソッドあるのか: しかもObjectだし」

参考: Object#taint

2.5.0の正規表現修正を2.4.3にもバックポート希望

puts RUBY_VERSION
p %w[+ é +].grep(/[[:punct:]]/)
2.3.5
[]

2.4.3
["+"]

2.5.0
["+", "+"]

つっつきボイス:éのところでマッチがつっかえてる」「正規表現絡みはなー、いろいろツライ」

$はus-asciiだと記号扱いでUTF-8だと記号扱いされないがいいか? -> 現状ママ

これも古いissueです。仕様レベルで違うということでrejectです。

# encoding: us-ascii
puts '$' =~ /\p{Punct}/ ? 'match' : 'no match'
# encoding: utf-8
puts '$' =~ /\p{Punct}/ ? 'match' : 'no match'

参考: POSIXでの定義
参考: Unicodeでの定義

Ruby

RubyGemに複数の脆弱性->修正済み(Ruby公式ニュースより)

2.5のModule#private_constant


つっつきボイス: 「privateって動詞か! こういうのを後から入れてくるのが何ともRubyらしい: 自分で自分を書き換えまくるような変更」

参考: Rubyリファレンスマニュアル Module#private_constant

name で指定した定数の可視性を private に変更します。

rubycritic: コードアナライザ gem(Awesome Rubyより)


whitesmith/rubycriticより

まだ2.4.x対応だそうです。内部でReekFlayなどを組み合わせているようです。


つっつきボイス: 「rubocopの競合というよりはコードアナライザというか静的解析に重点を置いている感じだから方向性は違うかな」

IO#closeのメッセージがRuby 2.5で改良されてうれしい(RubyFlowより)

#<Thread:0x00007f9cfc889370@io_ruby.rb:2 run> terminated with exception (report_on_exception is true):
Traceback (most recent call last):
        1: from io_ruby.rb:3:in `block in <main>'
io_ruby.rb:3:in `read': stream closed in another thread (IOError)
Traceback (most recent call last):
        1: from io_ruby.rb:3:in `block in <main>'
io_ruby.rb:3:in `read': stream closed in another thread (IOError)

つっつきボイス: 「どのスレッドでこけたかがわかるようになったのは確かにうれしいっすね」

Rubyのネットワークセキュリティ関連ツール


つっつきボイス: 「基本的にこの種のツールは実績で選びたいところ」

inspec: インフラのテストコードを書く(GitHub Trendingより)


inspec.ioより

# 同リポジトリより
describe port(80) do
  it { should_not be_listening }
end

describe port(443) do
  it { should be_listening }
  its('protocols') {should include 'tcp'}
end

つっつきボイス: 「いわゆるserver spec的なやつか: まあだいたいファイルの存在チェックとかポートのチェックになりますね」

LightIO: Ruby向け軽量スレッドライブラリ

Go言語のgoroutineやCrystal言語のfiberに似ているそうです。


つっつきボイス: 「RubyのFiberじゃなくてCrystalのfiberか」「green threadって聞いたことないなー」「造語かな?」「beamってのもある」「fiberより細いってことかも」

と思ったらありました。

グリーンスレッド(英: green threads)とは、コンピュータプログラミングにおいて、オペレーティングシステムではなく仮想マシン (VM) によってスケジュールされるスレッドである。グリーンスレッドはネイティブのOSの機能に依存せずにマルチスレッド環境をエミュレートする。グリーンスレッドはカーネル空間ではなくユーザー空間で管理されるため、ネイティブスレッドがサポートされていない環境でも動作する。
Wikipedia-ja: グリーンスレッドより

Rubyでsyntactic sugarメソッドを作る(Hacklinesより)

# 同記事より
person1 = Person.new
person1.name = "John"

array = [:foo, :bar]
array[1]  # => :bar

hash = { :key => :foo }
hash[:key] # => :foo
hash[:key] = :value

つっつきボイス: 「シンタックスシュガーかと思ったらsyntactic sugarだそうです」「どうやら=[]なんかをオーバーライドする話: ただあんまりやりすぎると単に読みにくいコードになるけど」「DSLとか書くときによく使うやつですね」

syntactic sugarとは、コードを読みやすくわかりやすくできるRubyのささやかなマジックのことです。Rubyではある種の記号やスペース文字を省略できるようにしたり、ヘルパー的な式を書いたりすることを指します。
同記事より大意

Rubyで形態素解析


つっつきボイス: 「これはもうmecab叩いてるやつでしょう」「mecabって随分前からありますね」

Rubyのさまざまなコンカレンシーモデルを紹介(Random Rubyより)


つっつきボイス: 「parallelにthread、お、EventMachineも入ってるか、fiber、などなど一通り揃ってるかな」「このあたりを知らない人は読んでおくといいと思う」

OpalとFerroでDOMを叩くHTML抜きRuby Web開発(Ruby Weeklyより)


easydatawarehousing.github.ioより

# 同サイトより
class Demo < FerroElementComponent
  def cascade
    # Add the title
    add_child(
      :title,
      FerroElementText,
      size: 4,
      content: 'Title'
    )

    # Add the button
    add_child(
      :btn,
      DemoButton,
      content: 'Click me'
    )
  end

  def rotate_title
    # We have access to the 'title' instance variable
    txt = title.get_text
    title.set_text (txt[1..-1] + txt[0]).capitalize
  end
end

class DemoButton < FerroFormButton
  def clicked
    # Every element knows its parent
    parent.rotate_title
  end
end

サイトの「Click me」ボタンでデモできます。


つっつきボイス: 「(見学の方へ)Opalっていう、RubyコードをJavaScriptに変換するのがあるんですね」「まだ対応付けみたいな感じでやってるんで、数値演算とかやったら結果はズレますが、ちょっとしたものなら作れる」


opalrb.comより

gemnasium.comがGitLabに買収される


gemnasium.comより


つっつきボイス: 「何のサービスだろうと思って見てたらいきなり終了のお知らせ↓が表示されたので」「ということはこのサイトの機能がGitLabに追加されるのかな」

ときどき、言語に公式の自動フォーマッタが欲しくなる


つっつきボイス: 「自分的には共感しちゃいます」「まあそれを推し進めるとPythonみたいに全部インデントでやるみたいになっちゃいそうですけどね」

追伸: こっちを貼るつもりだったのが漏れてました

rbcuda: Ruby向けCUDA

CUDAは機械学習方面で初めて見かけました。


つっつきボイス:CUDAといえばNVIDIAのライブラリ」

RubyKaigi CFP募集開始

ラジオ: Matzが語るRuby(Awesome Rubyより)

30分です。

SQL

PostgreSQLのロックを理解すれば怖くない(Postgres Weeklyより)


つっつきボイス: 「ぽすぐれのロックと言えば確か3種類」「行とか列とかでしたっけ?」「あと悲観/楽観かな」

PostgreSQLだけでbump chartを生成する(Postgres Weeklyより)


同記事より


つっつきボイス: 「こういうキモいのもぽすぐれによくある」

柔軟な全文検索の提案(Postgres Weeklyより)

ALTER TEXT SEARCH CONFIGURATION multi_en_de
    ALTER MAPPING FOR asciiword, word WITH
        CASE english_hunspell WHEN MATCH THEN KEEP ELSE english_stem END
        UNION
        CASE german_hunspell WHEN MATCH THEN KEEP ELSE german_stem END;

つっつきボイス: 「多言語検索↑が目についたので」「vectorに入れてるなら速そうではある」

JavaScript

polacode: コード部分だけスクショを撮るツール(GitHub Trendingより)


同リポジトリより


つっつきボイス: 「これはポラロイドのpolaですね: 自分でトリミングしなくていいそうです」「おっと、これはVS Code専用みたい」「ソウダッタカ(´・ω・`)」

basicScroll: parallax scrollライブラリ(GitHub Trendingより)

See the Pen basicScroll Default Demo by Tobias Reich (@electerious) on CodePen.


つっつきボイス: 「こういう上下方向のときにもparallaxって言うんでしたっけ?」「ですね」「スクロールに追従して変わるのは総じてparallax: キライですけど」「まあ飽きられるのも早そう」

vuetify: Vue.jsでMaterial Design(JavaScript Weeklyより)


vuetifyjs.comより


つっつきボイス: 「ビューティファイ!」「とりあえず名前がいいなー」「名前大事」

オピニオン: JavaScriptのPromiseは中立とは言えない(JavaScript Weeklyより)

// 同記事より
function fn(resolve, reject) {
  console.log('hello');
  // ...
}

console.log('before');
const promise = new Promise(fn); // fn() is called immediately!
console.log('after');
  • lazyではない
  • キャンセルできない
  • 同期的ではない
  • then()map()flatMap()のミックス

つっつきボイス: 「まあJSのPromiseって一種のシンタックスシュガー的なもので、見た目はそうでも中身はそうじゃないですしね」「カリー化とか頑張ればできるのかも知らんけど」

ass-js: JavaScriptで書かれたx86アセンブラ(JavaScript Weeklyより)

# 同リポジトリより
    (‿*‿) 
Assembler.js

つっつきボイス: 「この名前とアイコンw」「此奴、狙ってるナ」「ウォッチに載せていいものかかどうか考えてしまった: 少なくともアイキャッチには入れられない~」「やってることは普通にアセンブラですね」

CSS/HTML/フロントエンド

デザインの参考になるUI/UXポートフォリオ


つっつきボイス: 「非デザイナーとしてはこういうサイトを用途に応じて使いこなすテクニックが知りたい」「確かにー: いろんなデザインはあってもどれを選んだらいいのやら」

CSS variable、これだけは知っておきたい(Frontend Focusより)

See the Pen Component Variations with CSS Variables by Ohans Emmanuel (@ohansemmanuel) on CodePen.


つっつきボイス: 「Sassなら変数アルヨ!」「ま、それを生CSSで書けるのがいいところ」

Jekyllを使って技術ブログ向けのSEOをする(RubyFlowより)

http://jekyllthemes.org/Jekyll CIとは別だったんですね。


つっつきボイス: 「Jekyllはとてもいいですよ: 何といってもGitHubが公式にサポートしてる」「知らなかった」「自分の手元にRuby環境がなくてもGitHubにプッシュすればデプロイまでやってくれて優秀」

参考: github.com/jekyll/jekyll

どんな検索UIがあるかざっと集めてみた(RubyFlowより)


つっつきボイス: 「これの5倍ぐらいエントリがあればうれしいかなー」「まあ自分用のメモみたいなので」

その他

gitleaks: Gitリポジトリの秘密キーなどを検索(GitHub Trendingより)


つっつきボイス: 「おー、Gitのcommitログも検索してる!」「エグい」「これはpublicにさらす前とかに使うとか、CIに入れておくとよさそう」「CIに何でもやらせるとますます遅くなるけどな」

猫アバターの人のポッドキャスト

まだ一度しか聴いてませんがすごく面白かったので。

本格暗号本PDFが無料で公開


つっつきボイス: 「TeXフォーマットか」「楕円曲線とかめちゃガチな内容!」

番外

教会の尖塔をWi-Fiアンテナ設置場所に

避雷針は前からあるから心理的な抵抗は大したことないと思うけど、装置の雷対策も必要そうですね。

CSSでキーロガーは作れるか

今はリードオンリーになっています。実際には動かなかったらしいとも。

NHKの無料素材動画

加工も可能な動画素材です。

「シークワーサー」の表記ゆれ

科学写真コンテスト

参考: 「原子1個」を捉えた画像。英国の科学写真コンペ優秀賞も納得です。 | ギズモード・ジャパン

むかしむかし


今週は以上です。Ruby25でお会いしましょう。

バックナンバー(2018年度)

週刊Railsウォッチ(20180216)Rails 5.1.5リリース、DHHのYouTubeチャンネルは必見、Ruby Toolboxが運営再開ほか

今週の主なニュースソース

ソースの表記されていない項目は独自ルート(TwitterやRSSなど)です。

Ruby 公式ニュース

Rails公式ニュース

Ruby Weekly

Awesome Ruby

Random Ruby

RubyFlow

160928_1638_XvIP4h

Hacklines

Hacklines

Postgres Weekly

postgres_weekly_banner

Frontend Focus

frontendfocus_banner_captured

JavaScript Weekly

javascriptweekly_logo_captured

jslive_logo_captured

Github Trending

160928_1701_Q9dJIU

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ 開発エンジニア積極採用中です! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833 コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。 これまでにRuby on Rails チュートリアル第2版の半分ほど、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れてそれぞれ一部を翻訳。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 実は最近Go言語が好き。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

週刊Railsウォッチ

インフラ

ActiveSupport探訪シリーズ