週刊Railsウォッチ(20180820)Railsで構築されたサイト40選、Deviseはつらいよ、ARのスコープとクラスメソッドの使い分けほか

こんにちは、hachi8833です。Matzにっきを最初から読みふけってたら完璧に寝不足になってしまいました。


つっつきボイス:「お、例のMatzにっき、この間404になってなかったっけ?」「その後復旧してました: ここのtDiaryのナビゲーションがつらくて、最も最初の月にたどり着くのに何回もクリックしないといけなかったり😭」「😆」「最初が2003年なのでまだRailsも世に登場してなかった頃でした」

スクレイピングしてローカルで読もうかとも思いましたが負荷かけるのがコワイので、ブラウザで月ごとに気長にSave asし始めてます🐢。

  • 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを社内有志でつっついたときの会話です👄

お知らせ: 第2回「週刊Railsウォッチ 公開つっつき会」開催

初回の8/2に続き、「週刊Railsウォッチ 公開つっつき会 第2回」を9月6日(木)19:30〜より開催いたします。詳しくは上のリンクでご覧ください。皆さまのご参加をお待ちしております🙇🙇。

Rails: 先週の改修(Rails公式ニュースより)

ActiveStorageのエラーハンドリングを改善

issue #33157の方がわかりやすいかも?

わかりにくかったエラー
NameError: Cannot load Rails.config.active_storage.service: wrong constant name diskService
#33157より

# activestorage/lib/active_storage/service/configurator.rb#L27
      def resolve(class_name)
-        require "active_storage/service/#{class_name.to_s.underscore}_service"
+        ActiveStorage::Service.const_get(:"#{class_name}Service")
+        ActiveStorage::Service.const_get(:"#{class_name.classify}Service")
+      rescue LoadError
+        raise "Missing service adapter for #{class_name.inspect}"
      end

つっつきボイス:「"#{class_name}Service""#{class_name.classify}Service"に…?🤔あー大文字小文字をクラス名のスタイルにするメソッドか」「言葉どおりの『分類』ではなかったんですね💦」

参考: Ruby on Rails 5.2 / ActiveSupport::Inflector#classify — DevDocs

# devdocs.ioより
classify('ham_and_eggs') # => "HamAndEgg"
classify('posts')        # => "Post"

キャッシュのフェッチでnilをスキップするようになった

# activesupport/lib/active_support/cache.rb#L701
         def save_block_result_to_cache(name, options)
           result = instrument(:generate, name, options) do
            yield(name)
          end
-           write(name, result, options)
+          write(name, result, options) unless result.nil? && options[:skip_nil]
          result
        end

つっつきボイス:「今までは結果がnilの場合もキャッシュに保存されて、キャッシュがexpireするまで残っちゃってたのか💡」「で、今後はskip_nil: trueというオプションを指定すれば、結果がnilの場合はキャッシュしないようになると👍: わかりみ」

追記:

従来のコードでは、例えば「最新データがキャッシュにあればキャッシュから拾い、なければDBを参照する」みたいな動作を期待している時に一度nilをキャッシュしてしまうと、DBに新しいデータが入ってもキャッシュがexpireするまでnilを返してしまう仕様でした。

ただ、これはキャッシュエンジンの仕様としてはあながち間違いではありません。DB側を更新する時に明示的に対応キーのキャッシュを飛ばす実装にすればそれでも正しく動くからです。

今回の変更の:skip_nil`オプションは、その辺のキャッシュ自動管理を多少サボれるようになります。一度作られたら変わらないデータみたいなものをキャッシュに載せる場合には手軽に使えて便利という感じです。

ただし楽になるのは新規追加の時だけで、updateの場合には結局手動でキャッシュ飛ばすコードが必要です。この設定が手動で必要なことを見落とすと、古いデータが更新されないというIssueが上がってくる所までがワンセットになりそうな予感がします。

ネストした属性でextendしたときにbuildが呼ばれるように修正

これもissue #33389の方がわかりやすいかも。

# activerecord/lib/active_record/nested_attributes.rb#L503
            unless reject_new_record?(association_name, attributes)
-              association.build(attributes.except(*UNASSIGNABLE_KEYS))
+              association.reader.build(attributes.except(*UNASSIGNABLE_KEYS))
            end

つっつきボイス:「NestedAttributesは普段使わないなー: そこにも載っているaccepts_nested_attributes_forはいつ消えるんだろうって思ったり」「それ何でしたっけ?」「あ、これ実は要らないんじゃないかっていう説が前からあってですねー、典型的なパターンから外れてカスタマイズし始めると途端に破綻するヤツ」「へー!」「一応Railsの標準機能ではあるし、使われているのも見かけるんですが、たとえば順序を変えようとしたりするとすぐフォームが泥臭くなっちゃうんで自分はあまり好きでないです😩」「ストンとはまるところだけにしとけってことですね」「カスタマイズなしで作れる管理画面とか、後はSPAなんかでフォームを自分でビルドするときとかでしょうね😎」

参考: #method-i-accepts_nested_attributes_for

# api.rubyonrails.orgより
class Member < ActiveRecord::Base
  has_one :avatar
  accepts_nested_attributes_for :avatar

  def avatar
    super || build_avatar(width: 200)
  end
end

member = Member.new
member.avatar_attributes = {icon: 'sad'}
member.avatar.width # => 200

参考: 複数の子レコードを作成・更新する. accepts_nested_attributes_for - Qiita

Timeカラムの精度を改善

以下はReferences to changes in Rails 5.2から見繕いました。

# activemodel/lib/active_model/type/time.rb#L28
      private
         def cast_value(value)
-          return value unless value.is_a?(::String)
+          return apply_seconds_precision(value) unless value.is_a?(::String)
          return if value.empty?
-           if value.start_with?("2000-01-01")
-            dummy_time_value = value
-          else
-            dummy_time_value = "2000-01-01 #{value}"
-          end
+          dummy_time_value = value.sub(/\A(\d\d\d\d-\d\d-\d\d |)/, "2000-01-01 ")
           fast_string_to_time(dummy_time_value) || begin
            time_hash = ::Date._parse(dummy_time_value)
             return if time_hash[:hour].nil?
             new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset))
           end
         end

つっつきボイス:「precisionが指定できるようになったと」「quoted_なんちゃらのquotedって?」「そりゃ引用符""で囲む↓ってことでしょうね😆」「深読みしなくてよかったのか💦」「それにしてもActiveModelの中に2000-01-01みたいな日付がハードコードされてるのって何なんだろう?🤔テストコードならまだしも」

# activerecord/test/cases/adapters/sqlite3/quoting_test.rb#L58
+  def test_quoted_time_normalizes_date_qualified_time
+    value = ::Time.utc(2018, 3, 11, 12, 30, 0, 999999)
+    type = ActiveRecord::Type::Time.new
+     assert_equal "'2000-01-01 12:30:00.999999'", @conn.quote(type.serialize(value))
+  end

quoted company: 上場会社

セッションやcookieでのto_hto_hashの挙動を揃えた

# actionpack/lib/action_dispatch/middleware/cookies.rb#L341
+      # Returns the cookies as Hash.
+      alias :to_hash :to_h
+

つっつきボイス:「to_hto_hashの挙動が違ってた?」「ActionDispatchのSession::Requestにはto_hashがあったけどto_hがなくて、Request:: CookieJarにはto_hがあったけどto_hashがなかった、ってことみたい」「ははぁ食い違ってたのか」「この記事↓ではto_hto_hashの違いを説明してたけど、それとは別の話だったか」「確かにセッションとcookieって近いところにあるからこれが違ってたらイヤだなー😤」

Rubyの明示的/暗黙的な型変換についてのメモ(翻訳)

リレーションをmergeしたときにINNER JOINが変わらないようにした

# activerecord/lib/active_record/associations/join_dependency.rb#L107
-      def join_constraints(outer_joins, join_type)
+      def join_constraints(joins_to_add, join_type)
        joins = join_root.children.flat_map { |child|
          make_join_constraints(join_root, child, join_type)
        }
-         joins.concat outer_joins.flat_map { |oj|
+        joins.concat joins_to_add.flat_map { |oj|
          if join_root.match? oj.join_root
            walk join_root, oj.join_root
          else
            oj.join_root.children.flat_map { |child|
-              make_outer_joins oj.join_root, child
+              make_join_constraints(oj.join_root, child, join_type)
            }
          end
        }
       end

2016年11月のPRですが、マージされるまで半年以上かかってました。「INNER JOINが変わるのは仕様かも?」みたいな議論を経ています。

# 同PRより
Author.joins(:posts).merge(Post.joins(:comments))

# 期待
#=> SELECT ... INNER JOIN posts ON... LEFT OUTER JOIN comments ON...

実際
#=>SELECT ... INNER JOIN posts ON... INNER JOIN comments ON....

つっつきボイス:「確かに上の書き方ならINNER JOINにならないとおかしいのでわかるけど、元のが正規の挙動だと思ってやってた人いそう」「😅」「こういうのってto_sqlで確かめながら使うし、『こうやったらLEFT JOINできるのか!やったね💪』と思って使ってたらbreaking changeになったり」「これは完全にbreaking changesですね: マージに時間かかるのも無理ないし」

Rails

simple_calendar: Rails向けカレンダー


同サイトより


つっつきボイス:「最近kazzさんがカレンダーの設計と実装で頭抱えてたので」「ああーそういえば😆😆」「まーカレンダーは自力で実装するもんじゃないよなー😆」「表示はともかくモデルの設計で手こずってたようです」「カレンダーの中身をどこまで自由にさせるかで全然変わりますしね」「項目が増えたら...にするとかね😆」

「このカレンダーはそこそこ使いやすそうっすね: このdoブロックをeach的に回してその中にやりたいことを書く↓みたいな」

<!-- 同記事より -->
<%= month_calendar do |date| %>
  <%= date %>
<% end %>

「それにしても、こういうのを効率よく書こうとすると現実にはたいていうまくいかないですよね🤣:カレンダーを全部ループで書くのはよくないかなってつい思っちゃうじゃないですか: 3重ループの中で同じメソッドを何回も呼ぶぐらいならプリレンダリングしようなんて思ってやると、後でハマるハマる🤣」「🤣」「なまじ効率よく書いちゃうと、月表示の他に週表示もやりたいとか、週始まりを月曜から日曜に変えたいみたいな要件が来たときにつぶしが利かなくなる🔨」

「他にもBootstrapの縦分割が12だから、カレンダーを7日表示や5日表示にするときにつらいって言ってました」「それBootstrap 4ならできますよ: Bootstrap 3だとできないけどネ」「Bootstrap 3はFlexbox↓が使えないから🤣」「そういえばIE9縛りがあるとFlexboxが使えないからBootstrap 4が使えないんですよね😭」

See the Pen Demo Flexbox 1 by Hugo Giraudel (@HugoGiraudel) on CodePen.

「Bootstrap 4だとどうやるんでしたっけ🤔」「こんなふうに数値を付けないcol-*↓を使えばFlexboxで均等割になってくれますね😋」「おほー😃」「カレンダーの7分割もこれでイケます💪」

参考: Grid system · Bootstrap

<!-- getbootstrap.comより -->
<div class="container">
  <div class="row">
    <div class="col-sm">
      One of three columns
    </div>
    <div class="col-sm">
      One of three columns
    </div>
    <div class="col-sm">
      One of three columns
    </div>
  </div>
</div>

参考: Rails で簡単にカレンダーを扱える simple_calendar で週表示カレンダーのフォーム作成を試す - Qiita

スコープよりクラスメソッドの方がよい場合

2015年の記事ですが。

# 同記事より
# app/models/review.rb にスコープで書いた場合
scope :created_since, ->(time) { where("reviews.created_at > ?", time) if time.present? }

# クラスメソッドで書いた場合
def self.created_since(time)
  if time.present?
    where("reviews.created_at > ?", time)
  else
    all
  end
end

つっつきボイス:「どのスコープの話かなと思ったらActiveRecordね: スコープかクラスメソッドかというのはよく言われる話で、たとえばこんな別記事もあるし↓」「これも2013年の記事だけど詳しそうですね」

参考: Active Record scopes vs class methods « Plataformatec Blog

「スコープにするならchainableでextensibleなものにすべきとあるし、かのRailsガイド様でも引数を付けるときにはクラスメソッドが推奨となってる↓」「ホントだ😳」「スコープに引数を付けるのはおすすめされてないっぽい: 実際複雑になるし」

Using a class method is the preferred way to accept arguments for scopes.
Active Record Query Interface — Ruby on Rails Guidesより

「自分はめっちゃ長くならない限り引数もあんまり気にしないでスコープで書いちゃいますけどね」「結局長くなってきたときが問題」「ただ、少なくともチェインの順序を変えると結果が変わるものはスコープにしない方がいい」「確かに」「『always chainable』っていうのはそういうことだと思う: たとえばWHEREしか使ってなければ大丈夫だけど、GROUPとかが使われているとおかしな結果になったり」「うんうん」「あとORDERが使われているスコープも、条件が複雑になったときにカオスになりやすいし」「それからスコープとクラスメソッドがどちらも使われている場合に、どういうのをどっちでやるかという方針はあったほうがいいですね🧐」

Google CalendarとRailsの連携

# developers.google.comより
def authorize
  client_id = Google::Auth::ClientId.from_file(CREDENTIALS_PATH)
  token_store = Google::Auth::Stores::FileTokenStore.new(file: TOKEN_PATH)
  authorizer = Google::Auth::UserAuthorizer.new(client_id, SCOPE, token_store)
  user_id = 'default'
  credentials = authorizer.get_credentials(user_id)
  if credentials.nil?
    url = authorizer.get_authorization_url(base_url: OOB_URI)
    puts 'Open the following URL in the browser and enter the ' \
         "resulting code after authorization:\n" + url
    code = gets
    credentials = authorizer.get_and_store_credentials_from_code(
      user_id: user_id, code: code, base_url: OOB_URI
    )
  end
  credentials
end

つっつきボイス:「これもカレンダー絡みで: だいたいGoogle公式に揃ってるみたいですね」「GoogleのAPIにはたいていRubyのインターフェイスもあるので、Spreadsheetとかも含めてこういうのはたいていできます、ただし」「お?」「Googleに限りませんが、APIで一番よくハマるのは上限値の制約に引っかかったとき⛔」「あー😲」「たとえば1回のリクエストで取れる件数に上限があったりとかですね」

「カレンダーなんか場合、データを1リクエストでガバっと取ってきてから処理するなら全然楽勝なんですが、ちゃんとやるなら100件単位とかでループで回してデータを取ってきたりしないといけない: それ自体はそんなに大変でもないんですけど、それが面倒でガバっと取ってやろうとするとこういう制約に引っかかったりすると」「はー😞」「そういえばAWS S3にもそういう上限ありますね: 1000件ぐらいだったかな?」「まあ外部APIを使おうとするとだいたいこういう制約がありますし」

「ループもeachでさくっと書けそうに見えたりしますが、この手の外部APIはループをeachで単純に回してデータを取ると失敗することがあります」「お?😳」「たとえばカレンダーなら、ある瞬間のorder by updated_at的なデータを取ってきてから次のデータをリクエストする間にデータが変更される可能性があるので、そのままだと一意の結果が保証されないんですね」「おぉー😲」「正しくやるためには、そのデータを取るときにその時点のスナップショットを表すクエリIDも返してもらって、そのクエリIDと一緒にページングやorderingを扱わないといけない」「そうそう😤」「でないとorder by IDでループを回している間にデータが挿入されて、レコードが重複してコケるとかね」

「GoogleのはクエリID取れるんでしょうか?」「どっちだったかな…🤔?」「S3だと上限に達したときにnextなんとかを返してくれた覚えが」「あ、Googleにもそういうnextなんちゃらがあったと思う: でもどれでやるにしてもこの処理は面倒😢」「面倒ですよねー😞」「上限に達するぐらいデータを入れておかないとその部分をデバッグできないし💦」

DataTablesをRailsで使う


datatables.netより


つっつきボイス:「jQuery向けということで同じようなのは既にいっぱいありますが、割と頑張ってるかなと思って」「この時代にjQueryで攻める勇者」「でもこのぐらいのテーブルならjQueryで十分じゃね?と思う: ↓こういう動作もfunctionを書けばちゃんと実装できるし、自分はこういうのキライじゃない❤️」


同サイトより

Railsパフォーマンス最適化手法まとめ


同記事より


つっつきボイス:「割と基本というか常識的な話かな?」「プロバイダ選び、N+1、gem選び、バックグラウンドジョブ、CDN、インデックス…」「これほとんどRailsと関係ないし😆」「Webアプリ全般の最適化話やん🤣」「タイトル変えなきゃ🤓」「その分一般的に通用しそう」「はじめてWebアプリを作るのがRailsの人なら読んでおきたいヤツですね」

Deviseのcustom mailerが動かなかった話

# 同Wikiより
class MyMailer < Devise::Mailer   
  helper :application # gives access to all helpers defined within `application_helper`.
  include Devise::Controllers::UrlHelpers # Optional. eg. `confirmation_url`
  default template_path: 'devise/mailer' # to make sure that your mailer uses the devise views
end

つっつきボイス:「DeviseのWikiに書いてある通りやったのにcustom mailerが動かなくてハマった人が今ちょうどここにいらっしゃるので😇」「ああ例のw」「😤😤」「お、issue立ってるのか↓: でもcloseしてるけど?」「needs debuggingとかつぶやきながら閉じられてるんですよ😭修正されてないのに」「ひどいw」「そっ閉じw」

参考: #4842 Unable to use custom views for emails

「問題だったのは以下のdefault template_path: 'devise_mailers'のところなんですけど」

# 同issueより
class DeviseMailer < Devise::Mailer
  prepend_view_path Rails.root.join('app', 'ui')
  include Devise::Controllers::UrlHelpers
  layout 'devise_mailer' # is in app/ui/layouts/devise_mailer.html.haml
  default template_path: 'devise_mailers' # is in app/ui/devise_mailers/...
end

「(怒涛のトーク)…まとめると、上で記述したdefault template_path:が効いてなくて、app/views/devise_mailersを参照して欲しいのにapp/views/devise/mailerが参照されてしまうんですね」

# これは動く => app/views/mailer_templateを参照する
class MyMailer < ApplicationMailer
  default template_path: 'mailer_template'
end
# これだと期待どおりに動かない => 相変わらず app/views/devise/mailerをみる
class MyMailer < Devise::Mailer
  default template_path: 'mailer_template'
end

「あーもしかしてDeviseMailerがActionMailerを継承しているから?」「かなっとも思ったんですが、Deviseのヘルパーにあるheaders_forというメソッド↓がtemplate_pathを書き換えていて、それによってこちらが書いたtemplate_pathが上書きされたので、メール文言がDeviseのデフォルト文言になってしまった😇」「はは~ん、わかりみ〜☺️」

# DeviseのHelperより
      def headers_for(action, opts)
        headers = {
          subject: subject_for(action),
          to: resource.email,
          from: mailer_sender(devise_mapping),
          reply_to: mailer_reply_to(devise_mapping),
          template_path: template_paths,
          template_name: action
        }.merge(opts)

「一応回避方法もissueに載ってます↓: この#headers_forメソッドがDeviseの汎用ヘルパー的なものらしいんですけど、それをこうやってオーバーライドしろってことでした」「privateメソッド臭ぷんぷん」「でもどんな影響が生じるか読みきれないんでneeds debuggingって言ってます」「DeviseのWikiは相当読み込んだけど、この手の『privateメソッドをオーバーライドせよ』的な驚きの拡張方法をちょくちょく強いられるんですよね」「『これ本当にオーバーライドしていいの?!』みたいなのが続出するし」「『え?、configじゃなくてメソッドをオーバーライド?!』とか」「オーバーライドするしかないとかキツイわ〜」「Deviseはこういうところがキラワれがち」

# 同issueより
class DeviseMailer < Devise::Mailer
  prepend_view_path Rails.root.join('app', 'ui')
  include Devise::Controllers::UrlHelpers
  layout 'devise_mailer' # is in app/ui/layouts/devise_mailer.html.haml

  # this below has no effect
  default template_path: 'devise_mailers' # is in app/ui/devise_mailers/...

  # this below enables effectively the custom views path
  def headers_for(action, opts)
      super.merge!(template_path: 'devise_mailers')
  end
end

「こういうことが起きるから、機能を拡張するときは『継承よりコンポジションしろ』って口を酸っぱくして言われるんですよね😆」「うんうん」

「今回特にムカつくのは、Wikiのコードが間違ってるのに動いちゃうところ: devise_mailerって間違ってるけど実在するから💦」「いっそ止まってくれればよかったのに😞」

「DeviseでたとえばRegistrationコントローラを自前で作るときとか、DeviseのRegistrationコントローラをコピペするところから始めるなんてのもざらにやりますしね🤪」「そしてそのコピペをRubocopに怒られるところまでがテンプレww👮」「😭😭」「ところがところが、必要なメソッドだけ上書きするよりも全部コピペする方がまだ安全なんですねこれが」「そうかもしれない」「日暮れて道遠し感」「まさにイッツ・ア・Deviseワールド」

[Rails] Devise Wiki日本語もくじ1「ワークフローのカスタマイズ」(概要・用途付き)

PHPからRubyへの移行ガイド


同サイトより

かなりがっつりと書かれています。「Railsの方が稼げる」というセリフも。


つっつきボイス:「自分もPHPからRailsにやってきた人だったしそういえば」「Rubyなら===とか使わなくても比較できるよみたいな?😆」

外部キーなしのActiveRecord関連付け

# 同記事より
class Order < ApplicationRecord
  has_one :custom_logo,
    ->(order) {
      unscope(:where).where(
        origin_value: order.origin,
        client_id:    order.client_id)
    }
end

つっつきボイス:「↑そうそう、lambda使えば外部キーなしでもできますね」「実用的ではないんでしょうか?」「一応使えるといえば使えそう: unscope(:where)とかやっていいのかなー?と思わなくもないけど🤔」

そういえば以前著者のTom Copelandさんの記事を翻訳しました↓。

Rails: マイグレーションを実行せずにマイグレーションのSQLを表示する(翻訳)

Railsで構築されたサイト40選: 2018年度版(RubyFlowより)


同記事より


つっつきボイス:「よくあるリストといえばそれまでですけど」「あ、でもこういうリストは『Railsってどの辺がいいの?』って聞かれたときなんかに便利ですよ😋」「AirbnbとかShopifyとか有名どころもあるし」「DribbleもRailsか」「何のサイトでしたっけ」「デザイナー向けSNSみたいな感じでそこそこ有名」


dribbble.comより

SlideShareHuluもRailsとは😲」「Huluは有料動画サイトでしたっけ」「kickstarterがRailsというのは何となくわかる」「意外にいろいろあるなー🎂」


hulu.comより


kickstarter.comより

Urban Dictionaryは翻訳で愛用してます💚」


urbandictionary.comより

Basecampが16番目とは😆」「DHHのお膝元なのに」

「カスタマーサポートサービスのZendeskも!へー😲」


zendesk.comより

BloombergがRailsなのは有名」「知らなかったー」「確かgemも出してたはず(GitHub)」


bloomberg.comより

Indiegogoもか」「これは?」「有名なクラウドファンディングサイト」


indiegogo.comより

元記事のIndiegogoのリンクはなぜか間違ってました。

「えTwitchもRails?!😲」「何すかこれ?」「BPS社内Slackの格ゲー板では欠かせないヤツ💪」「最大のゲーム配信プラットフォームっす🎮」

↓開くといきなり動画が再生されます。


twitch.tvより

CodeacademyがRailsというのも何かわかる」


codecademy.comより

「知らないサイトもあるけど、意外なサイトがRails使ってるんだなー☺️」「こういうリストのエロサイト版があったら面白いかも🤪」「?」「エロサイトってそこらのメジャーなサイトとか目じゃないぐらい普段からものすごい量のアクセスをさばいているし、いろんな意味で(笑)常に最先端を行ってるから内部にはものすごいノウハウが蓄積されてるはずなんですよね: しかもたいてい門外不出という🤣」

Railsガイド日本語版に「Active Record と PostgreSQL」が追加

今日の昼に公開されました。本家英語版にもまだないエントリなので、当然ながらWIP状態です。


Railsガイド日本語版より

Ruby trunkより

2003年のRubyConferenceでのMatzのスライド

いつもとちょっと毛色が違いますが、Matzにっきで見かけた古きを訪ねてみました。


同スライドより


つっつきボイス:「2003年です」「Ruby 1.9が始まろうとしてた頃かー😲当時学生だったし」「たとえば以下のようなローカル変数スコープの変更が提案されてました↓」

# 同スライドより加工
# Ruby 1.9でのローカル変数の扱いの変更の構想
def foo
  a = nil
  ary.each do |b|
    # bはブロックに対してローカル
    c = b
    a = b
    # aとcはメソッドに対してローカル
  end
  # aとcはブロックの外でアクセスできる
  puts a
  puts c
end

2.5.1で試すとNameError (undefined local variable or methodc’ for main:Object)`になりました

「この頃からRubyConferenceってあったんだなー: 明らかにBefore Rails時代だし🏛」「今やお馴染みのキーワード引数やハッシュリテラル↓も提案されているし」「マルチアサインとか」

def foo(a, b: 42, **keys)
  p [a, b, keys]
end
foo(2, b: 1)       #=> [2, 1, {}]
foo(2, b: 5)       #=> [2, 5, {}]
foo(3, b: 4, c: 6) #=> [3, 4, {:c=>6}]
# 1.8まで
{ :a => 45, :b => 55, :c => 65 }

# 1.9向け提案
{ a: 45, b: 55, c: 65 }

「このメソッド結合(method combination)って何だろうと思って」「これは明らかに今のRubyにはない」「ボツになったんでしょうね」「スゴイ書き方😅」「フックをかける書式のようだ🤔」

class Foo
  def foo:pre(*args)
    p "pre"
  end
  def foo:post(*args)
    p "post"
  end
  def foo:wrap(*args)
    p "wrap pre"
    super
    p "wrap post"
  end
  def foo(*args)
    p "foo"
  end
end

Foo.new.foo
# wrap pre
# pre
# foo
# post
# wrap post

個人的にはインスタンス変数にprivateスコープを作る提案↓が気になりました。本当はデフォルトでprivateにしたかったようですが、日記の方で「評判よくなかった」とあり、いずれも採用されなかったようです。

@foo  = 42  # サブクラスからアクセスできる
@_foo = 55  # そのクラス/モジュールからのみアクセス

提案: 名前空間の改善

# 同issueより
class Foo
end

# Kernel#namespaceの導入
namespace :Hello do
  # 名前空間のカオスを回避
  # Foo -> NameError, can't access TOPLEVEL_BINDING directly

  # Kernel#importはFooという名前をOPLEVEL_BINDINGから導入する
  import :Foo

  # 名前空間内では、インポートした名前にしかアクセスできない
  Foo

  # 定数は別のエイリアス名にインポート
  # ネストしたモジュール名/クラス名を書くことを回避できる
  import :"A::B::C::D", as: :E

  # requireしてインポートするショートハンド
  import :"A::B::C::D", as: :E, from: 'some_rb_file'

  # 2つのgemから同じ名前をインポート
  import :"Foo", as: :Foo_A, from: 'foo_a'
  import :"Foo", as: :Foo_B, from: 'foo_b'

  # 名前をバッチでインポート
  import %i{"A::B::C::D", "AnotherClass"}, from: 'some_rb_file'

  # インポートとエイリアス化をバッチで
  import {:"A::B::C::D" => :E, :Foo => Foo2}, from: 'some_rb_file'

  class Bar
    def xxx
      # 名前空間のスコープ内にあるすべての名前にアクセスできる
      [Foo, Foo_A, Foo_B]
    end
  end
end

その後namespaceisolateに変えて提案しています。


つっつきボイス:「Rubyに名前空間とは」「お、確かRailsにそれっぽいものがいくつかあったと思う: Rubyの機能じゃないんですよね」「そうそう」「Railsじゃない普通のRubyコードでnamespaceって書いたらundefinedって言われた覚えはある」「(RubyMineで探す)お、たとえばこれですね↓(GitHub)」「おー」

# rails/railties/lib/rails/command/base.rb
        # Convenience method to get the namespace from the class name. It's the
        # same as Thor default except that the Command at the end of the class
        # is removed.
        def namespace(name = nil)
          if name
            super
          else
            @namespace ||= super.chomp("_command").sub(/:command:/, ":")
          end
        end

ルーティングにもnamespaceがありますね。

「Rubyだとモジュールでも名前空間を切ることはできるけど、明示的に名前空間を切るという意味ではnamespaceっていうキーワードはRubyにもあっていいんじゃないかなとは思いますね」「むしろRubyにデフォルトでnamespaceがないのが少々驚き😮」

RubyソースのインデントはTabから8スペースに

#14984を追ってて見つけました。

RubyのCファイル238個を調べたところ
* スペースインデントのみ: 10件
* タブインデントのみ: 66件
* インデントなし(!): 61件

つまり残り101ファイルはタブ/スペースインデントが混じっているということ。
同issueより大意


つっつきボイス:「少し前にUrabeさんが提案してました」「なるほど☺️これは揃えないとねー」「↑ちゃんと調べてるしスゴイなー😲」「Cのソースレベルだと他にもいろいろ揃ってないものがありまくりそうだけど、せめてインデントだけでもってことなんでしょうね」

Ruby

ngx_mruby: Nginxにmrubyを

RubyKaigi 2018でも話されていました

参考: ngx_mruby v2のHTTPクライアントをv1よりも最大90倍高速にした - 人間とウェブの未来
参考: Rubyエンジニアはsleep 1で殺せる、をngx_mrubyのAsync.sleepで乗り越える - The paradigm shift


つっつきボイス:「『sleep 1で殺せる』記事で見かけたので」「そうそう、sleep 1はマジで死にますよ: コントローラとかに絶対書いちゃダメなやつ」「ギャー!それはダメー!😩」「やったらどうなるんでしょう?」「ワーカーが詰まるw」

「Rubyでなくたってsleepはあかんでしょう…😅」「でもまあ、慣れてないとAPIアクセスなんかで間を空けたいときについsleepを入れたくなっちゃうんでしょうねー: そんなにやりたかったら非同期でやれと😆」

「そういえばブラウザのJavaScriptでsleep使いたくて探し回ったことありました」「setTimeout()」「ブラウザのJavaScriptでsleepする分には何の問題もないんですけど、サーバーサイドのRubyコードでsleepするとその間ワーカーをがっちり掴んで離さない: とっても簡単に死ねる😇」「😆」

参考: JavaScriptでループ中にスリープしたい。それも読みやすいコードで - Qiita

DIとハードコード定数のいいとこ取り(RubyFlowより)

class RegisterUser
  attr_reader :validator, :repo

  def self.build
    new(
      validator: UserValidator.new,
      repo: UserRepository.new,
    )
  end

  def initialize(validator:, repo:)
    @validator = validator
    @repo = repo
  end

  def call(params)
    if validator.validate(params)
      repo.save(params)
    else
      nil
    end
  end
end

つっつきボイス:「DIするとスタブやモックを入れやすいよ、みたいな話なんでしょうね: test doubleとか」「で上のアプローチ↑では、実装はDIだけど、validator: UserValidator.newのようにハードコードするってことか」「おー、これはキレイキレイ❤️」「この書き方は割とよく使いますね: 書いた時点では1種類しかないからこういう形にしておくけど、後でほぼ確実に増えることが予測できる場合なんかに拡張性を担保できるのがいいですよね😋」「ま、オーバーキルにも見えるので普通にハードコードしちゃうこともありますが😆」

「あたしもinitializeのデフォルト引数でこうするのが最近お気に入り😍」「それも同じコンセプトですね: 実装をDIにできるし、引数もキーワード引数にしておけばなおいいし」

dry-rbでサービスを設計する(Awesome Rubyより)

# 同記事より
class NotifySlack 
  extend Dry::Initializer
  option :message
  option :notifier, default: -> { Slack::Notifier.new(URL) }

  def self.call(**args)
    new(**args).call
  end

  def call
    notifier.ping(message)
  end
end

つっつきボイス:「ここでも依存性の注入が登場していました」「そういえばDependency Injectionを『依存性の注入』と言うのってどうかな~と思ったり😉」「あーそういえばそうだったか💦」

「まあ多くの日本語書籍で『依存性の注入』と訳されちゃっている現実があるんですが、この記事がひと頃流行りましたよね↓」「これ見たことあったそういえば👁」「それもあって自分はDIと言うようにしてる😎」

参考: やはりあなた方のDependency Injectionはまちがっている。 — A Day in Serenity (Reloaded) — PHP, FuelPHP, Linux or something

「注入って言葉が何かよくないっすよね」「そうそう、注入というよりイメージとしては差し込む感じ」「ジェネリクスというか」「しかも注入するものって依存性じゃないんですよね」「そうそう🤣」「どっちかというと『差し替え可能にすることで依存しないようにする』なんじゃ?」「dependencyとinjectionをそのまま訳しちゃったからこういうことになったんでしょうね〜」「元の英語もそれなりに残念な気がしますね」「たぶんinjectionを『注入』としちゃったのが敗因じゃないかな〜?」「dependencyも何か問題ありそう」「もう慣れちゃったから依存性の注入でもいいかなっと😉」「日本語にしないのが確実かも」「実際に日本語で言う人見たことないなー」「本で覚えちゃった人は言うかもしれない」「読むときも心の中でDIに差し替えてるし🧐」


確かに「依存性」も「注入」も薬物依存を強く連想してしまいがちですね。プログラミング言語の仕様を後からドラスティックに変えるのが困難なように、翻訳もいったん定着してしまった用語を覆すのは大変です。自分ひとりではできない作業なので💦。

そういえば「差し込み印刷」がmerge printの訳語だったのを思い出しました。これはいい訳だと思います💪。

参考: 差し込み印刷とは - IT用語辞典 Weblio辞書

次に学ぶ言語にRubyを選ぶことの知られざるメリット(RubyFlowより)


つっつきボイス:「『Rubyistはフレンドリー』😆」「😆」「『Rubyistは美しいコードを心がける』ホントかー?🤣美しいとは言い難いコードも山ほど見たけどなっ」「🤣」「オープンソースのコードを書いている人ならRubyに限らずだいたいそうだと思う」「他のコミュニティ向けの記事みたいです」「確かにRubyコミュニティは不毛な論争になりにくい感じはありますね😋」

Ruby関連カンファレンス情報


同エントリより

大江戸Ruby会議に値段が2種類あるのが謎でした。


つっつきボイス:「5,656円ってもしやゴロゴロ😆」「語呂合わせ」「雷門にかけてるのか」「倍以上違うし🤣」「前回は御茶ノ水で今回はお膝元の浅草ですが、自分は御茶ノ水の方が行きやすいなーと思ったり」「花やしきの裏か」


こちらも↓。

JSONを安全に「mung」する(RubyFlowより)

# 同記事より
def munge(hash)
  instructions.each do |inst|
    inst.call(hash)
  end
  hash
end

つっつきボイス:「このmungって言葉が割と謎で」「mail munglingとかじゃなくて?」「mungleじゃなくてmungeなんですがさっき手元の串刺し辞書検索で見つからなくて💦」「(しばらく探す)お、Macの英英辞典にあった↓🎯」「へー!」「しかも例文がIT系でピンポイントの内容」「『操作する』」「mungまたはmungeなのね」「しかもmash until no goodの略語という説が: すげー😳」「時間ないので次へー」

Ransack gemのyaml翻訳を増やしたい(RubyFlowより)


つっつきボイス:「珍しくRubyFlowのエントリをそのまま貼ってみました: Ransackのローカライズ済みyamlをもっと増やしたいんだそうです」「『みんな!オラにyamlをくれ!』みたいな😆」「日本語yamlは3年前のがもうあるのね」「今のところyamlは18言語分、と」

クラウド/コンテナ/インフラ/Linux/Serverless

Aurora Serverless MySQLがリリース


aws.amazon.comより


つっつきボイス:「AuroraのこのサービスをServerlessって呼んでいいものかどうか微妙〜😆」「😆」「どんなサービスでしたっけ」「単にMySQL connectしたタイミングでRDSインスタンスが起動するヤツです」「?」「つまりインスタンスは普段は止まっていて、MySQL Connectすると勝手に起動してくれて、接続が終わったらしばらくしてまた自動的に止まるということ」

「よくバッチ処理なんかで一時的に激しくアクセスしたいなんてときに、これまでだとRDSの起動や終了を手動でやらないといけなかったんですが、そういうのをお任せでやってくれるというイメージ」「ほほ〜」「だからこのサービスはバッチ処理に向いてると思うんですよね」「確かに使いみちはありそうっすね: しかしServerlessかと言うとw」「Aurora On-Demandとかそういう名前の方がよくね?」「流行り言葉だからServerlessって言ってみるテスト?」「インスタンスを起動するのに1分とかかかるから、即時性を要求するものよりは、やっぱりバッチ処理に向いてるんじゃないかなー🤔」

「Lambdaと相性がいいとかあるんですかね?」「いや特に😆」「Lambdaも即時応答を必要としないバッチ的なものならいけるでしょうし☺️」

「そういえばAWS Batchってのもありますね?」「あれはただのバッチで🤣、cron的にEC2インスタンスを起動してコマンドを実行して終わったらインスタンスを落とすとかに使う」「なんだ🤣」

Cookieの次はSec-HTTP-Stateヘッダ

Sec-HTTP-State: token=J6BRKagRIECKdpbDLxtlNzmjKo8MXTjyMomIwMFMonM

Googleの中の人です。

draft-cdn-loop-prevention-00 - CDN Loop Preventionというのもありました。

参考: Cookieにかわる Sec-HTTP-State ヘッダの提案 - ASnoKaze blog


つっつきボイス:「これはてブで見ましたネ」「先週出した勉強会記事↓の最後のステートレスとステートフルの話にも書きましたけど、CookieってステートレスなHTTPプロトコルの上でステートフルな振る舞いを実現するために使われまくっているわけで、WebアプリがCookie使ってステートフルなのはもう当たり前になってしまってますよね」「ですねー」「それほどまでに使われているのに、Cookieって未だに不便なところが多すぎ😭」「記事にあるけど『secure属性やhttp-only属性の利用率は10%に達してない』のが悲しすぎる😢」「かーなーしぃー😞」

Webアプリの基礎とさまざまな実行環境を理解する#3(社内勉強会)

「ブラウザを替えると動かなくなるアプリだって多すぎるんだし、それなら新しいものを定義した方がいいっていう発想は自然」「↓こういうの見るとCookieも限界だなって思いますね」

Cookie request header is 409 bytes, while the 90th percentile is 1,589 bytes, the 95th 2,549 bytes, and the 99th 4,601 bytes
同記事より

「問題なのはCookieの仕様がレガシーすぎることで、ブラウザのCookie APIを生で触るとかホント地獄ですよ💀やったことあります?」「ありますw」「あそこにはいわゆるPOSTパラメータがそのまんま入ってるんで、JSON的にオブジェクトをCookieに格納しようと思ったら自分でシリアライズしないといけないという🤮」「一応js-cookie↓というのを使うとキーに保存できますけどね」「つかそもそもCookieだけではキーにセットすることすらできないんだからぁああ😤」「CSSですらやれることもできないCookieって…😅」

「その点SessionStorageとかlocalStorageはキーバリューストアとして使えることが保証されているんで、断然使いやすいですね😍」「GoogleスプレッドシートのデータとかはlocalStorageに保存されてるんでしょうね…」「バカでかいJSONデータみたいなものはよくlocalStorageにそのまんま放り込まれてたりしますね🗻」「indexedDBなんかは確かSQLライクにちゃんと扱えるんですよね?」「そうそう😋あんまり実装されてないけど」

参考: HTML5 SessionStorageの使い方 - WebStorageを使ってみよう!
参考: Window.localStorage - Web API インターフェイス | MDN

REST APIはデータベースではない(Awesome Rubyより)


同記事より


つっつきボイス:「RESTはー、データベースじゃー、ないよー😆」「😆」「この絵好き↑」

go-health: ヘルスチェッカー


同記事より


同リポジトリより


つっつきボイス:「このGopherくんみたいな絵ってみんなどこから仕入れてるんだろか?😆」「😆」「眼球よく見たら完全な球体w」「ヘルスチェックっていかに軽くするかが至上命題ですね🧐」

ついでにこんなのを見つけちゃいました。


同リポジトリより

モバイル/Android/iOS

Lottie: Adobe After Effectsアニメーションを直接動かせるライブラリ


つっつきボイス:「BPSアプリチームとデザインチームがこれにちょっとざわついてました」「After Effectsを直接かけられるとはねー😲よく頑張ったなってマジで思う」

参考: Adobe Creative Cloud | プロのクリエイター向けソフトウェアとサービス

Flipper: Facebookのモバイルアプリデバッガ(JSer.infoより)



同サイトより


つっつきボイス:「うん、こういうのはいろいろあるけどやっぱり便利😋」「SafariのDeveloper Toolsとかでもある程度できるけど時々扱えない項目とかあったりしますね」

SQL

JOINのコスト(Postgres Weeklyより)

-- 同記事より
EXPLAIN ANALYZE
SELECT
    count(*)
FROM
    table_1 AS t1 INNER JOIN
    table_2 AS t2 ON
        t1.id = t2.table_1_id INNER JOIN
    table_3 AS t3 ON
        t2.id = t3.table_2_id INNER JOIN
    table_4 AS t4 ON
        t3.id = t4.table_3_id INNER JOIN
    table_5 AS t5 ON
        t4.id = t5.table_4_id
WHERE
    t1.id <= 10;

                                                                            QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=88.52..88.53 rows=1 width=8) (actual time=0.411..0.411 rows=1 loops=1)
   ->  Nested Loop  (cost=1.43..88.50 rows=9 width=0) (actual time=0.067..0.399 rows=10 loops=1)
         ->  Nested Loop  (cost=1.14..85.42 rows=9 width=4) (actual time=0.054..0.304 rows=10 loops=1)
               ->  Nested Loop  (cost=0.86..82.34 rows=9 width=4) (actual time=0.043..0.214 rows=10 loops=1)
                     ->  Nested Loop  (cost=0.57..79.25 rows=9 width=4) (actual time=0.032..0.113 rows=10 loops=1)
                           ->  Index Only Scan using table_1_pkey on table_1 t1  (cost=0.29..8.44 rows=9 width=4) (actual time=0.015..0.023 rows=10 loops=1)
                                 Index Cond: (id <= 10)
                                 Heap Fetches: 10
                           ->  Index Scan using table_2_table_1_id_idx on table_2 t2  (cost=0.29..7.86 rows=1 width=8) (actual time=0.007..0.007 rows=1 loops=10)
                                 Index Cond: (table_1_id = t1.id)
                     ->  Index Scan using table_3_table_2_id_idx on table_3 t3  (cost=0.29..0.33 rows=1 width=8) (actual time=0.008..0.008 rows=1 loops=10)
                           Index Cond: (table_2_id = t2.id)
               ->  Index Scan using table_4_table_3_id_idx on table_4 t4  (cost=0.29..0.33 rows=1 width=8) (actual time=0.007..0.008 rows=1 loops=10)
                     Index Cond: (table_3_id = t3.id)
         ->  Index Only Scan using table_5_table_4_id_idx on table_5 t5  (cost=0.29..0.33 rows=1 width=4) (actual time=0.007..0.008 rows=1 loops=10)
               Index Cond: (table_4_id = t4.id)
               Heap Fetches: 10
 Planning time: 2.287 ms
 Execution time: 0.546 ms
(19 rows)

しょっぱなで「場合によりけり」とあります。


つっつきボイス:「おータイトルがかっこいいなー😎」「↑ぽすぐれはこうやってクエリプランがとっても読みやすいのがホントいい❤️」「MySQLのクエリプランは、読めるけど読めないw」「フォーマットしてハイライトしてもあかん感じでしょうか?」「MySQLのはテーブルで出力されるますしねー💦」「クエリがどういう戦略で組み立てられたのかが結局よくわかんない😭だからforce indexしたりwhereの順序を変えたりとかして試さないと」「最後はログからMySQL様のお気持ちを読み取ることに🤣」「そうそう🤣」

「ポスグレの出力はどこを評価したらどうなったかというのが逐一分かるのがエライ」「しかも数値付きだし」


同記事より

[Rails] RubyistのためのPostgreSQL EXPLAINガイド(翻訳)

時間のかかるクエリ


つっつきボイス:「これMySQLだし」「およ、Using temporaryしてるし↓これはヤバいやつ」「というと?」「これをやると中間テーブルを一度ファイルに出すんですけど、そうすると何やかんやでディスクがボトルネックになっていく」「あぁ〜😲」「それがサブクエリになってたりするともうあかん🤣」「🤣」

+------+-------------+-----------------+--------+---------------+---------+
| id   | select_type | table           | type   | possible_keys | key     |
+------+-------------+-----------------+--------+---------------+---------+
|    1 | SIMPLE      | project_commits | ALL    | NULL          | NULL    |
|    1 | SIMPLE      | commits         | eq_ref | PRIMARY       | PRIMARY |
+------+-------------+-----------------+--------+---------------+---------+

+---------+-------------------------------------+------------+-----------------+
| key_len | ref                                 | rows       | Extra           |
+---------+-------------------------------------+------------+-----------------+
| NULL    | NULL                                | 5417294109 | Using temporary |
| 4       | ghtorrent.project_commits.commit_id |          1 |                 |
+---------+-------------------------------------+------------+-----------------+

追いかけボイス: もう少し具体的にはこんな流れ:

  • JOINやサブクエリで必要な一時テーブルのサイズがtmp_table_sizeとかmax_heap_table_size(今は名前違うかも?)とかから算出されるサイズを超えるとtemporary tableとしてファイルに書き出し始める
  • ↑の時点で既に激遅いのに、さらにファイル書き出し&READが発生するため、OS側で空きメモリを使って実施しているファイルキャッシュがゴリゴリ破棄されていく
  • 他のプロセスのキャッシュもガンガンページアウトされ、次回参照時にまたディスクから読みに行く
  • 実質メモリ足りない時のスラッシングに近い状況が発生する

「『5 billion rows and commits 847 million rows』というボリュームでやってたらそうなりそう: よく10日も待ってたって思う😢」「クエリがなかなか戻ってこない時の判断って迷うよね: productionでどれぐらい時間かかるクエリを回したことあります?」「productionじゃないけど、移行の時にproduction相当のセッティングにして3時間経っても戻ってこないからこれは絶対何かおかしいと思って、速攻アプリを閉じてOracleを再起動したら10分かからずに返ってきましたね🤣」「🤣」「チューニング無しで12時間かかるクエリをチューニングして6時間まで短縮して、それをproductionで回したことならある😆」「夜が明けるまでが勝負のヤツですね」「SQLで1000行ぐらいあったかな」「ぶほっ」「SQLのありがたいところは、途中でエラーがraiseされたりしないところですね☺️」

JavaScript

Vue.jsのAsyncコンポーネント

// static import
import utils from "./utils";

// dynamic import
import("./utils").then(utils => {
  // utils module is available here...
});

つっつきボイス:「thenで書けるようになったってことみたい」「thenってES2015あたりで入ってきたんだったかな?」「Promiseのthenですね」

参考: Promise - JavaScript | MDN

「そういえばRubyでもthen入ってきましたね」「あーyield_selfの名前がRubyKaigiで変わったヤツ」「へー知らなかった」

Ruby 2.5の`yield_self`が想像以上に何だかスゴい件について(翻訳)

WebpackのHMR(Hot Module Replacement)とは


つっつきボイス:「HMRは今日の社内の勉強会の発表で出てきたので: Webpackerのつらさがよくわかるスライドでした☺️」

参考: モジュールをHMRに対応するための実装について - Qiita

Electron Fiddle(JavaScript Weeklyより)


同記事より

Fiddleで書いたものをElectron Forgeを使ってElectronアプリにできるようです。


electronforge.ioより

CSS/HTML/フロントエンド/テスト

配色アイデア見本2018年保存版


つっつきボイス:「BPSデザインチームが感動してました: とってもキレイですね」「こういうのは自分で直接カラーパレットいじるとろくなことにならないという」「カラーパレットはやっぱりツールを使って選ぶべきですねー」「そういうサイトもいろいろあるし」「Photoshopにもありますし」

WordPressの編集画面が5.0で変わる

WordPressの更新情報で気が付きました。

参考: Before Gutenberg - WordPress 5.0になるまでに準備すべきこと - Capital P


つっつきボイス:「どうよくなるのか次第ですけどねー」「今までのTinyMCEがあまりに歴史古いし: 相当前からある」「TinyMCEで編集中にdivから抜けたつもりでEnter押してたら抜けてなかったなんてことあった😢」「TinyMCEの出た頃ってtableレイアウト全盛でしたね☺️」「Gutenbergになったらどうなるのかちょっとだけ心配っす: Markdownしか使わないけど」「Markdownは大丈夫でしょうきっと」


tiny.cloudより

参考: TinyMCE - Wikipedia

言語よろずの間

lem: Common LISPベースのEmacsエディタ


同リポジトリより


つっつきボイス:「まあエディタは好きなものを使えばいいんじゃね?☺️」「これCLIでも動きそう」「Emacsはめちゃ重いからな〜(と起動してみる)お、一回起動すると速いのかな?: 久しぶりにEmacs起動したし😆」

追いかけボイス:「どうやら以前入れていたspaceemacsが重すぎてMac更新時に捨てていたので速かったようです: 今は.emacsファイルすらないという」

コンパイラは新しいフレームワークだ

「Webの人も今こそコンパイラの仕組みを学ぼう」という結論でした。


つっつきボイス:「コンパイラのことは知ってて損はないと思いますね: 『こういうコードは最適化が効きやすい』みたいのを押さえておけばスクリプトエンジンの最適化を活用できるし」

日本語や中国語でルビをマークアップする(Awesome Rubyより)


同記事より


つっつきボイス:「Rubyじゃなくてルビということで」「これ見てると例の文字渦↓を思い出しちゃう」「それそれ」「やっぱスゲー」「タイトルは中島敦の『文字禍』のもじりなんでしょうね」「このルビはまったく別の文章?」「二重化されてるっぽいですね」「他のページはもっとスゴイのかも?」

参考: 文字禍 - Wikipedia

その他言語

その他

安価なMacbook欲しい

Intel CPUの「Foreshadow」脆弱性の解説ムービー

投機的実行の脆弱性、Turing Complete FMでも話されていたような覚えがあります。


つっつきボイス:「これはMeltdownとかとまた別の脆弱性?」「そうみたいです」「L1キャッシュをクリアすると安全にはなるけど遅くなっちゃうんですよね」

参考: IntelのCPUで新たに発見された脆弱性「Foreshadow」の解説ムービーをRedHatが公開中 - GIGAZINE

世界最悪のログイン処理コードを鑑賞


つっつきボイス:「これはホントすごいよなー: 首を傾げ度がヤバい😆」「"true" === "true"とか」「apiService.sql()とか」「腹いてー🤣」「ツッコミどころしかない🔫」「コワイよ〜」

「C言語だったら"true" === "true"みたいなのを書くことはたまにあるけど」「お?」「パイプラインを強制的にフォールトさせるときとか: コンパイラの最適化を全部オフにしておいてブランチ命令を実行することでパイプラインを無理やり落とすという」「ま、そういうのは普通インラインアセンブラでやるでしょうけど😆」

追いかけボイス: 「組み込み向けのマイコン開発などではこういうことが割とあります: CPU初期化系のレジスタ更新がスペックシート上はすぐに反映されそうに書いてあっても、実際には数クロック待たないと反映されないケースではNOP NOP NOP NOPしたりするなどです」

その他のその他


番外

回路で遊ぶ

木星並の漂流惑星が発見される

記事の方ではこの惑星をNibiruと呼んでました。

参考: ニビル (仮説上の惑星) - Wikipedia
参考: どの星系にも属さず宇宙を漂流する巨大惑星を発見 - NRAOなど | マイナビニュース


今回は以上です。

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

週刊Railsウォッチ(20180813)Rails 5.2.1リリース、sanitize_sql_arrayは5.2からpublicだった、Dev.toがRailsアプリのソースを公開ほか

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

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

Rails公式ニュース

Ruby Weekly

Awesome Ruby

RubyFlow

160928_1638_XvIP4h

Hacklines

Hacklines

WebOps Weekly

webops_weekly_banner

Postgres Weekly

postgres_weekly_banner

JSer.info

jser.info_logo_captured

JavaScript Weekly

javascriptweekly_logo_captured

デザインも頼めるシステム開発会社をお探しなら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探訪シリーズ