アーカイブ

2016 年 8 月 のアーカイブ

Rails4→5で目にしたdeprecationたち。 このエントリーを含むはてなブックマーク はてなブックマーク - Rails4→5で目にしたdeprecationたち。

2016 年 8 月 24 日 Comments off

なにかの役に立つかも知れないので、淡淡と書いておきます。

DEPRECATION WARNING: Method map is deprecated and will be removed in Rails 5.1, as `ActionController::Parameters` no longer inherits from hash. Using this deprecated behavior exposes potential security problems. If you continue to use this method you may be creating a security vulnerability in your app that can be exploited. Instead, consider using one of these documented methods which are not deprecated: http://api.rubyonrails.org/v5.0.0.1/classes/ActionController/Parameters.html

DEPRECATION WARNING: uniq is deprecated and will be removed from Rails 5.1 (use distinct instead)

DEPRECATION WARNING: `redirect_to :back` is deprecated and will be removed from Rails 5.1. Please use `redirect_back(fallback_location: fallback_location)` where `fallback_location` represents the location to use if the request has no HTTP referer information.

DEPRECATION WARNING: `render :text` is deprecated because it does not actually render a `text/plain` response. Switch to `render plain: 'plain text'` to render as `text/plain`, `render html: '<strong>HTML</strong>'` to render as `text/html`, or `render body: 'raw'` to match the deprecated behavior and render with the default Content-Type, which is `text/plain`.

DEPRECATION WARNING: xhr and xml_http_request methods are deprecated in favor of `get :index, xhr: true` and `post :create, xhr: true`

DEPRECATION WARNING: ActionController::TestCase HTTP request methods will accept only keyword arguments in future Rails versions.
Examples:
get :show, params: { id: 1 }, session: { user_id: 1 }
process :update, method: :post, params: { id: 1 }

カテゴリー: Rails タグ:

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 タグ: