具体的な影響としてはたとえば次のように、SKUという単語をacronymとして設定しても、namespace
でモジュールを切ったらそれが反映されない。
# config/initializers/inflections.rb ActiveSupport::Inflector.inflections(:en) do |inflect| inflect.acronym 'SKU' inflect.acronym 'SKUs' end # config/routes.rb Rails.application.routes.draw do namespace :admin do resources :skus end end # app/controllers/admin/skus_controller.rb class Admin::SKUsController < ApplicationController def index render text: "ok" end end GET /admin/skus #=> ActionController::RoutingError (uninitialized constant Admin::SKUsController)
この例ではルーティングのadmin/skus
から"Admin::SKUsController"
っていう定数名を取得するところまでは問題ないんだけど、そこからconst_missing
をフックしてファイルを動的に読み込もうとしたときに、ここで"Admin::SKUsController".underscore
が"admin/sk_us_controllerを返すために適切なファイルのパスが取得できず、結果として
Admin::SKUsController`を定義できないために失敗してしまう。
対処法としては、定数名とファイル名の対応付けが事前にできていればいいのだから、次のようにautoload
しておけばよい。 ((eager_autoload
で包んだほうがいいかも?))
# config/application.rb とか module Admin autoload :SKUsController, Rails.root.join("app/controllers/admin/skus_controller") end
ちなみにこの件、4.1では修正されないみたいだ。
追記 2014-11-17
autoload
でコントローラの対応付けをするだけでは足りず、さらにviewのディレクトリとの対応付けをする必要もあった。
もうめんどくさくなったので、次のように4.2.xで入りそうなパッチをあてた。
# lib/fix_underscore.rb # https://github.com/rails/rails/blob/861b70e92f4a1fc0e465ffcf2ee62680519c8f6f/activesupport/lib/active_support/inflector/methods.rb からコピー require "active_support/inflector/methods" if Rails::VERSION::MAJOR == 4 if Rails::VERSION::MINOR < 2 module ActiveSupport module Inflector def underscore(camel_cased_word) return camel_cased_word unless camel_cased_word =~ /[A-Z-]|::/ word = camel_cased_word.to_s.gsub(/::/, '/') word.gsub!(/(?:(?<=([A-Za-z\d]))|\b)(#{inflections.acronym_regex})(?=\b|[^a-z])/) { "#{$1 && '_'}#{$2.downcase}" } word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2') word.gsub!(/([a-z\d])([A-Z])/,'\1_\2') word.tr!("-", "_") word.downcase! word end end end else ActiveSupport::Deprecation.warn "Patch for ActiveSupport::Inflector#underscore is included since Rails 4.2" end end # config/application.rb require File.expand_path("../../lib/fix_underscore", __FILE__)