belongs_to_required_by_defaultが効かない。 このエントリーを含むはてなブックマーク はてなブックマーク - belongs_to_required_by_defaultが効かない。

2016 年 8 月 17 日 Comments off

Rails 5.0.0からbelongs_toがデフォルトで必須になったはずなのだけれど、そうなっていなかったので調べた。
結論から言うと「config/initializers/new_framework_defaults.rb」に置いたままではダメで、「config/application.rb」に書かないといけない。
理由は読まれるタイミングと使われるタイミング。(またこれか)

最初に、belongs_toの必須が定義されるのはここで、「model.belongs_to_required_by_default」が元になっている。
activerecord-5.0.0.1/lib/active_record/associations/builder/belongs_to.rb

128       if reflection.options[:optional].nil?
129         required = model.belongs_to_required_by_default
130       else
131         required = !reflection.options[:optional]
132       end

で、上の「model.belongs_to_required_by_default」がどこでセットされるかというと、ここ。追加したコメントはあとで出てきます。
activesupport-5.0.0.1/lib/active_support/core_ext/module/attribute_accessors.rb

123       class_eval(<<-EOS, __FILE__, __LINE__ + 1)
124         @@#{sym} = nil unless defined? @@#{sym}
125
126         def self.#{sym}=(obj)
127 #{if sym == :belongs_to_required_by_default
128 'puts "#{name}.#{__method__} # ここで決まる!"'
129 end}
130           @@#{sym} = obj
131         end
132       EOS

って書いても分かりにくいので、コメントを仕込んでタイミングを表示してみた。こんな感じ。

config/application.rb

20 puts "#{__FILE__.sub("#{Rails.root}/", '')}:#{__LINE__} Rails.application.config.active_record.belongs_to_required_by_default #=> #{Rails.application.config.active_record.belongs_to_required_by_default}"
 21   config.active_record.belongs_to_required_by_default = true # ここに書かないとダメ!
 22 puts "#{__FILE__.sub("#{Rails.root}/", '')}:#{__LINE__} Rails.application.config.active_record.belongs_to_required_by_default #=> #{Rails.application.config.active_record.belongs_to_required_by_default}"

config/initializers/new_framework_defaults.rb

17 # Require `belongs_to` associations by default. Previous versions had false.
 18 puts "#{__FILE__.sub("#{Rails.root}/", '')}:#{__LINE__} Rails.application.config.active_record.belongs_to_required_by_default #=> #{Rails.application.config.active_record.belongs_to_required_by_default}"
 19 Rails.application.config.active_record.belongs_to_required_by_default = true
 20 puts "#{__FILE__.sub("#{Rails.root}/", '')}:#{__LINE__} Rails.application.config.active_record.belongs_to_required_by_default #=> #{Rails.application.config.active_record.belongs_to_required_by_default}"

まずは「config/application.rb」に書かなかった場合

% bundle exec rails c
config/application.rb:20 Rails.application.config.active_record.belongs_to_required_by_default #=>
config/application.rb:22 Rails.application.config.active_record.belongs_to_required_by_default #=>
config/initializers/new_framework_defaults.rb:18 Rails.application.config.active_record.belongs_to_required_by_default #=>
config/initializers/new_framework_defaults.rb:20 Rails.application.config.active_record.belongs_to_required_by_default #=> true
Loading development environment (Rails 5.0.0.1)
irb(main):001:0> ActiveRecord::Base.belongs_to_required_by_default
=> nil

つぎに「config/application.rb」に書いた場合

% bundle exec rails c
config/application.rb:20 Rails.application.config.active_record.belongs_to_required_by_default #=>
config/application.rb:22 Rails.application.config.active_record.belongs_to_required_by_default #=> true
ActiveRecord::Base.belongs_to_required_by_default= # ここで決まる!
config/initializers/new_framework_defaults.rb:18 Rails.application.config.active_record.belongs_to_required_by_default #=> true
config/initializers/new_framework_defaults.rb:20 Rails.application.config.active_record.belongs_to_required_by_default #=> true
Loading development environment (Rails 5.0.0.1)
irb(main):001:0> ActiveRecord::Base.belongs_to_required_by_default
=> true

config/application.rb」に書かないとnilのままなんだね・・・。

って、すぐ遭遇しそうなことなので、自分が基本的なことを見落としている気がしてきたぞ。

カテゴリー: Rails タグ:

time_zoneはconfig/initializersに移しちゃ(まだ?)ダメっぽい。 このエントリーを含むはてなブックマーク はてなブックマーク - time_zoneはconfig/initializersに移しちゃ(まだ?)ダメっぽい。

2016 年 8 月 11 日 Comments off
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
# config.time_zone = 'Central Time (US & Canada)'

config/application.rbにあったこのコメントがRails 5.0.0から消えたので、config/initializersに移動すべきと解釈してファイルを分けたら効かなくなってしまった。
理由は、config/initializersが読まれる前にconfig.time_zoneが使われてしまうから。

なので、まだconfig.time_zoneはconfig/application.rbに書いておかないといけない。
気になってconfig.i18n.default_localeも調べたらこっちは大丈夫だった。

それぞれの読まれる/使われる順番はこんな感じ。

% bundle exec rails c
config/application.rb:21
vendor/bundle/gems/activesupport-5.0.0/lib/active_support/railtie.rb:32 Time.zone #=>
vendor/bundle/gems/activesupport-5.0.0/lib/active_support/railtie.rb:33 Time.zone #=> (GMT+00:00) UTC
config/initializers/i18n.rb:1
config/initializers/time_zone.rb:1
vendor/bundle/gems/activesupport-5.0.0/lib/active_support/i18n_railtie.rb:49 I18n.default_locale #=> en
vendor/bundle/gems/activesupport-5.0.0/lib/active_support/i18n_railtie.rb:51 I18n.default_locale #=> ja
Loading development environment (Rails 5.0.0)
irb(main):001:0> Time.zone
=> #<ActiveSupport::TimeZone:0x007f97bc001968 @name="UTC", @utc_offset=nil, @tzinfo=#<TZInfo::DataTimezone: Etc/UTC>>
irb(main):002:0> I18n.default_locale
=> :ja
カテゴリー: Rails タグ:

per_form_csrf_tokensはどう影響するのか。 このエントリーを含むはてなブックマーク はてなブックマーク - per_form_csrf_tokensはどう影響するのか。

2016 年 8 月 10 日 Comments off

Configuring Rails Applications — Ruby on Rails Guides

config.action_controller.per_form_csrf_tokens configures whether CSRF tokens are only valid for the method/action they were generated for.

5.0から加わったこれ、tokenがmethodとactionに関連付くようになるオプションということで、自分でform_authenticity_tokenを直に呼んでいるところでは影響を受けるのかが気になってコードを読んでみた。
結果から言うと、自分でform_authenticity_tokenを呼んでいる場合には影響を受けない。

rails/request_forgery_protection.rb at master · rails/rails

# Sets the token value for the current session.
def form_authenticity_token(form_options: {})
  masked_authenticity_token(session, form_options: form_options)
end

form_authenticity_tokenはform_optionsを引数で受け取っていて、デフォルトは空になってる。

rails/request_forgery_protection.rb at master · rails/rails

# Creates a masked version of the authenticity token that varies
# on each request. The masking is used to mitigate SSL attacks
# like BREACH.
def masked_authenticity_token(session, form_options: {})
  action, method = form_options.values_at(:action, :method)
  raw_token = if per_form_csrf_tokens && action && method
    action_path = normalize_action_path(action)
    per_form_csrf_token(session, action_path, method)
  else
    real_csrf_token(session)
  end

form_authenticity_tokenで受け取った引数はこんな感じで使われる。
ここのper_form_csrf_tokensは、config/initializers/new_framework_defaults.rbにあるやつそのもの。

ではform_optionsはどこから来るのかっていうと、ここ。

rails/url_helper.rb at master · rails/rails

def token_tag(token=nil, form_options: {})
  if token != false && protect_against_forgery?
    token ||= form_authenticity_token(form_options: form_options)
    tag(:input, type: "hidden", name: request_forgery_protection_token.to_s, value: token)
  else
    "".freeze
  end
end

url_helperの中だ。

ひとまず影響がないことが分かったけれど変わりやすそうな場所ではあるので、注意が必要かな。

カテゴリー: Rails タグ:

nginx.confの変数は読みやすさのために使うな。 このエントリーを含むはてなブックマーク はてなブックマーク - nginx.confの変数は読みやすさのために使うな。

2016 年 7 月 21 日 Comments off

Is there a proper way to use nginx variables to make sections of the configuration shorter, using them as macros for making parts of configuration work as templates?

Variables should not be used as template macros. Variables are evaluated in the run-time during the processing of each request, so they are rather costly compared to plain static configuration. Using variables to store static strings is also a bad idea. Instead, a macro expansion and “include” directives should be used to generate configs more easily and it can be done with the external tools, e.g. sed + make or any other common template mechanism.

意訳:リクエストの度に余計な負荷が掛かるから、変数使わないでベタに書け。読みやすくしたいなら他の方法を使え。

capistrano-puma/puma.rake at master · seuros/capistrano-puma

upload! StringIO.new(ERB.new(erb, nil, ‘-‘).result(binding)), to

ということで、同じ時期に触ってたcapistrano-pumaが同じようなことでerb使ってたのでマネしました。

カテゴリー: プログラミング一般 タグ:

メールアドレスの属性名について。 このエントリーを含むはてなブックマーク はてなブックマーク - メールアドレスの属性名について。

2016 年 6 月 13 日 Comments off

ソースコードにでてくる「メールアドレス」を表す属性名が「e-mail」や「e_mail」、「email」でブレてたのが、いつの間にか「email」に統一された気がすると思っていたら、根拠がここにあった(のかもしれない)というはなし。

「Internet」と「Web」が終了

言葉は生き物だ。大文字・小文字の変化の他に、ハイフンやスペースの変化、すなわち2語が1語になる変化もある。2011年に「e-mail」は「email」に、2010年に「Web site」は「Website」(6月1日からは「website」)になっている。

空白や記号を含まない一語になってくれると、変数名として使いやすくてうれしい。
名前を決めるのに、ブレが気になって時々すごく時間が掛かることがあるので、ね。

なんとか名について。 » サイキョウライン

さて、どうしましょ。

カテゴリー: プログラミング一般 タグ:

tmuxのutf8オプションについて。 このエントリーを含むはてなブックマーク はてなブックマーク - tmuxのutf8オプションについて。

2016 年 5 月 25 日 Comments off
.tmux.conf:15: unknown option: status-utf8
.tmux.conf:16: unknown option: utf8

tmuxを2.2に上げたらこんなことを言われたので、調べたらこのオプションが不要になって、かつ削除されてるとのこと。

tmux reports “unknown option: status-utf8” on startup · Issue #230 · tmux/tmux

It is no longer necessary.

confを書き換えた。

カテゴリー: コンピュータ一般 タグ:

Ubuntuのinterfacesについて。 このエントリーを含むはてなブックマーク はてなブックマーク - Ubuntuのinterfacesについて。

2016 年 5 月 13 日 Comments off

16.04 LTSがリリースされたので開発環境を再構築していたのですが、初っ端から躓いたのでメモ。

NICを追加しようと「/etc/network/interfaces」を開くと「eth0」や「eth1」の記述がない。
代わりに「enp0s3」なんていう、知らない命名ルールの設定がありました。

ググってみたところどうやら15の時点で変わっていたようで、LTSしか見ていなかったので知りませんでした。
こちらではVirtualBoxにインストールしようとしていて、自分も同じパターンだったので、どストライクです。

Network Interfaces Name change in Ubuntu 15.10 (Wily Werewolf) | Ubuntu Geek

In Wily Werewolf, starting with systemd/udev will automatically assign predictable, stable network interface names for all local Ethernet, Wlan and Wwan interfaces.

で、知りたいのは追加する時にどういう名前を付ければ良いのかということ。

% ip link

というコマンドで、自動で振られている名前(enp0s8)が確認できました。

ここで「/etc/network/interfaces」に追記してもいいんですが、「/etc/network/interfaces.d」というディレクトリがあるということはそういうことなんだろうということで「/etc/network/interfaces.d/enp0s8」を新たに作って設定を書きました。

公式のドキュメントではまだ「ethX」を使うことになってた。

ネットワークの設定

Ethernet interfaces are identified by the system using the naming convention of ethX, where X represents a numeric value. The first Ethernet interface is typically identified as eth0, the second as eth1, and all others should move up in numerical order.

[2016-05-24 追記]
CentOS 7の記事ですがここの説明が分かり易かったのでメモ。

CentOS 7で始める最新Linux管理入門(3):CentOS 7のネットワーク管理「NetworkManager」を極める (2/5) – @IT

CentOS 7では、Udevというプログラムが「Predictable Network Interface Names」と呼ぶルールに沿ってNIC(ネットワークインタフェースカード)の命名を行います。

カテゴリー: Linux タグ:

隣り合わせの灰と青春を読んだ。 このエントリーを含むはてなブックマーク はてなブックマーク - 隣り合わせの灰と青春を読んだ。

2016 年 4 月 12 日 Comments off

リルガミンサーガとVのサントラをBGMにして。
初めて触れたのがファミコン版のIIIで、Wizといえば末弥純の画と羽田健太郎の曲だった。

サントラがリルガミンサーガとVしか手元にないのであらためて探したら、だいぶお高いことになってる。
欲しいけどこの値段はちょっとなぁ・・・。

カテゴリー: 日記 タグ:

IMAPですべて既読にするやつ。 このエントリーを含むはてなブックマーク はてなブックマーク - IMAPですべて既読にするやつ。

2016 年 3 月 8 日 Comments off

たまに必要になるので。しっかし、なんでreadじゃなくてseeなんだろ。

カテゴリー: Ruby タグ:

e-Taxソフトの電子署名でつまづいた。 このエントリーを含むはてなブックマーク はてなブックマーク - e-Taxソフトの電子署名でつまづいた。

2016 年 3 月 2 日 Comments off

申告データの用意をすませて電子署名をするところで。
住基カードを使って署名しようとしたところ、エラーコードは「SC00X010」で「ICカードを認識できませんでした。設定を確認の上、再試行してください。」とのこと。(スクショ忘れた。)
JPKI利用者ソフト単体でのカード読み取りテストは通っているのでリーダーは問題ないみたい。

昨年もe-Taxで申告してそのままだったので自動アップデートに任せたのだけれど、どうもそれが原因みたい。
JPKI利用者ソフトとe-Taxソフトの両方を一旦アンインストールして、JPKI利用者ソフト→e-Taxソフトの順で再インストールしたら問題なく署名、送信できました。
腑に落ちないけれど年1回のことなのでこれ以上は深入りしない。おしまい。

利用者クライアントソフトのダウンロード : 公的個人認証サービス ポータルサイト

利用者クライアントソフトとは、公的個人認証サービスを利用した行政手続き等を行うときに個人番号カード及び住民基本台帳カード(ICカード)に記録された電子証明書を利用するためのソフトウェアです。

e-Taxソフトダウンロードコーナー|e-Tax

e-Taxソフトについては、当コーナーからのダウンロードによる取得が可能です。

カテゴリー: 日記 タグ: