ブログ開設して1年が経っていた

f:id:tanaken0515:20191020084715p:plain

メールが来てた。

数えたらこの記事で30記事目だった。

ほとんどの記事はですます調だったけど、最近はやめた。

自分はですます調で文章を書くと、なんとなく「化粧した文章」になってしまうと感じ始めたから。

ほんとに書きたいことを書けないというか。別に嘘を書いてるわけじゃないんだけど。

書きなぐっている感のある文章の方が素直にかけるような、そんな気がしてる。

特に最近は、自分方向へのアウトプットというか、未来の自分がリユース(?)するための文章というかんじ。

Scrapboxも使っているから、そこに全部まとめても良いんだけど。

Scrapboxは「寝ぐせついてて無精髭でパジャマ」、ブログは「一応寝ぐせ直してヒゲは剃っておくか〜服は適当だけど」くらいの使い分けをしてる。

Rails CHANGELOG "2019-10-07".."2019-10-13"

この期間の CHANGELOG.md へのコミットは3件。

ActionPack, ActiveModel, ActiveStorageに関してそれぞれ1件。

ActionPack

ActionDispatch::Request クラスのインスタンス変数 @remote_ip を更新できない不具合を修正した

コミット: Updated `ActionDispatch::Request.remote_ip=` · rails/rails@bf14a8e

修正は remote_ip= メソッドの @remote_ip = nil の一行だけ。

def remote_ip
  @remote_ip ||= (get_header("action_dispatch.remote_ip") || ip).to_s
end

def remote_ip=(remote_ip)
  @remote_ip = nil
  set_header "action_dispatch.remote_ip", remote_ip
end

引用: rails/request.rb at bf14a8e23526447b9893ed66090f898da68eb7f1 · rails/rails

@remote_ip = nil をせずに remote_ip メソッドを呼んでいたため、set済みの @remote_ip のまま書き変わらない不具合があった。

ActiveModel

freezeされた ActiveModel のオブジェクトに対して attribute の書き変えをできないようにした

コミット: Raise FrozenError for frozen objects when trying to write to a · rails/rails@54b1574

概要はCHANGELOG.mdにある例の通り。

class Animal
  include ActiveModel::Attributes  
  attribute :age 
end

animal = Animal.new
animal.freeze 
animal.age = 25 # => FrozenError, "can't modify a frozen Animal"

引用: rails/CHANGELOG.md at 54b157442171d28c7e9553537aef7a6ae571aad7 · rails/rails

修正は ActiveModel:: Attributes::ClassMethods モジュールの define_method_attribute= メソッド。

def define_method_attribute=(name)
  ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
    generated_attribute_methods, name, writer: true,
  ) do |temp_method_name, attr_name_expr|
    generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
      def #{temp_method_name}(value)
        raise FrozenError, "can't modify frozen #{self.class.name}" if frozen?
        name = #{attr_name_expr}
        write_attribute(name, value)
      end
    RUBY
  end
end

引用: rails/activemodel/lib/active_model/attributes.rb at 54b157442171d28c7e9553537aef7a6ae571aad7 · rails/rails

なるほどこういう実装になっていたのか〜。

ActiveStorage

ActiveStorage::Blob#url でパーマネントリンクを作れるようになった

コミット: Permanent URLs for public storage blobs · rails/rails@feab703

config/storage.yml に新しいキー public: true | false を設定することで、 true の場合はパーマネントリンクを作ることができる。未設定の場合は false で、今まで通り期限付きのリンクになる。

ActiveStorage::Blob#url を見てみる。ここでは service.url(ActiveStorage::Service#url) を呼んでる。

def url(expires_in: ActiveStorage.service_urls_expire_in, disposition: :inline, filename: nil, **options)
  filename = ActiveStorage::Filename.wrap(filename || self.filename)

  service.url key, expires_in: expires_in, filename: filename, content_type: content_type_for_service_url,
    disposition: forced_disposition_for_service_url || disposition, **options
end

引用: rails/blob.rb at feab7031b57040afa2b2f5f78f9251dbad6cbdf8 · rails/rails

ActiveStorage::Service#url を見てみる。if public?public_url or private_url に振り分けてる。

def url(key, **options)
  instrument :url, key: key do |payload|
    generated_url =
      if public?
        public_url(key, **options)
      else
        private_url(key, **options)
      end

    payload[:url] = generated_url

    generated_url
  end
end

引用: rails/service.rb at feab7031b57040afa2b2f5f78f9251dbad6cbdf8 · rails/rails

ActiveStorage::Service クラスの public_urlprivate_url は未実装(raise NotImplementedError)となっており、このクラスを継承している各ストレージサービスのクラスで public_urlprivate_url を実装している。具体的な実装は各クラスを参照。

子クラスで実装を分けたい(かつ未実装だったらエラー吐きたい)ときに、親クラスで raise NotImplementedError にしとくの便利。よくある(定石的な)実装なのかな。これまでまともにOSSのコードリーディングしてなかった&設計関連の本もほぼ読んでないからこの辺の設計論?みたいなもの、自論として確立できてないんだよなぁ。ともかく勉強になった。

Rails CHANGELOG "2019-10-01".."2019-10-06"

この期間の CHANGELOG.md へのコミットは5件。

ActiveRecordに関して2件、ActiveStorageに関して3件。

ActiveRecord

has_secure_token に文字数を指定できるようになった

コミット: Merge pull request #35915 from bernardoamc/allow-has-secure-token-len… · rails/rails@a273da7

もともとは24文字で固定だった。24文字以上の文字数を指定できるようになったので、セキュリティ的な要件で「めっちゃ長くしたい」場合もこれで安心。

Before:

has_secure_token :auth_token

After:

has_secure_token :default_token             # 24 characters
has_secure_token :auth_token, length: 36    # 36 characters
has_secure_token :invalid_token, length: 12 # => ActiveRecord::SecureToken::MinimumLengthError

引用: rails/activerecord/CHANGELOG.md at a273da7619ac6a2b2f98532a5610238c68ad219b · rails/rails

belongs_toinverse_of: オプションを has_many associationでも使えるようになった

コミット: Add support for belongs_to to has_many inversing. · rails/rails@d45c9ad

もともと belongs_toinverse_of: オプションは has_one associationにしか対応していなかった。これを has_many の場合でも使えるようになった。

たぶんこんな感じ(動作確認はしてない)

class User < ApplicationRecord
  has_many :writings,
           class_name: 'Book'
end
 
class Book < ApplicationRecord
  belongs_to :author,
             class_name: 'User',
             foreign_key: 'author_id'
             # ここに inverse_of: 'writings' を指定できるようになった。 
end

ActiveStorage

添付ファイルごとに保存先の外部サービスを選べるようになった

コミット: Allow configure services for individual attachments · rails/rails@e7f798c

ActiveStorageあまり触っていなくてよく分からん太郎だったのでRailsガイドで復習した。Active Storage の概要 - Rails ガイド

「セットアップ」に書かれているようにActiveStorageで使うサービスは config/storage.yml で定義して、環境ごとに config/environments/ 配下で設定する。これだと同一環境内で使えるサービスは1つだけになる。例えば「production では Amazon S3 を使う!!!1」など。

で、今回のコミットでは添付ファイルごとに保存先のサービスを選べるようになるよ、便利だね、という話。

class User < ActiveRecord::Base
  has_one_attached :avatar, service: :s3
end
class Gallery < ActiveRecord::Base
  has_many_attached :photos, service: :s3
end

引用: rails/activestorage/CHANGELOG.md at e7f798c3f549502d696167e9b29f18106cf2cbe0 · DmitryTsepelev/rails

active_storage_blobs テーブルに service_name カラムが追加されているからversion upの際にはmigrationが必要になりそう。

外部サービスに画像のvariantをアップロードするときにContent-Typeを指定するようになった

コミット: Set Content-Type on variant uploads · rails/rails@698e9ce

Content-Typeが指定されていなかったので指定したよ、というコミット。

Content-Typeは delegate :filename, :content_type, :format, to: :specification となっていて specification はこうなってた。

def specification
  @specification ||=
    if WEB_IMAGE_CONTENT_TYPES.include?(blob.content_type)
      Specification.new \
          filename: blob.filename,
          content_type: blob.content_type,
          format: nil
    else
      Specification.new \
          filename: ActiveStorage::Filename.new("#{blob.filename.base}.png"),
          content_type: "image/png",
          format: "png"
    end
end

引用: rails/variant.rb at 698e9ce0ffb516564e02053872077a2d5a287617 · rails/rails

ので、Content-Typeは WEB_IMAGE_CONTENT_TYPES(= %w[ image/png image/jpeg image/jpg image/gif ]) のどれか or "image/png" になる。

明示的にサービス名を指定しなくてもよくなった

コミット: Make Active Storage services aware of configuration names · rails/rails@e6487e8

1つ目の 添付ファイルごとに保存先の外部サービスを選べるようになった に関連する修正。

ActiveStorage::Service::Configurator クラスをbuildするときに config/storage.yml に指定されているサービス名を使うよう修正されている

def build(service_name)
  config = config_for(service_name.to_sym)
  resolve(config.fetch(:service)).build(
    **config, configurator: self, name: service_name
  )
end

引用: rails/configurator.rb at e6487e84fc0dae30d3b20b396404881e962f1f3a · rails/rails

で、ActiveStorage::Service クラスにインスタンス変数 name が追加され、has_one_attached :avatar, service: :s3 のようにサービスが指定された時だけ、その値で上書きする、という感じになっている

def build(configurator:, name:, service: nil, **service_config) #:nodoc:
  new(**service_config).tap do |service_instance|
    service_instance.name = name
  end
end

引用: rails/service.rb at e6487e84fc0dae30d3b20b396404881e962f1f3a · rails/rails

Ruby 2.6.5 が出てたので docker image を即更新しようとしたら即過ぎた

www.ruby-lang.org

で、Ruby 2.6.5 が出てた。

手元のRuby 2.6.4 で動いてるやつを更新しようとした。

$ docker-compose build
Building web
Step 1/10 : FROM ruby:2.6.5
ERROR: Service 'web' failed to build: manifest for ruby:2.6.5 not found

おぉ。

https://hub.docker.com/_/ruby を確認。なるほど確かに 2.6.5 はまだなかった。

おもむろに

2.6.4-buster, 2.6-buster, 2-buster, buster, 2.6.4, 2.6, 2, latest

のリンク先を眺める。

Update to 2.6.4 のコミットログへのリンクを見つけてクリック。

手元でこういうのをやればいいのかぁ、と寝ぼけて考え始める。

いや、冷静になるんだ自分。即でプルリク作られてるはずでしょ。

うん、ある、良かった。

Upgrade Ruby version 2.4.x to 2.4.8, 2.5.x to 2.5.7 and 2.6.x to 2.6.5 by JanDintel · Pull Request #296 · docker-library/ruby

見つけて数分後にマージされた。

けどまだ ruby:2.6.5 not found だ。(2019/10/02 00:50現在)

deployされてないのかな。マージされたら即デプロイというわけではないんだなぁ。

やる気スイッチが入ってるうちにシュッとあげようと思ったけど眠いな、寝よう。


追記: 2019/10/02 13:00

deployされてた。ので仕事から帰ったら上げよう。

memo: Rails CHANGELOG 2019-09

RailsのCHANGELOG.mdのフィードを購読し始めた - tanaken’s blog けどこのままだとサッと目を通しただけで流れてしまうからメモしておく。

1ヶ月で18コミットか。 Fix typo もちょいちょいあるな。

週1回くらいの頻度で各コミットについて思ったこと書き留めたほうがいいかも。

月1回で一気に書くのはダルくなってしまいそう。

何らかの記事を書く前提なら手を加えて自動化したいな。

"再現性のある能力" を考える

このツイートを見てからときどき「自分の "再現性のある能力" は何だろう」と考えてる。

けど「これだ」というものが見つかっていない。

多分このツイートが目に止まったのは、自分に "再現性のある能力" なんてあるのか?と少しドキッとしたからだと思う。

さて、そもそも "再現性のある能力" とは何だろう。

ツイートを見たときは『俺に任せて、XXなら出来るよ(自信あるよ)』と言える能力のことかなと思った。

もう少し分解して考えてみよう。

"再現性" とは何だろう。

測定の精度(precision)を表現する条件として、測定者、測定システムおよび測定場所が異なり、測定手順も異なることが望ましいという条件のもとでの実験により得られた測定結果のばらつきの大きさを表現する指標。これに対して、繰り返し性(併行精度:repeatability)とは、測定手順、測定者、測定システム、測定条件及び測定場所が同一で、短時間の繰り返し測定の結果から得られるばらつきの程度をいう。

再現性(さいげんせい)とは - コトバンク

なるほど、"再現性" は 測定結果のばらつきの大きさを表現する指標 だったのか。

「再現性がある」という表現は「測定結果のばらつきが小さい」という意味合いで捉えて良さそう。

さてここでの「測定」の対象は何だろう。

元のツイートを再度読むと、 自社に欲しい人を考えるとき という文脈なので、「業務においてその人が残す成果」を測定すると考えるのが自然かな。

となると "再現性のある能力" は「業務においてばらつきが小さい成果を残す能力」という意味になりそう。

「ばらつきが小さい成果」というのはどういうことかな。何かと何かを比べて初めて「ばらつき」という表現になりそう。「過去に残した成果と同じような成果」と解釈して良さそう。

加えて 測定者、測定システムおよび測定場所が異なり、測定手順も異なることが望ましいという条件のもとで とある。

これも加味すると "再現性のある能力" は「誰に、いつ、どこで、どのような方法で評価されても、過去に残した成果と同じような成果を残す能力」という意味になりそう

さて、ここまでを整理すると、冒頭の「自分の "再現性のある能力" は何だろう」という問いは、

「自分の『誰に、いつ、どこで、どのような方法で評価されても、過去に残した成果と同じような成果を残す能力』は何だろう」

という問いになる。

えー。何だろう。

ひとつ言えるのは、いろんなことをやっていろんな成果(良い成果も悪い成果も)を出している人は、 過去に残した成果と同じような成果を残す能力 がありそうかどうかを考える材料が増えるので、何もやってない人よりは良いんじゃないかなぁということ。

試行回数やサンプル数が多いほどまともな結果が出るし分析しやすくなる。はず。

ので、これまでやったことを書き出してみたり、今後いろんなことをやると、この問いの答えっぽいものが見えてくるんじゃないかなと思った。

RailsのCHANGELOG.mdのフィードを購読し始めた

GitHubの特定ファイルのフィード取得する方法ないのかな〜と思って調べたらあった。

qiita.com

この形式で取得できるとのこと。

https://github.com/{org or user}/{repo}/commits/{branch}/{path_to_file}.atom

Railsのことをもっと身近にしていきたい(知っていきたい)なぁと思っている中で、CHANGELOG.md に変更があった時だけその差分を読んでみると良いかも?と思っていたので、早速slackに通知するように設定した。

f:id:tanaken0515:20190831231257p:plain

よし、よさそう。