1 일반적인 조언
기존 애플리케이션을 업그레이드하기 전에, 업그레이드할 만한 좋은 이유가 있는지 확인해야 합니다. 새로운 기능의 필요성, 오래된 코드에 대한 지원을 찾기가 점점 어려워지는 점, 그리고 사용 가능한 시간과 기술 등 여러 요소들의 균형을 맞춰야 합니다.
1.1 Test Coverage
애플리케이션이 업그레이드 후에도 여전히 작동하는지 확인하는 가장 좋은 방법은 업그레이드 프로세스를 시작하기 전에 좋은 test coverage를 확보하는 것입니다. 애플리케이션의 대부분을 실행하는 자동화된 테스트가 없다면, 변경된 모든 부분을 수동으로 테스트하는 데 시간을 투자해야 할 것입니다. Rails 업그레이드의 경우, 이는 애플리케이션의 모든 기능을 의미합니다. 업그레이드를 시작하기 전에 test coverage가 충분한지 확인하여 자신을 위한 선택을 하세요.
1.2 Ruby 버전
Rails는 일반적으로 새로 출시된 Ruby 버전을 긴밀하게 따릅니다:
- Rails 8.0은 Ruby 3.2.0 이상이 필요합니다.
- Rails 7.2는 Ruby 3.1.0 이상이 필요합니다.
- Rails 7.0과 7.1은 Ruby 2.7.0 이상이 필요합니다.
- Rails 6은 Ruby 2.5.0 이상이 필요합니다.
- Rails 5는 Ruby 2.2.2 이상이 필요합니다.
Ruby와 Rails를 따로 업그레이드하는 것이 좋습니다. 먼저 가능한 최신 Ruby 버전으로 업그레이드한 다음, Rails를 업그레이드하세요.
1.3 업그레이드 프로세스
Rails 버전을 변경할 때는 deprecation 경고를 효과적으로 활용하기 위해 한 번에 하나의 minor 버전씩 천천히 진행하는 것이 좋습니다. Rails 버전 번호는 Major.Minor.Patch 형식입니다. Major와 Minor 버전은 public API를 변경할 수 있으므로 애플리케이션에 오류가 발생할 수 있습니다. Patch 버전은 버그 수정만 포함하며 public API를 변경하지 않습니다.
프로세스는 다음과 같이 진행해야 합니다:
- 테스트를 작성하고 통과하는지 확인합니다.
- 현재 버전 이후의 최신 patch 버전으로 이동합니다.
- 테스트와 deprecated된 기능들을 수정합니다.
- 다음 minor 버전의 최신 patch 버전으로 이동합니다.
목표로 하는 Rails 버전에 도달할 때까지 이 프로세스를 반복합니다.
1.3.1 버전 간 이동
버전 간 이동하려면:
Gemfile
의 Rails 버전 번호를 변경하고bundle update rails
를 실행합니다.- jsbundling-rails를 실행 중인 경우
package.json
의 Rails JavaScript 패키지 버전을 변경하고bin/rails javascript:install
을 실행합니다. - Update task를 실행합니다.
- 테스트를 실행합니다.
모든 배포된 Rails gem 목록은 여기에서 찾을 수 있습니다.
1.4 Update 작업
Rails는 rails app:update
명령어를 제공합니다. Gemfile
에서 Rails 버전을 업데이트한 후에 이 명령어를 실행하세요.
이 명령어는 대화형 세션을 통해 새로운 파일 생성과 기존 파일의 변경을 도와줍니다.
$ bin/rails app:update
exist config
conflict config/application.rb
/myapp/config/application.rb를 덮어쓰시겠습니까? (도움말은 "h" 입력) [Ynaqdh]
force config/application.rb
create config/initializers/new_framework_defaults_8_0.rb
...
diff와 merge 도중 예상치 못한 변경사항이 있었는지 차이점을 검토하는 것을 잊지 마세요. 이 과정에서 사용되는 diff와 merge 도구는 THOR_DIFF
와 THOR_MERGE
환경 변수를 사용하여 정의할 수 있다는 점을 기억하세요.
1.5 Framework 기본값 설정
새로운 Rails 버전은 이전 버전과 다른 기본 설정 값을 가질 수 있습니다. 하지만 위에서 설명한 단계를 따른 후에도, 애플리케이션은 여전히 이전 Rails 버전의 기본 설정으로 실행될 것입니다. 이는 config/application.rb
의 config.load_defaults
값이 아직 변경되지 않았기 때문입니다.
새로운 기본값으로 하나씩 업그레이드할 수 있도록, update 작업은 config/initializers/new_framework_defaults_X_Y.rb
파일을 생성했습니다(파일명에 원하는 Rails 버전 포함). 파일 내의 주석을 해제하여 새로운 기본 설정을 활성화해야 합니다. 이는 여러 번의 배포를 거쳐 점진적으로 수행할 수 있습니다. 애플리케이션이 새로운 기본값으로 실행될 준비가 되면, 이 파일을 제거하고 config.load_defaults
값을 변경할 수 있습니다.
2 Rails 8.0에서 Rails 8.1로 업그레이드
Rails 8.1에서 변경된 사항에 대한 자세한 내용은 릴리스 노트를 참조하세요.
3 Rails 7.2에서 Rails 8.0으로 업그레이드
Rails 8.0에서 변경된 사항에 대한 자세한 내용은 릴리스 노트를 참조하세요.
4 Rails 7.1에서 Rails 7.2로 업그레이드
Rails 7.2에서 변경된 사항에 대한 자세한 내용은 릴리스 노트를 참조하세요.
4.1 모든 테스트가 이제 active_job.queue_adapter
설정을 준수합니다
config/application.rb
또는 config/environments/test.rb
파일에서 config.active_job.queue_adapter
를 설정한 경우,
이전에는 선택한 adapter가 모든 테스트에서 일관되게 사용되지 않았습니다. 일부 테스트에서는 설정한 adapter가 사용되었지만, 다른 테스트에서는 TestAdapter
가 사용되었습니다.
Rails 7.2에서는 모든 테스트가 제공된 queue_adapter
설정을 준수합니다. 만약 queue_adapter
설정을 :test
가 아닌 다른 것으로 설정했지만, TestAdapter
에 의존하는 방식으로 테스트를 작성한 경우 테스트 오류가 발생할 수 있습니다.
설정이 제공되지 않은 경우에는 계속해서 TestAdapter
가 사용됩니다.
5 Rails 7.0에서 Rails 7.1로 업그레이드
Rails 7.1의 변경사항에 대한 자세한 내용은 릴리스 노트를 참조하세요.
5.1 Development 및 test 환경의 secret_key_base 파일 변경
Development 및 test 환경에서 Rails가 secret_key_base
를 읽는 파일이 tmp/development_secret.txt
에서 tmp/local_secret.txt
로 이름이 변경되었습니다.
동일한 secret을 계속 사용하려면 이전 파일의 이름을 local_secret.txt
로 변경하거나, 이전 파일의 키를 새 파일로 복사하면 됩니다.
이렇게 하지 않으면 앱이 로드될 때 Rails가 새로운 파일 tmp/local_secret.txt
에 새로운 secret key를 생성합니다.
이로 인해 development 및 test 환경의 모든 기존 세션/쿠키가 무효화되며, Active Storage/Action Text 첨부파일과 같이 secret_key_base
로부터 파생된 다른 서명들도 작동하지 않게 됩니다.
Production 및 기타 환경은 영향을 받지 않습니다.
5.2 Autoload된 경로는 더 이상 $LOAD_PATH에 포함되지 않습니다
Rails 7.1부터 autoloader가 관리하는 디렉토리들은 더 이상 $LOAD_PATH
에 추가되지 않습니다. 이는 수동으로 require
호출을 통해 이러한 파일들을 로드할 수 없다는 것을 의미하며, 어차피 그렇게 해서는 안 됩니다.
$LOAD_PATH
의 크기를 줄이면 bootsnap
을 사용하지 않는 앱의 경우 require
호출 속도가 빨라지고, bootsnap
을 사용하는 앱의 경우 bootsnap
캐시의 크기가 줄어듭니다.
만약 이러한 경로들을 여전히 $LOAD_PATH
에 포함시키고 싶다면, 다음과 같이 opt-in할 수 있습니다:
config.add_autoload_paths_to_load_path = true
Rails가 $LOAD_PATH
에 autoload path들을 추가할지 여부를 설정합니다.
오래된 코드와의 호환성을 위해서는 true
로 설정해야 할 수 있습니다만, 기본값은 false
입니다.
이것은 Zeitwerk
mode가 활성화되었을 때만 적용됩니다.
하지만 우리는 그렇게 하는 것을 권장하지 않습니다. autoload paths에 있는 클래스와 모듈은 autoload되도록 설계되어 있습니다. 즉, 단순히 참조만 하면 됩니다.
lib
디렉토리는 이 설정의 영향을 받지 않으며, 항상 $LOAD_PATH
에 추가됩니다.
5.3 config.autoload_lib 및 config.autoload_lib_once
애플리케이션에서 lib
디렉토리가 autoload 또는 autoload once 경로에 포함되어 있지 않다면, 이 섹션을 건너뛰세요. 아래의 명령어 출력을 통해 확인할 수 있습니다.
# autoload 경로를 출력합니다.
$ bin/rails runner 'pp Rails.autoloaders.main.dirs'
# autoload once 경로를 출력합니다.
$ bin/rails runner 'pp Rails.autoloaders.once.dirs'
애플리케이션이 autoload paths에 이미 lib
를 가지고 있다면, 일반적으로 config/application.rb
에 다음과 같은 configuration이 있습니다
# lib 디렉터리를 autoload하되, eager load는 하지 않습니다 (간과될 수 있음).
config.autoload_paths << config.root.join("lib")
또는
# lib를 autoload하고 eager load도 합니다.
config.autoload_paths << config.root.join("lib")
config.eager_load_paths << config.root.join("lib")
or
# eager load path 들은 모두 autoload path 가 되므로 같은 결과입니다.
config.eager_load_paths << config.root.join("lib")
이것도 여전히 작동하지만, 이러한 코드를 더 간결한 코드로 대체하는 것이 권장됩니다
config.autoload_lib(ignore: %w(assets tasks))
lib 디렉토리를 autoload path에 추가하면서, 'assets'와 'tasks' 서브디렉토리는 제외합니다.
lib
하위 디렉토리 중에서 .rb
파일을 포함하지 않거나 reload 또는 eager load가 필요하지 않은 디렉토리는 ignore
리스트에 추가해주세요. 예를 들어, 애플리케이션에 lib/templates
, lib/generators
, 또는 lib/middleware
가 있다면, lib
를 기준으로 한 상대 경로로 이름을 추가하면 됩니다:
lib 디렉터리의 자동 로딩 설정이지만, %w(assets tasks templates generators middleware) 디렉터리들은 제외합니다.
이 한 줄의 코드로 config.eager_load
가 true
인 경우(production
모드에서 기본값) lib
폴더 내의 (무시되지 않은) 코드도 eager load될 것입니다. 이는 일반적으로 원하는 동작이지만, 만약 lib
가 이전에 eager load paths에 추가되지 않았고 그대로 유지하고 싶다면 다음과 같이 opt-out할 수 있습니다:
Rails.autoloaders.main.do_not_eager_load(config.root.join("lib"))
lib
디렉터리를 eager loading에서 제외합니다.
config.autoload_lib_once
메소드는 애플리케이션이 config.autoload_once_paths
에 lib
를 포함하고 있을 때의 동일한 역할을 하는 메소드입니다.
5.4 ActiveStorage::BaseController
가 더 이상 streaming concern을 포함하지 않음
커스텀 파일 제공 로직을 구현하기 위해 streaming을 사용하고 ActiveStorage::BaseController
를 상속하는 application controller는 이제 명시적으로 ActiveStorage::Streaming
module을 포함해야 합니다.
5.5 MemCacheStore
와 RedisCacheStore
가 이제 기본적으로 connection pooling을 사용합니다
connection_pool
gem이 activesupport
gem의 의존성으로 추가되었으며, MemCacheStore
와 RedisCacheStore
는 이제 기본적으로 connection pooling을 사용합니다.
connection pooling을 사용하지 않으려면, cache store를 구성할 때 :pool
옵션을 false
로 설정하세요:
config.cache_store = :mem_cache_store, "cache.example.com", { pool: false }
Rails에서의 캐싱 가이드에서 더 자세한 정보를 확인하세요.
5.6 SQLite3Adapter
가 이제 strict strings 모드에서 사용되도록 설정됨
strict strings 모드의 사용으로 큰따옴표로 된 문자열 리터럴이 비활성화됩니다.
SQLite는 큰따옴표로 된 문자열 리터럴과 관련해 몇 가지 특이사항이 있습니다. 먼저 큰따옴표로 된 문자열을 식별자 이름으로 간주하려고 시도하지만, 해당 식별자가 존재하지 않으면 문자열 리터럴로 간주합니다. 이로 인해 오타가 조용히 간과될 수 있습니다. 예를 들어, 존재하지 않는 컬럼에 대한 인덱스를 생성하는 것이 가능합니다. 자세한 내용은 SQLite 문서를 참조하세요.
SQLite3Adapter
를 strict 모드에서 사용하지 않으려면 이 동작을 비활성화할 수 있습니다:
# config/application.rb
config.active_record.sqlite3_adapter_strict_strings_by_default = false
SQLite adapter가 string literals를 strict하게 취급할지 여부를 지정합니다. false로 설정하면 legacy behavior가 유지됩니다. SQLite에서 'foo' = "foo"
와 같은 비교가 가능해집니다.
5.7 ActionMailer::Preview
를 위한 다중 미리보기 경로 지원
config.action_mailer.preview_path
옵션은 config.action_mailer.preview_paths
로 대체되었습니다. 이 설정 옵션에 경로를 추가하면 mailer preview를 검색할 때 해당 경로들이 사용됩니다.
config.action_mailer.preview_paths << "#{Rails.root}/lib/mailer_previews"
메일러 preview 파일을 검색할 추가 경로를 지정합니다.
5.8 config.i18n.raise_on_missing_translations = true
가 이제 누락된 모든 번역에서 예외를 발생시킵니다.
이전에는 view나 controller에서 호출될 때만 예외가 발생했습니다. 이제는 I18n.t
에 인식되지 않는 키가 제공될 때마다 예외가 발생합니다.
# config.i18n.raise_on_missing_translations = true 설정 시
# view나 controller에서:
t("missing.key") # 7.0에서 예외 발생, 7.1에서 예외 발생
I18n.t("missing.key") # 7.0에서 예외 발생하지 않음, 7.1에서 예외 발생
# 어디에서든:
I18n.t("missing.key") # 7.0에서 예외 발생하지 않음, 7.1에서 예외 발생
이 동작을 원하지 않는다면, config.i18n.raise_on_missing_translations = false
로 설정할 수 있습니다:
# config.i18n.raise_on_missing_translations = false 설정과 함께
# view나 controller에서:
t("missing.key") # 7.0에서 raise하지 않았고, 7.1에서도 raise하지 않음
I18n.t("missing.key") # 7.0에서 raise하지 않았고, 7.1에서도 raise하지 않음
# 어디서든:
I18n.t("missing.key") # 7.0에서 raise하지 않았고, 7.1에서도 raise하지 않음
또는 I18n.exception_handler
를 커스터마이즈할 수 있습니다.
자세한 내용은 i18n 가이드를 참조하세요.
AbstractController::Translation.raise_on_missing_translations
는 제거되었습니다. 이는 private API였으며, 만약 이를 사용하고 있었다면 config.i18n.raise_on_missing_translations
또는 커스텀 exception handler로 마이그레이션해야 합니다.
5.9 bin/rails test
가 이제 test:prepare
태스크를 실행합니다
bin/rails test
로 테스트를 실행할 때, 테스트가 실행되기 전에 rake test:prepare
태스크가 실행됩니다. 만약 test:prepare
태스크를 강화했다면, 테스트 실행 전에 해당 강화된 기능들이 실행될 것입니다. tailwindcss-rails
, jsbundling-rails
, cssbundling-rails
와 다른 서드파티 gem들이 이 태스크를 강화합니다.
자세한 내용은 Testing Rails Applications 가이드를 참고하세요.
단일 파일의 테스트를 실행할 경우(bin/rails test test/models/user_test.rb
), 실행 전에 test:prepare
가 실행되지 않습니다.
5.10 @rails/ujs
의 import 구문이 수정됨
Rails 7.1부터 @rails/ujs
에서 모듈을 import하는 구문이 수정되었습니다. Rails는 더 이상 @rails/ujs
에서 모듈을 직접 import하는 것을 지원하지 않습니다.
예를 들어, 라이브러리에서 함수를 import하려고 하면 실패할 것입니다:
import { fileInputSelector } from "@rails/ujs"
// 에러: '@rails/ujs'에서 'fileInputSelector'를 찾을 수 없습니다 (가능한 exports: default)
Rails 7.1에서는 사용자가 먼저 Rails 객체를 @rails/ujs
에서 직접 import 해야 합니다.
그런 다음 사용자는 Rails 객체에서 특정 모듈을 import 할 수 있습니다.
Rails 7.1의 import 예시는 다음과 같습니다:
import Rails from "@rails/ujs"
// 메서드 별칭 지정
const fileInputSelector = Rails.fileInputSelector
// 또는 사용되는 Rails 객체에서 직접 참조
Rails.fileInputSelector(...)
5.11 Rails.logger
가 이제 ActiveSupport::BroadcastLogger
인스턴스를 반환합니다
ActiveSupport::BroadcastLogger
클래스는 로그를 다양한 싱크(STDOUT, 로그 파일...)로 쉽게 브로드캐스트할 수 있게 해주는 새로운 logger입니다.
로그를 브로드캐스트하는 API(ActiveSupport::Logger.broadcast
메서드 사용)는 이전에 private이었으며 제거되었습니다.
만약 애플리케이션이나 라이브러리가 이 API에 의존하고 있었다면, 다음과 같은 변경이 필요합니다:
logger = Logger.new("some_file.log")
# Before(변경 전)
Rails.logger.extend(ActiveSupport::Logger.broadcast(logger))
# After(변경 후)
Rails.logger.broadcast_to(logger)
애플리케이션에서 커스텀 logger를 구성했다면, Rails.logger
는 모든 메서드를 래핑하고 프록시합니다. 이를 작동시키기 위해 별도의 변경이 필요하지 않습니다.
커스텀 logger 인스턴스에 접근해야 한다면, broadcasts
메서드를 사용하면 됩니다:
# config/application.rb
config.logger = MyLogger.new
# 애플리케이션 내 어디서나
puts Rails.logger.class #=> BroadcastLogger
puts Rails.logger.broadcasts #=> [MyLogger]
[assert_match][assert_match]
5.12 Active Record Encryption 알고리즘 변경사항
Active Record Encryption은 이제 해시 다이제스트 알고리즘으로 SHA-256을 사용합니다. 이전 Rails 버전에서 암호화된 데이터가 있다면, 다음 두 가지 시나리오를 고려해야 합니다:
config.active_support.key_generator_hash_digest_class
가 SHA-1(Rails 7.0 이전의 기본값)로 설정되어 있다면, Active Record Encryption에도 SHA-1을 설정해야 합니다:config.active_record.encryption.hash_digest_class = OpenSSL::Digest::SHA1
모든 데이터가 비결정적으로 암호화되었다면(deterministric: true로
encrypts
를 전달하지 않은 기본값), 대신 아래 시나리오 2처럼 Active Record Encryption에 SHA-256을 설정하고 다음 설정을 통해 이전에 SHA-1으로 암호화된 컬럼의 복호화를 허용할 수 있습니다:config.active_record.encryption.support_sha1_for_non_deterministic_encryption = true
config.active_support.key_generator_hash_digest_class
가 SHA-256(7.0의 새로운 기본값)으로 설정되어 있다면, Active Record Encryption에도 SHA-256을 설정해야 합니다:config.active_record.encryption.hash_digest_class = OpenSSL::Digest::SHA256
config.active_record.encryption.hash_digest_class
에 대한 자세한 내용은 Rails 애플리케이션 설정하기 가이드를 참조하세요.
추가로, 앞서 언급한 hash_digest_class
설정을 통해 SHA-256이 설정되어 있을 때도 일부 속성이 SHA-1로 암호화되는 버그를 해결하기 위해 새로운 설정 config.active_record.encryption.support_sha1_for_non_deterministic_encryption
이 도입되었습니다.
기본적으로 Rails 7.1에서는 config.active_record.encryption.support_sha1_for_non_deterministic_encryption
가 비활성화되어 있습니다. Rails 7.1 미만 버전에서 암호화된 데이터가 있고 앞서 언급한 버그의 영향을 받았을 것으로 생각된다면, 이 설정을 활성화해야 합니다:
config.active_record.encryption.support_sha1_for_non_deterministic_encryption = true
비결정적 암호화의 경우 SHA1 Hash를 지원하도록 활성화합니다.
암호화된 데이터를 다루고 있다면, 위의 내용을 주의 깊게 검토해주세요.
5.13 Controller Tests, Integration Tests 및 System Tests에서 예외를 처리하는 새로운 방법
config.action_dispatch.show_exceptions
설정은 Action Pack이 요청에 응답하는 동안 발생한 예외를 처리하는 방식을 제어합니다.
Rails 7.1 이전에는 config.action_dispatch.show_exceptions = true
를 설정하면 Action Pack이 예외를 포착하고 적절한 HTML 오류 페이지를 렌더링하도록 구성되었습니다. 예를 들어 ActiveRecord::RecordNotFound
예외를 발생시키는 대신 404 Not found
상태 코드와 함께 public/404.html
을 렌더링하는 식입니다. config.action_dispatch.show_exceptions = false
를 설정하면 Action Pack이 예외를 포착하지 않도록 구성되었습니다. Rails 7.1 이전에는 새 애플리케이션이 생성될 때 config/environments/test.rb
에 config.action_dispatch.show_exceptions = false
를 설정하는 코드가 포함되어 있었습니다.
Rails 7.1은 허용되는 값을 true
와 false
에서 :all
, :rescuable
, :none
으로 변경했습니다.
:all
- 모든 예외에 대해 HTML 오류 페이지를 렌더링 (true
와 동일):rescuable
-config.action_dispatch.rescue_responses
에 선언된 예외에 대해 HTML 오류 페이지를 렌더링:none
(false
와 동일) - 어떤 예외도 포착하지 않음
Rails 7.1 이후 생성된 애플리케이션은 config/environments/test.rb
에서 config.action_dispatch.show_exceptions = :rescuable
을 설정합니다. 업그레이드 시 기존 애플리케이션은 새로운 동작을 사용하기 위해 config.action_dispatch.show_exceptions = :rescuable
로 변경하거나, 기존 값을 해당하는 새 값으로 대체할 수 있습니다(true
는 :all
로, false
는 :none
으로 대체).
6 Rails 6.1에서 Rails 7.0으로 업그레이드
Rails 7.0의 변경 사항에 대한 자세한 내용은 릴리스 노트를 참조하세요.
6.1 ActionView::Helpers::UrlHelper#button_to
동작 변경
Rails 7.0부터 button_to
는 영속된 Active Record 객체가 버튼 URL을 생성하는 데 사용될 경우 patch
HTTP verb와 함께 form
태그를 렌더링합니다.
현재 동작을 유지하려면 method:
옵션을 명시적으로 전달하는 것을 고려하세요:
-button_to("POST 실행하기", [:my_custom_post_action_on_workshop, Workshop.find(1)])
+button_to("POST 실행하기", [:my_custom_post_action_on_workshop, Workshop.find(1)], method: :post)
또는 helper를 사용하여 URL을 만듭니다:
-button_to("POST 실행", [:my_custom_post_action_on_workshop, Workshop.find(1)])
+button_to("POST 실행", my_custom_post_action_on_workshop_workshop_path(Workshop.find(1)))
6.2 Spring
애플리케이션이 Spring을 사용하는 경우, 최소 3.0.0 버전으로 업그레이드해야 합니다. 그렇지 않으면
`mechanism=`가 ActiveSupport::Dependencies:Module에 대해 정의되지 않은 메서드
또한, config/environments/test.rb
에서 config.cache_classes
가 false
로 설정되어 있는지 확인하세요.
6.3 Sprockets는 이제 선택적 의존성입니다
rails
gem은 더 이상 sprockets-rails
에 의존하지 않습니다. 애플리케이션에서 여전히 Sprockets를 사용해야 하는 경우, Gemfile에 sprockets-rails
를 추가하세요.
gem "sprockets-rails"
6.4 애플리케이션은 zeitwerk
모드로 실행되어야 합니다
classic
모드로 실행 중인 애플리케이션은 zeitwerk
모드로 전환해야 합니다. 자세한 내용은 Classic to Zeitwerk HOWTO 가이드를 참조하세요.
6.5 setter config.autoloader=
가 삭제되었습니다
Rails 7에서는 autoloading 모드를 설정하는 설정점이 없어졌으며, config.autoloader=
가 삭제되었습니다. 어떤 이유로든 :zeitwerk
로 설정했다면, 그냥 제거하면 됩니다.
6.6 ActiveSupport::Dependencies
private API가 삭제됨
ActiveSupport::Dependencies
의 private API가 삭제되었습니다. 여기에는 hook!
, unhook!
, depend_on
, require_or_load
, mechanism
등의 메서드들이 포함됩니다.
주요 변경사항:
ActiveSupport::Dependencies.constantize
또는ActiveSupport::Dependencies.safe_constantize
를 사용했다면, 단순히String#constantize
또는String#safe_constantize
로 변경하세요.
ActiveSupport::Dependencies.constantize("User") # 더 이상 사용 불가
"User".constantize # 👍
ActiveSupport::Dependencies.mechanism
의 읽기 또는 쓰기 사용은config.cache_classes
를 적절히 접근하는 것으로 대체되어야 합니다.autoloader의 활동을 추적하고 싶다면,
ActiveSupport::Dependencies.verbose=
는 더 이상 사용할 수 없으며,config/application.rb
에Rails.autoloaders.log!
를 추가하면 됩니다.
ActiveSupport::Dependencies::Reference
, ActiveSupport::Dependencies::Blamable
등과 같은 보조 내부 클래스나 모듈들도 함께 삭제되었습니다.
6.7 초기화 중 Autoloading
to_prepare
블록 외부에서 초기화 중에 reloadable 상수를 autoload한 애플리케이션은 Rails 6.0부터 해당 상수가 unload되고 이러한 경고가 발생했습니다:
DEPRECATION WARNING: 초기화 시에 상수 를 자동으로 로드했습니다 ....
이런 방식은 더 이상 권장되지 않습니다. 초기화 중의 autoloading은
향후 Rails 버전에서 에러가 발생하게 될 것입니다.
...
만약 로그에서 이 warning이 계속 보인다면, autoloading guide의 애플리케이션 부팅 시 autoloading에 대한 섹션을 확인해주세요. 그렇지 않으면 Rails 7에서 NameError
가 발생할 것입니다.
once
autoloader가 관리하는 Constants는 초기화 중에 autoload 될 수 있으며, to_prepare
블록 없이도 정상적으로 사용할 수 있습니다. 하지만 이를 지원하기 위해 once
autoloader가 이제 더 일찍 설정됩니다. 애플리케이션에 custom inflections이 있고 once
autoloader가 이를 인식해야 하는 경우, config/initializers/inflections.rb
의 코드를 config/application.rb
의 애플리케이션 클래스 정의 본문으로 이동해야 합니다:
module MyApp
class Application < Rails::Application
# ...
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.acronym "HTML" # HTML과 같은 약어가 포함된 문자열을 변환할 때 약어 형태를 유지하도록 지정
end
end
end
6.8 config.autoload_once_paths
구성 기능
config.autoload_once_paths
는 config/application.rb
에 정의된 application 클래스의 body 또는 config/environments/*
의 환경 설정에서 설정할 수 있습니다.
마찬가지로 engine은 engine 클래스의 body나 환경 설정에서 해당 컬렉션을 구성할 수 있습니다.
그 후에는 컬렉션이 freeze되며, 이러한 경로에서 autoload할 수 있습니다. 특히 초기화 중에도 이러한 경로에서 autoload할 수 있습니다. 이들은 reload하지 않고 autoload/eager load만 수행하는 Rails.autoloaders.once
autoloader에 의해 관리됩니다.
환경 설정이 처리된 후에 이 설정을 구성했고 FrozenError
가 발생하는 경우, 코드 위치만 이동하면 됩니다.
6.9 ActionDispatch::Request#content_type
은 이제 Content-Type 헤더를 있는 그대로 반환합니다.
이전에는 ActionDispatch::Request#content_type
이 반환하는 값이 charset 부분을 포함하지 않았습니다.
이 동작이 변경되어 Content-Type 헤더의 charset 부분을 있는 그대로 포함하여 반환하게 되었습니다.
만약 MIME type만 필요하다면, 대신 ActionDispatch::Request#media_type
을 사용하세요.
이전:
request = ActionDispatch::Request.new("CONTENT_TYPE" => "text/csv; header=present; charset=utf-16", "REQUEST_METHOD" => "GET")
request.content_type #=> "text/csv"
죄송하지만 번역할 문서가 공유되지 않았습니다. Rails 가이드 문서를 공유해주시면 요청하신대로 번역을 도와드리겠습니다.
request = ActionDispatch::Request.new("Content-Type" => "text/csv; header=present; charset=utf-16", "REQUEST_METHOD" => "GET")
request.content_type #=> "text/csv; header=present; charset=utf-16"
request.media_type #=> "text/csv"
6.10 Key generator digest class 변경에는 cookie rotator가 필요합니다
Key generator의 기본 digest class가 SHA1에서 SHA256으로 변경됩니다. 이는 암호화된 쿠키를 포함하여 Rails에서 생성된 모든 암호화 메시지에 영향을 미칩니다.
이전 digest class를 사용하여 메시지를 읽으려면 rotator를 등록해야 합니다. 이를 하지 않으면 업그레이드 중에 사용자의 세션이 무효화될 수 있습니다.
다음은 암호화된 쿠키와 서명된 쿠키를 위한 rotator의 예시입니다.
config/initializers/cookie_rotator.rb
Rails.application.config.after_initialize do Rails.application.config.action_dispatch.cookies_rotations.tap do |cookies| authenticated_encrypted_cookie_salt = Rails.application.config.action_dispatch.authenticated_encrypted_cookie_salt signed_cookie_salt = Rails.application.config.action_dispatch.signed_cookie_salt
secret_key_base = Rails.application.secret_key_base
key_generator = ActiveSupport::KeyGenerator.new(
secret_key_base, iterations: 1000, hash_digest_class: OpenSSL::Digest::SHA1
)
key_len = ActiveSupport::MessageEncryptor.key_len
old_encrypted_secret = key_generator.generate_key(authenticated_encrypted_cookie_salt, key_len)
old_signed_secret = key_generator.generate_key(signed_cookie_salt)
cookies.rotate :encrypted, old_encrypted_secret
cookies.rotate :signed, old_signed_secret
end end
6.11 ActiveSupport::Digest의 Digest class가 SHA256으로 변경됨
ActiveSupport::Digest의 기본 digest class가 SHA1에서 SHA256으로 변경되었습니다. 이는 Etag와 같은 것들의 변경과 캐시 키에도 영향을 미칩니다. 이러한 키들의 변경은 캐시 적중률에 영향을 줄 수 있으므로, 새로운 해시로 업그레이드할 때 주의하고 이를 주시해야 합니다.
6.12 새로운 ActiveSupport::Cache 직렬화 형식
더 빠르고 더 간단한 직렬화 형식이 도입되었습니다.
이를 활성화하려면 config.active_support.cache_format_version = 7.0
을 설정해야 합니다:
# config/application.rb
config.load_defaults 6.1
config.active_support.cache_format_version = 7.0
Or simply로만 되어있어서 번역할 내용이 부족합니다. 전체 문장이나 단락을 제공해주시면 번역해드리겠습니다.
# config/application.rb
config.load_defaults 7.0
주어진 버전의 기본값들을 로드합니다. 이 설정은 새로 생성된 애플리케이션에 기본으로 포함되어 있으며 Rails의 다음 버전에서 일관된 기능을 얻기 위해 이전 버전의 기본값을 가져올 수 있게 해줍니다.
그러나 Rails 6.1 애플리케이션은 이 새로운 serialization 포맷을 읽을 수 없습니다. 따라서 원활한 업그레이드를 위해서는 먼저 config.active_support.cache_format_version = 6.1
로 Rails 7.0 업그레이드를 배포해야 하며, 모든 Rails 프로세스가 업데이트된 후에만 config.active_support.cache_format_version = 7.0
으로 설정할 수 있습니다.
Rails 7.0은 두 가지 포맷을 모두 읽을 수 있으므로 업그레이드 중에 캐시가 무효화되지 않습니다.
6.13 Active Storage 비디오 미리보기 이미지 생성
비디오 미리보기 이미지 생성이 이제 FFmpeg의 장면 변화 감지 기능을 사용하여 더 의미 있는 미리보기 이미지를 생성합니다. 이전에는 비디오의 첫 번째 프레임이 사용되었고, 이는 비디오가 검은색에서 페이드 인되는 경우 문제가 되었습니다. 이 변경사항을 적용하려면 FFmpeg v3.4+ 버전이 필요합니다.
6.14 Active Storage 기본 variant processor가 :vips
로 변경됨
새로운 앱의 경우, 이미지 변환 시 ImageMagick 대신 libvips를 사용합니다. 이를 통해 variant를 생성하는 데 걸리는 시간과 CPU 및 메모리 사용량이 감소되어, 이미지 제공을 위해 Active Storage를 사용하는 앱의 응답 시간이 개선됩니다.
:mini_magick
옵션은 deprecate되지 않으므로 계속 사용해도 무방합니다.
기존 앱을 libvips로 마이그레이션하려면 다음과 같이 설정하세요:
Rails.application.config.active_storage.variant_processor = :vips
그런 다음 기존의 이미지 변환 코드를 image_processing
매크로로 변경하고, ImageMagick의 옵션을 libvips의 옵션으로 교체해야 합니다.
6.14.1 resize를 resize_to_limit로 교체
- variant(resize: "100x")
+ variant(resize_to_limit: [100, nil])
crop할 때 array를 사용하지 않으면, vips로 전환할 때 다음과 같은 에러가 발생합니다: no implicit conversion to float from string
.
6.14.2 crop할 때는 array를 사용하세요
- variant(crop: "1920x1080+0+0")
+ variant(crop: [0, 0, 1920, 1080])
vips로 마이그레이션할 때 이를 수행하지 않으면 `unable to call crop: you supplied 2 arguments, but operation needs 5` 에러가 발생합니다.
#### 크롭 값 제한하기:
Vips는 ImageMagick보다 크로핑에 대해 더 엄격합니다:
1. `x` 및/또는 `y`가 음수인 경우 크롭하지 않습니다. 예: `[-10, -10, 100, 100]`
2. 위치(`x` 또는 `y`)에 크롭 크기(`width`, `height`)를 더한 값이 이미지보다 큰 경우 크롭하지 않습니다. 예: 125x125 이미지에 `[50, 50, 100, 100]` 크롭
vips로 마이그레이션할 때 이를 수행하지 않으면 `extract_area: bad extract area` 에러가 발생합니다.
#### `resize_and_pad`에 사용되는 배경색 조정하기
Vips는 ImageMagick처럼 흰색이 아닌 검은색을 `resize_and_pad`의 기본 배경색으로 사용합니다. `background` 옵션을 사용하여 이를 수정할 수 있습니다:
- variant(resize_and_pad: [300, 300])
+ variant(resize_and_pad: [300, 300, background: [255]])
6.14.3 EXIF 기반 회전 제거
Vips는 variant를 처리할 때 EXIF 값을 사용하여 이미지를 자동으로 회전합니다. 만약 ImageMagick을 사용하여 회전을 적용하기 위해 사용자가 업로드한 사진의 회전 값을 저장하고 있었다면, 이제는 그렇게 하지 말아야 합니다:
- variant(format: :jpg, rotate: rotation_value)
+ variant(format: :jpg)
6.14.4 monochrome를 colorspace로 대체하기
Vips는 단색(monochrome) 이미지를 만들기 위해 다른 옵션을 사용합니다:
- variant(monochrome: true)
+ variant(colourspace: "b-w")
6.14.5 libvips 옵션으로 전환하여 이미지 압축하기
JPEG
- variant(strip: true, quality: 80, interlace: "JPEG", sampling_factor: "4:2:0", colorspace: "sRGB")
+ variant(saver: { strip: true, quality: 80, interlace: true })
경고: 불완전한 지침입니다. 번역할 Rails 가이드 문서의 실제 내용이 제공되지 않았습니다. 번역을 도와드리려면 완전한 영문 원문을 공유해 주시기 바랍니다.
- variant(strip: true, quality: 75)
+ variant(saver: { strip: true, compression: 9 })
죄송하지만 번역할 내용이 보이지 않습니다. Rails 가이드 문서를 공유해주시면 번역을 도와드리도록 하겠습니다.
- variant(strip: true, quality: 75, define: { webp: { lossless: false, alpha_quality: 85, thread_level: 1 } })
+ variant(saver: { strip: true, quality: 75, lossless: false, alpha_q: 85, reduction_effort: 6, smart_subsample: true })
GIF
- variant(layers: "Optimize")
+ variant(saver: { optimize_gif_frames: true, optimize_gif_transparency: true })
6.14.6 프로덕션 배포
Active Storage는 이미지 URL에 수행되어야 할 transformation 목록을 인코딩합니다. 앱이 이러한 URL들을 캐싱하는 경우, 새로운 코드를 프로덕션에 배포한 후 이미지가 깨질 수 있습니다. 이러한 이유로 영향을 받는 캐시 키를 수동으로 무효화해야 합니다.
예를 들어, 뷰에서 다음과 같은 코드가 있다면:
<% @products.each do |product| %>
<% cache product do %>
<%= image_tag product.cover_photo.variant(resize: "200x") %>
<% end %>
<% end %>
제품을 touch하거나 cache key를 변경하여 cache를 무효화할 수 있습니다:
<% @products.each do |product| %>
<% cache ["v2", product] do %>
<%= image_tag product.cover_photo.variant(resize_to_limit: [200, nil]) %>
<% end %>
<% end %>
6.15 스키마 덤프에 Rails 버전이 이제 포함됨
Rails 7.0은 일부 컬럼 타입의 기본값을 변경했습니다. Rails 6.1에서 7.0으로 업그레이드하는 애플리케이션이 새로운 7.0 기본값을 사용하여 현재 스키마를 로드하는 것을 방지하기 위해, Rails는 이제 스키마 덤프에 프레임워크의 버전을 포함합니다.
Rails 7.0에서 처음으로 스키마를 로드하기 전에, 스키마 덤프에 버전이 포함되도록 rails app:update
를 실행하십시오.
스키마 파일은 다음과 같이 보일 것입니다:
# 이 파일은 현재 데이터베이스 상태로부터 자동 생성됩니다. 이 파일을 직접
# 수정하는 대신, Active Record의 migration 기능을 사용하여 점진적으로 데이터베이스를
# 수정하고, schema 정의를 재생성하세요.
#
# 이 파일은 `bin/rails db:schema:load` 실행 시 Rails가 schema를 정의하는데 사용하는 소스입니다.
# 새로운 데이터베이스를 만들 때 `bin/rails db:schema:load`는 migration을 처음부터 실행하는 것보다
# 더 빠르고 잠재적으로 오류가 적습니다. 외부 의존성이나 애플리케이션 코드를 사용하는
# 오래된 migration은 올바르게 적용되지 않을 수 있습니다.
#
# 이 파일을 version control system에 체크인하는 것을 강력히 권장합니다.
ActiveRecord::Schema[6.1].define(version: 2022_01_28_123512) do
# ...
end
Rails 7.0에서 처음으로 schema를 dump할 때, column 정보를 포함하여 해당 파일에 많은 변경사항이 보일 것입니다. 새로운 schema 파일의 내용을 검토하고 repository에 commit하시기 바랍니다.
7 Rails 6.0에서 Rails 6.1로 업그레이드
Rails 6.1에서 이루어진 변경사항에 대한 자세한 내용은 릴리스 노트를 참조하세요.
7.1 Rails.application.config_for
의 반환 값이 더 이상 String 키를 사용한 접근을 지원하지 않습니다.
다음과 같은 설정 파일이 있다고 가정할 때:
# config/example.yml
development:
options:
key: value
Rails.application.config_for(:example).options
이전에는 String 키로 값에 접근할 수 있는 hash를 반환했습니다. 이는 6.0에서 deprecated 되었고 이제는 더 이상 작동하지 않습니다.
String 키로 값에 접근하고 싶다면 config_for
의 반환값에 with_indifferent_access
를 호출할 수 있습니다. 예:
Rails.application.config_for(:example).with_indifferent_access.dig("options", "key")
7.2 respond_to#any
사용시 Response의 Content-Type
Rails 6.0에서 반환되던 것과 다른 Content-Type 헤더가 응답으로 반환될 수 있습니다.
특히 애플리케이션에서 respond_to { |format| format.any }
를 사용하는 경우에 더욱 그렇습니다.
Content-Type은 이제 요청의 format이 아닌 주어진 블록을 기반으로 결정됩니다.
예시:
def my_action
respond_to do |format|
format.any { render(json: { foo: "bar" }) }
end
end
get("my_action.csv")
이전 동작은 JSON 응답이 렌더링되고 있음에도 부정확한 text/csv
Content-Type을 반환했습니다.
현재 동작은 올바르게 application/json
Content-Type을 반환합니다.
만약 애플리케이션이 이전의 잘못된 동작에 의존하고 있다면, 액션이 허용하는 포맷을 명시적으로 지정하는 것을 권장합니다, 예를 들어:
format.any(:xml, :json) { render request.format.to_sym => @people }
- :xml이나 :json 형식 모두에서 해당 format으로 @people을 렌더링합니다
7.3 ActiveSupport::Callbacks#halted_callback_hook
이 이제 두 번째 인자를 받습니다
Active Support는 콜백이 체인을 중단할 때마다 halted_callback_hook
을 오버라이드할 수 있게 해줍니다. 이 메소드는 이제 중단된 콜백의 이름인 두 번째 인자를 받습니다. 이 메소드를 오버라이드하는 클래스가 있다면 두 개의 인자를 받도록 수정해야 합니다. 이는 이전 deprecation 주기 없이 이루어지는 breaking change임을 참고하세요(성능상의 이유로).
예시:
class Book < ApplicationRecord
before_save { throw(:abort) }
before_create { throw(:abort) }
def halted_callback_hook(filter, callback_name) # => 이 메서드는 이제 1개 대신 2개의 인자를 받습니다
Rails.logger.info("Book이 #{callback_name}될 수 없습니다")
end
end
7.4 컨트롤러의 helper
클래스 메서드는 String#constantize
를 사용
개념적으로, Rails 6.1 이전에는
helper "foo/bar"
일치하는 디렉토리 아래에 정의된 helper를 추가합니다. "foo/bar"는 "app/helpers/foo/bar_helper.rb"를 추가합니다.
resulted in은 ~의 결과를 초래했다, ~을 야기했다 라는 의미입니다.
require_dependency "foo/bar_helper"
module_name = "foo/bar_helper".camelize
module_name.constantize
참고: Rails는 Class/Module.const_missing을 사용하여 자동로딩이 작동하기 때문에 autoload_paths에 있는 파일은 require나 load를 직접 호출해서는 안됩니다. 그러나 해당 파일이 autoload_paths의 파일에 직접 의존하는 경우 require_dependency를 사용할 수 있습니다.
그 예로는 ActiveRecord callbacks가 있습니다. ActiveRecord model이 mixin을 require하고, mixin이 초기화될 때 model에서 attr_accessor를 정의하면, 이러한 accessor는 클래스 정의 시간에 존재해야 하므로 require_dependency가 필요합니다.
이제 다음과 같이 작동합니다:
prefix = "foo/bar".camelize
"#{prefix}Helper".constantize
첫 번째 줄은 "foo/bar"를 camel case로 변환하고 prefix
에 저장합니다. 즉, "FooBar"가 됩니다.
두 번째 줄은 문자열 "FooBarHelper"를 만든 후 이것을 상수로 변환합니다. 이는 실제 FooBarHelper
클래스를 찾아 반환하게 됩니다.
이 변경사항은 대부분의 애플리케이션에서 하위 호환성을 유지하므로, 별도의 조치가 필요하지 않습니다.
하지만 기술적으로는, 컨트롤러가 helpers_path
를 autoload paths에 포함되지 않은 $LOAD_PATH
내의 디렉터리를 가리키도록 설정할 수 있었습니다. 이러한 사용 사례는 더 이상 기본적으로 지원되지 않습니다. helper 모듈이 autoloadable하지 않은 경우, helper
를 호출하기 전에 해당 모듈을 로드하는 것은 애플리케이션의 책임입니다.
7.5 HTTP에서 HTTPS로의 리다이렉션이 이제 308 HTTP 상태 코드를 사용합니다
HTTP에서 HTTPS로 GET/HEAD가 아닌 요청을 리다이렉트할 때 ActionDispatch::SSL
에서 사용되는 기본 HTTP 상태 코드가 https://tools.ietf.org/html/rfc7538 에 정의된 대로 308
로 변경되었습니다.
7.6 Active Storage가 이제 Image Processing을 필요로 합니다
Active Storage에서 variant를 처리할 때, 이제 mini_magick
을 직접 사용하는 대신 image_processing gem을 번들링해야 합니다. Image Processing은 기본적으로 내부적으로 mini_magick
을 사용하도록 설정되어 있으므로, 업그레이드하는 가장 쉬운 방법은 mini_magick
gem을 image_processing
gem으로 교체하고 더 이상 필요하지 않은 combine_options
의 명시적 사용을 제거하는 것입니다.
가독성을 위해, 원시 resize
호출을 image_processing
매크로로 변경하는 것이 좋습니다. 예를 들어, 다음과 같은 대신:
video.preview(resize: "100x100") # 강제로 100x100 크기로 이미지 조정
video.preview(resize: "100x100>") # 원본이 더 클 때만 100x100으로 축소
video.preview(resize: "100x100^") # 100x100 영역을 채우도록 이미지 확대
다음과 같이 할 수 있습니다:
video.preview(resize_to_fit: [100, 100]) # 비율을 유지하면서 지정된 크기에 맞추어 축소/확대
video.preview(resize_to_limit: [100, 100]) # 비율을 유지하면서 지정된 크기 이하로만 축소
video.preview(resize_to_fill: [100, 100]) # 비율과 관계없이 지정된 크기로 변환하고 중앙 기준으로 자르기
7.7 새로운 ActiveModel::Error
클래스
오류는 이제 API가 변경된 새로운 ActiveModel::Error
클래스의 인스턴스입니다. 이러한 변경 사항 중 일부는 오류를 다루는 방식에 따라 에러를 발생시킬 수 있으며, 다른 일부는 Rails 7.0을 위해 수정되어야 하는 deprecation 경고를 출력할 것입니다.
이 변경사항과 API 변경에 대한 자세한 내용은 이 PR에서 확인할 수 있습니다.
8 Rails 5.2에서 Rails 6.0으로 업그레이드
Rails 6.0에서 이루어진 변경사항에 대한 자세한 내용은 릴리스 노트를 참조하세요.
8.1 Webpacker 사용하기
Webpacker는 Rails 6의 기본 JavaScript 컴파일러입니다. 하지만 앱을 업그레이드하는 경우에는 기본적으로 활성화되어 있지 않습니다. Webpacker를 사용하고 싶다면, Gemfile에 포함시키고 설치하세요:
gem "webpacker"
$ bin/rails webpacker:install
8.2 Force SSL
Controller의 force_ssl
메서드는 deprecated 되었으며 Rails 6.1에서 제거될 예정입니다. 애플리케이션 전체에 HTTPS 연결을 적용하기 위해서는 config.force_ssl
을 활성화하는 것을 권장합니다. 만약 특정 endpoint에서 리다이렉션을 제외해야 한다면, config.ssl_options
를 사용하여 해당 동작을 설정할 수 있습니다.
8.3 보안 강화를 위해 signed와 encrypted 쿠키에 목적과 만료 메타데이터가 포함됨
보안 향상을 위해 Rails는 암호화되거나 서명된 쿠키 값 안에 목적과 만료 메타데이터를 포함시킵니다.
이를 통해 Rails는 쿠키의 signed/encrypted 값을 복사하여 다른 쿠키의 값으로 사용하려는 공격을 막을 수 있습니다.
이 새로운 포함된 메타데이터로 인해 Rails 6.0 이전 버전과는 호환되지 않습니다.
Rails 5.2 이하 버전에서 쿠키를 읽어야 하거나, 아직 6.0 배포를 검증 중이어서 롤백이 가능하도록 하려면 Rails.application.config.action_dispatch.use_cookies_with_metadata
를 false
로 설정하세요.
8.4 모든 npm 패키지가 @rails
scope로 이동되었습니다
만약 이전에 npm/yarn을 통해 actioncable
, activestorage
, 또는 rails-ujs
패키지를 로드했다면, 이러한 의존성들을 6.0.0
으로 업그레이드하기 전에 이름을 업데이트해야 합니다:
actioncable → @rails/actioncable
activestorage → @rails/activestorage
rails-ujs → @rails/ujs
8.5 Action Cable JavaScript API 변경사항
Action Cable JavaScript 패키지가 CoffeeScript에서 ES2015로 전환되었으며, 이제 npm 배포판에 소스 코드를 게시합니다.
이 릴리스에는 Action Cable JavaScript API의 선택적 부분에 대한 몇 가지 주요 변경사항이 포함되어 있습니다:
WebSocket 어댑터와 logger 어댑터의 설정이
ActionCable
의 속성에서ActionCable.adapters
의 속성으로 이동되었습니다. 이러한 어댑터를 설정하는 경우 다음과 같은 변경이 필요합니다:- ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket
- ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger
ActionCable.startDebugging()
과ActionCable.stopDebugging()
메서드가 제거되고ActionCable.logger.enabled
속성으로 대체되었습니다. 이러한 메서드를 사용하고 있다면 다음과 같은 변경이 필요합니다:- ActionCable.startDebugging() + ActionCable.logger.enabled = true
- ActionCable.stopDebugging() + ActionCable.logger.enabled = false
8.6 ActionDispatch::Response#content_type
이 이제 Content-Type 헤더를 수정 없이 반환합니다
이전에는 ActionDispatch::Response#content_type
의 반환값이 charset 부분을 포함하지 않았습니다.
이 동작이 이전에 생략되었던 charset 부분도 포함하도록 변경되었습니다.
MIME type만 필요한 경우 대신 ActionDispatch::Response#media_type
을 사용하세요.
이전:
resp = ActionDispatch::Response.new(200, "Content-Type" => "text/csv; header=present; charset=utf-16")
resp.content_type #=> "text/csv; header=present"
죄송하지만 실수로 보내주신 번역할 원문이 없어서 번역을 해드릴 수 없네요. Rails 가이드 문서 내용을 공유해 주시면 번역해드리도록 하겠습니다.
resp = ActionDispatch::Response.new(200, "Content-Type" => "text/csv; header=present; charset=utf-16")
resp.content_type #=> "text/csv; header=present; charset=utf-16"
resp.media_type #=> "text/csv"
8.7 새로운 config.hosts
설정
이제 Rails는 보안 목적으로 새로운 config.hosts
설정을 가지고 있습니다. 이 설정은 development 환경에서 기본값으로 localhost
로 되어 있습니다. development 환경에서 다른 도메인을 사용하는 경우 다음과 같이 허용해야 합니다:
# config/environments/development.rb
config.hosts << "dev.myapp.com"
config.hosts << /[a-z0-9-]+\.myapp\.com/ # 선택적으로 정규식도 사용할 수 있습니다
다른 환경의 경우 config.hosts
는 기본적으로 비어있어 Rails가 host를 전혀 검증하지 않습니다. 필요한 경우 production 환경에서 검증하기 위해 선택적으로 추가할 수 있습니다.
8.8 Autoloading
Rails 6의 기본 설정
Rails 6.0에서 새로운 애플리케이션의 autoloader 설정은 다음과 같습니다:
# config/application.rb
config.load_defaults 6.0
이는 zeitwerk
모드를 활성화합니다:
# config/application.rb
config.autoloader = :zeitwerk
config/application.rb
에서 config.load_defaults 6.0
이 주석 처리되어 있거나 파일에서 제거된 경우, 기본값은 다음과 같이 classic 모드가 됩니다:
# config/application.rb
config.autoloader = :classic
레일스 팀은 classic 모드를 deprecated하는 것을 계획하고 있습니다. 새로운 애플리케이션은 zeitwerk
모드를 사용하는 것을 권장합니다.
# config/application.rb
config.load_defaults 6.0
이렇게 하면 해당 버전(이 경우 6.0)의 기본 설정이 활성화됩니다. 새로운 버전의 Rails로 업그레이드할 때는 새로운 기본값을 즉시 적용하지 않고도 애플리케이션을 수정할 수 있습니다.
CRuby에서 zeitwerk
autoloading 모드를 활성화합니다. 이 모드에서는 autoloading, reloading, 그리고 eager loading이 Zeitwerk에 의해 관리됩니다.
이전 Rails 버전의 기본값을 사용하고 있다면, 다음과 같이 zeitwerk를 활성화할 수 있습니다:
# config/application.rb
config.autoloader = :zeitwerk
:zeitwerk를 autoloader로 사용하도록 애플리케이션을 구성합니다.
8.8.1 Public API
일반적으로, 애플리케이션은 Zeitwerk의 API를 직접 사용할 필요가 없습니다. Rails는 기존 규약에 따라 설정을 처리합니다: config.autoload_paths
, config.cache_classes
등.
애플리케이션은 이 인터페이스를 따라야 하지만, 실제 Zeitwerk loader 객체는 다음과 같이 접근할 수 있습니다
Rails.autoloaders.main
예를 들어 Single Table Inheritance (STI) 클래스를 프리로드하거나 커스텀 inflector를 구성해야 하는 경우에 유용할 수 있습니다.
8.8.2 Project Structure
업그레이드되는 애플리케이션이 올바르게 autoload된다면, 프로젝트 구조는 이미 대부분 호환되어 있어야 합니다.
하지만 classic
모드는 누락된 상수 이름에서 파일 이름을 추론(underscore
)하는 반면, zeitwerk
모드는 파일 이름에서 상수 이름을 추론(camelize
)합니다. 이러한 헬퍼들은 특히 약어가 포함된 경우 항상 서로의 역연산이 되지는 않습니다. 예를 들어, "FOO".underscore
는 "foo"
이지만, "foo".camelize
는 "FOO"
가 아닌 "Foo"
입니다.
호환성은 zeitwerk:check
태스크로 확인할 수 있습니다:
$ bin/rails zeitwerk:check
잠시만 기다려주세요, application을 eager loading 중입니다.
모두 정상입니다!
8.8.3 require_dependency
require_dependency
의 모든 알려진 사용 사례들은 제거되었습니다. 프로젝트에서 이를 검색하여 삭제해야 합니다.
애플리케이션이 Single Table Inheritance를 사용하는 경우, Autoloading and Reloading Constants (Zeitwerk Mode) 가이드의 Single Table Inheritance 섹션을 참고하세요.
8.8.4 클래스와 모듈 정의에서의 정규화된 이름
이제 클래스와 모듈 정의에서 상수 경로를 안정적으로 사용할 수 있습니다:
# 이 클래스의 body 내의 Autoloading은 이제 Ruby 의미론과 일치합니다.
class Admin::UsersController < ApplicationController
# ...
end
실행 순서에 따라, classic autoloader가 때때로 Foo::Wadus
를 다음과 같이 autoload할 수 있다는 점을 주의해야 합니다.
class Foo::Bar
Wadus
end
이는 Foo
가 nesting에 없기 때문에 Ruby의 문법과 일치하지 않으며, zeitwerk
모드에서는 전혀 작동하지 않습니다. 이러한 특수한 경우를 발견하면 정규화된 이름 Foo::Wadus
를 사용할 수 있습니다:
class Foo::Bar
Foo::Wadus
end
또는 nesting에 Foo
를 추가하세요:
module Foo
class Bar
Wadus
end
end
8.8.5 Concerns
표준 구조에서 다음과 같이 autoload와 eager load를 할 수 있습니다:
app/models
app/models/concerns
이 디렉터리는 애플리케이션의 model들을 포함합니다. model은 비즈니스 로직을 포함하고 데이터베이스와의 상호작용을 담당합니다. model의 naming 및 작성 가이드라인에 대해서는 Rails Database Naming Conventions을 참조하세요. models/concerns는 여러 model 간에 공유되는 concern들을 포함합니다.
이 경우 app/models/concerns
는 루트 디렉토리로 간주되며(autoload paths에 속하기 때문에) 네임스페이스로는 무시됩니다. 따라서 app/models/concerns/foo.rb
는 Concerns::Foo
가 아닌 Foo
를 정의해야 합니다.
Concerns::
네임스페이스는 classic autoloader에서 구현의 부작용으로 작동했지만, 이는 의도된 동작이 아니었습니다. Concerns::
를 사용하는 애플리케이션은 zeitwerk
모드에서 실행하기 위해 해당 클래스와 모듈의 이름을 변경해야 합니다.
8.8.6 autoload paths에 app
포함하기
일부 프로젝트는 app/api/base.rb
가 API::Base
를 정의하기를 원하며, classic
모드에서 이를 달성하기 위해 app
을 autoload paths에 추가합니다. Rails는 app
의 모든 하위 디렉토리를 자동으로 autoload paths에 추가하기 때문에, 중첩된 루트 디렉토리가 있는 또 다른 상황이 발생하므로 이 설정은 더 이상 작동하지 않습니다. 위에서 concerns
와 함께 설명한 것과 유사한 원칙입니다.
이러한 구조를 유지하고 싶다면, initializer에서 하위 디렉토리를 autoload paths에서 삭제해야 합니다:
ActiveSupport::Dependencies.autoload_paths에서 "#{Rails.root}/app/api"를 삭제합니다
8.8.7 Autoloaded Constants와 명시적 Namespaces
namespace가 파일에서 정의되어 있다면, 여기서 Hotel
처럼:
app/models/hotel.rb # Hotel을 정의합니다.
app/models/hotel/pricing.rb # Hotel::Pricing을 정의합니다.
Hotel
상수는 class
또는 module
키워드를 사용하여 설정해야 합니다. 예를 들면:
class Hotel
end
는 좋습니다.
다음과 같은 대안들이
Hotel = Class.new
또는
Hotel = Struct.new
작동하지 않을 것이며, Hotel::Pricing
과 같은 자식 객체들을 찾을 수 없게 됩니다.
이 제한사항은 명시적인 namespace에만 적용됩니다. namespace를 정의하지 않는 클래스와 모듈은 이러한 방식을 사용하여 정의할 수 있습니다.
8.8.8 하나의 파일, 하나의 상수 (동일한 최상위 레벨에서)
classic
모드에서는 기술적으로 여러 상수를 동일한 최상위 레벨에서 정의하고 모두 리로드할 수 있었습니다. 예를 들어, 다음과 같은 경우:
# app/models/foo.rb
class Foo
end
class Bar
end
Bar
가 autoload되지 않은 상태에서 Foo
를 autoload하면 Bar
도 함께 autoload된 것으로 표시됩니다. 하지만 zeitwerk
모드에서는 그렇지 않으며, Bar
를 bar.rb
라는 자체 파일로 옮겨야 합니다. 하나의 파일에는 하나의 상수만 정의되어야 합니다.
이는 위 예시처럼 같은 최상위 레벨에 있는 상수들에만 적용됩니다. 내부 클래스와 모듈은 괜찮습니다. 예를 들어 다음과 같은 경우를 살펴보겠습니다.
# app/models/foo.rb
class Foo
class InnerClass
end
end
애플리케이션이 Foo
를 리로드하면, Foo::InnerClass
도 함께 리로드됩니다.
8.8.9 Spring과 test
환경
Spring은 변경사항이 있을 때 애플리케이션 코드를 리로드합니다. test
환경에서는 이 기능이 동작하도록 리로딩을 활성화해야 합니다:
# config/environments/test.rb
config.cache_classes = false
이는 테스트 환경에서 클래스를 다시 로드할 수 있도록 설정하는 것입니다. 이렇게 하면 테스트 실행 간에 코드 변경 사항이 반영됩니다.
그렇지 않으면 다음과 같은 에러가 발생할 것입니다:
reloading이 비활성화되어 있습니다. config.cache_classes가 true이기 때문입니다
8.8.10 Bootsnap
Bootsnap은 최소 1.4.2 버전이어야 합니다.
추가로, Ruby 2.5를 실행할 때는 인터프리터의 버그로 인해 Bootsnap이 iseq 캐시를 비활성화해야 합니다. 이 경우 최소 Bootsnap 1.4.4 버전에 의존하도록 해주세요.
8.8.11 config.add_autoload_paths_to_load_path
새로운 설정 포인트인 config.add_autoload_paths_to_load_path
는 하위 호환성을 위해 기본값이 true
이지만, autoload 경로를 $LOAD_PATH
에 추가하지 않도록 선택할 수 있습니다.
대부분의 애플리케이션에서 이는 합리적입니다. 예를 들어 app/models
에 있는 파일을 절대 require할 필요가 없고, Zeitwerk는 내부적으로 절대 파일 경로만 사용하기 때문입니다.
이 옵션을 해제하면 $LOAD_PATH
조회를 최적화할 수 있고(확인할 디렉토리가 줄어듦), Bootsnap이 이 디렉토리들의 인덱스를 구축할 필요가 없어져서 작업량과 메모리 소비를 줄일 수 있습니다.
8.8.12 스레드 안정성
classic 모드에서 상수 autoloading은 스레드 안전하지 않습니다. 하지만 Rails는 개발 환경에서 일반적인 것처럼 autoloading이 활성화된 상태에서 웹 요청을 스레드 안전하게 만들기 위한 잠금 장치를 가지고 있습니다.
상수 autoloading은 zeitwerk
모드에서는 스레드 안전합니다. 예를 들어 이제 runner
명령으로 실행되는 멀티스레드 스크립트에서 autoload를 사용할 수 있습니다.
8.8.13 config.autoload_paths의 글로브
다음과 같은 설정을 주의하세요
config.autoload_paths += Dir["#{config.root}/lib/**/"]
lib 디렉터리와 하위의 모든 디렉터리를 autoload path에 추가합니다.
config.autoload_paths
의 모든 요소는 최상위 namespace(Object
)를 나타내야 하며, 결과적으로 중첩될 수 없습니다(위에서 설명한 concerns
디렉토리는 예외).
이를 해결하려면 와일드카드를 제거하면 됩니다:
config.autoload_paths << "#{config.root}/lib"
(이 라인은 /lib
디렉토리를 autoload path에 추가합니다)
8.8.14 Eager loading과 autoloading이 일관적입니다
classic
모드에서는 app/models/foo.rb
가 Bar
를 정의하는 경우 해당 파일을 autoload할 수 없지만, eager loading은 파일들을 재귀적으로 무조건 로드하기 때문에 작동합니다. 만약 처음에 eager loading으로 테스트하면, 나중에 autoloading 시에는 실패할 수 있어서 이것이 오류의 원인이 될 수 있습니다.
zeitwerk
모드에서는 두 로딩 모드가 일관적이어서, 같은 파일에서 실패하고 오류가 발생합니다.
8.8.15 Rails 6에서 Classic Autoloader를 사용하는 방법
애플리케이션은 Rails 6 기본값을 로드하면서도 다음과 같이 config.autoloader
를 설정하여 classic autoloader를 사용할 수 있습니다:
# config/application.rb
config.load_defaults 6.0
config.autoloader = :classic
이 설정은 classic autoloader를 계속 사용하면서 Rails 6.0의 기본 설정을 로드합니다.
Rails 6 애플리케이션에서 Classic Autoloader를 사용할 때는 스레드 안전성 문제로 인해 development 환경의 web server와 background processor의 concurrency level을 1로 설정하는 것이 권장됩니다.
8.9 Active Storage 할당 동작 변경
Rails 5.2의 기본 구성에서는, has_many_attached
로 선언된 첨부파일 컬렉션에 할당하면 새로운 파일들이 추가됩니다:
class User < ApplicationRecord
has_many_attached :highlights
end
user.highlights.attach(filename: "funky.jpg")
user.highlights.count # => 1
blob = ActiveStorage::Blob.create_after_upload!(filename: "town.jpg")
user.update!(highlights: [ blob ])
user.highlights.count # => 2
user.highlights.first.filename # => "funky.jpg"
user.highlights.second.filename # => "town.jpg"
Rails 6.0의 기본 설정에서는, attachment 컬렉션에 할당할 때 파일을 추가하는 대신 기존 파일을 대체합니다. 이는 컬렉션 association에 할당할 때의 Active Record 동작과 일치합니다:
user.highlights.attach(filename: "funky.jpg")
user.highlights.count # => 1
blob = ActiveStorage::Blob.create_after_upload!(filename: "town.jpg")
user.update!(highlights: [ blob ])
user.highlights.count # => 1
user.highlights.first.filename # => "town.jpg"
#attach
는 기존의 attachment들을 제거하지 않고 새로운 attachment를 추가하는데 사용할 수 있습니다:
blob = ActiveStorage::Blob.create_after_upload!(filename: "town.jpg")
user.highlights.attach(blob)
user.highlights.count # => 2
user.highlights.first.filename # => "funky.jpg"
user.highlights.second.filename # => "town.jpg"
기존 애플리케이션은 config.active_storage.replace_on_assign_to_many
를 true
로 설정하여 이 새로운 동작을 선택할 수 있습니다. 이전 동작은 Rails 7.0에서 deprecated 될 예정이며 Rails 7.1에서 제거될 예정입니다.
8.10 커스텀 예외 처리 애플리케이션
유효하지 않은 Accept
또는 Content-Type
요청 헤더는 이제 예외를 발생시킵니다.
기본 config.exceptions_app
은 해당 오류를 특별히 처리하고 이를 보완합니다.
커스텀 예외 애플리케이션도 해당 오류를 처리해야 합니다. 그렇지 않으면 이러한 요청들이 Rails로 하여금 대체 예외 애플리케이션을 사용하게 하여 500 Internal Server Error
를 반환하게 됩니다.
9 Rails 5.1에서 Rails 5.2로 업그레이드하기
Rails 5.2에서 이루어진 변경사항에 대한 자세한 내용은 릴리스 노트를 참조하세요.
9.1 Bootsnap
Rails 5.2는 새로 생성된 앱의 Gemfile에 bootsnap gem을 추가합니다.
app:update
명령어는 boot.rb
에서 이를 설정합니다. 이를 사용하려면 Gemfile에 추가하세요:
# 캐싱을 통해 부팅 시간을 단축시킵니다; config/boot.rb에서 필요함
gem "bootsnap", require: false
bootsnap을 사용하지 않으려면 boot.rb
를 변경하세요.
9.2 서명되거나 암호화된 쿠키의 만료 정보가 이제 쿠키 값에 포함됨
보안 향상을 위해 Rails는 이제 만료 정보를 암호화되거나 서명된 쿠키 값에도 포함시킵니다.
이 새로운 포함된 정보로 인해 해당 쿠키들은 Rails 5.2 이전 버전과 호환되지 않습니다.
만약 쿠키가 5.1 이하 버전에서도 읽혀야 하거나, 아직 5.2 배포를 검증 중이어서 롤백이 가능하도록 하고 싶다면 Rails.application.config.action_dispatch.use_authenticated_cookie_encryption
을 false
로 설정하세요.
10 Rails 5.0에서 Rails 5.1로 업그레이드
Rails 5.1의 변경사항에 대한 자세한 내용은 릴리스 노트를 참조하세요.
10.1 최상위 HashWithIndifferentAccess
는 소프트 deprecated 되었습니다
애플리케이션에서 최상위 HashWithIndifferentAccess
클래스를 사용하고 있다면, ActiveSupport::HashWithIndifferentAccess
를 대신 사용하도록 코드를 점진적으로 변경해야 합니다.
이것은 소프트 deprecated일 뿐이므로, 현재 코드가 깨지거나 deprecation 경고가 표시되지는 않지만, 이 상수는 향후 제거될 예정입니다.
또한, 이러한 객체들의 dump를 포함하는 오래된 YAML 문서가 있다면, 올바른 상수를 참조하도록 하고 향후 로드할 때 문제가 발생하지 않도록 하기 위해 다시 로드하고 dump할 필요가 있을 수 있습니다.
10.2 application.secrets
가 이제 모든 키를 symbol로 로드합니다
애플리케이션이 config/secrets.yml
에 중첩된 설정을 저장하는 경우, 이제 모든 키가 symbol로 로드되므로 string을 사용하는 접근 방식을 변경해야 합니다.
변경 전:
Rails.application.secrets[:smtp_settings]["address"]
번역 할 내용이 제공되지 않았습니다. Rails 가이드 문서의 내용을 주시면 번역해드리도록 하겠습니다.
Rails.application.secrets[:smtp_settings][:address]
10.3 render
에서 더 이상 사용되지 않는 :text
와 :nothing
지원 제거
컨트롤러에서 render :text
를 사용하고 있다면 더 이상 작동하지 않습니다. MIME type이 text/plain
인 텍스트를 렌더링하는 새로운 방법은 render :plain
을 사용하는 것입니다.
마찬가지로, render :nothing
도 제거되었으며 헤더만 포함된 응답을 보내려면 head
메서드를 사용해야 합니다. 예를 들어, head :ok
는 본문 없이 200 응답을 보냅니다.
10.4 redirect_to :back
지원 중단
Rails 5.0에서 redirect_to :back
은 deprecated 되었습니다. Rails 5.1에서는 완전히 제거되었습니다.
대안으로 redirect_back
을 사용하세요. redirect_back
은 HTTP_REFERER
가 없는 경우 사용될 fallback_location
옵션도 함께 사용해야 한다는 점에 주의하세요.
redirect_back(fallback_location: root_path)
request가 있었던 이전 페이지로 돌아가고, 만약 HTTP_REFERER이 없다면 fallback_location
으로 redirect 합니다.
11 Upgrading from Rails 4.2 to Rails 5.0
Rails 5.0에서 변경된 사항에 대한 자세한 내용은 release notes를 참조하세요.
11.1 Ruby 2.2.2+ 필수
Ruby on Rails 5.0부터는 Ruby 2.2.2+ 버전만 지원됩니다. 계속 진행하기 전에 Ruby 2.2.2 이상의 버전을 사용하고 있는지 확인하세요.
11.2 Active Record Models는 이제 기본적으로 ApplicationRecord를 상속합니다
Rails 4.2에서는 Active Record model이 ActiveRecord::Base
를 상속했습니다. Rails 5.0에서는 모든 model이 ApplicationRecord
를 상속합니다.
ApplicationRecord
는 모든 앱 model을 위한 새로운 superclass입니다. 이는 app controller가 ActionController::Base
대신 ApplicationController
를 상속하는 것과 유사합니다. 이를 통해 앱은 앱 전체의 model 동작을 설정할 수 있는 단일 지점을 갖게 됩니다.
Rails 4.2에서 Rails 5.0으로 업그레이드할 때는 app/models/
디렉토리에 application_record.rb
파일을 생성하고 다음 내용을 추가해야 합니다:
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
end
이것은 Rails 5.0에서 도입된 새로운 클래스입니다. 모든 model이 상속하는 추상 클래스입니다. 이것은 직접적으로 생성되지 않으며 대신 템플릿 역할을 하는 클래스입니다. ActiveRecord::Base
와는 달리, ApplicationRecord
는 자유롭게 코드를 수정할 수 있습니다. 예를 들어 전체 애플리케이션에 대해 특정 scope나 메서드를 정의할 수 있습니다.
그리고 모든 model들이 이것을 상속받는지 확인하세요.
11.3 throw(:abort)
를 통한 Callback Chain 중단하기
Rails 4.2에서는 Active Record와 Active Model의 'before' callback이 false
를 반환하면 전체 callback chain이 중단됩니다. 다시 말해서, 이후의 'before' callback들은 실행되지 않으며, callback으로 감싸진 액션도 실행되지 않습니다.
Rails 5.0에서는 Active Record나 Active Model callback에서 false
를 반환하더라도 callback chain을 중단하는 부수 효과가 없습니다. 대신, callback chain을 명시적으로 중단하려면 throw(:abort)
를 호출해야 합니다.
Rails 4.2에서 Rails 5.0으로 업그레이드할 때, 이러한 종류의 callback에서 false
를 반환하면 여전히 callback chain이 중단되지만, 이 예정된 변경사항에 대한 deprecation 경고를 받게 됩니다.
준비가 되었다면, config/application.rb
에 다음 설정을 추가하여 새로운 동작을 적용하고 deprecation 경고를 제거할 수 있습니다:
ActiveSupport.halt_callback_chains_on_return_false = false
Active Support 콜백의 경우 어떤 값이 반환되더라도 체인을 중단하지 않기 때문에 이 옵션은 영향을 미치지 않는다는 점에 유의하세요.
자세한 내용은 #17227을 참조하세요.
11.4 ActiveJob는 이제 기본적으로 ApplicationJob을 상속받습니다
Rails 4.2에서는 Active Job가 ActiveJob::Base
를 상속받았습니다. Rails 5.0에서는 이 동작이 ApplicationJob
을 상속받도록 변경되었습니다.
Rails 4.2에서 Rails 5.0으로 업그레이드할 때, app/jobs/
디렉토리에 application_job.rb
파일을 생성하고 다음 내용을 추가해야 합니다:
class ApplicationJob < ActiveJob::Base
end
참고: 이 파일은 새로운 Rails 애플리케이션에서 생성되는 기본 파일입니다. 모든 Job은 이 클래스를 상속받아야 합니다.
그런 다음 모든 job 클래스가 이를 상속하는지 확인하세요.
자세한 내용은 #19034를 참조하세요.
11.5 Rails Controller Testing
11.5.1 rails-controller-testing
로의 일부 헬퍼 메소드 추출
assigns
와 assert_template
가 rails-controller-testing
gem으로 추출되었습니다. controller 테스트에서 이 메소드들을 계속 사용하려면 Gemfile
에 gem "rails-controller-testing"
를 추가하세요.
RSpec을 테스트에 사용하고 있다면, gem의 문서에서 필요한 추가 설정을 확인하시기 바랍니다.
11.5.2 파일 업로드시 새로운 동작
테스트에서 파일 업로드를 위해 ActionDispatch::Http::UploadedFile
을 사용하고 있다면, 대신 비슷한 Rack::Test::UploadedFile
클래스를 사용하도록 변경해야 합니다.
자세한 내용은 #26404를 참조하세요.
11.6 Production 환경에서 부팅 후 Autoloading이 비활성화됨
Production 환경에서는 기본적으로 부팅 후 autoloading이 비활성화됩니다.
애플리케이션의 eager loading은 부팅 프로세스의 일부이므로, 최상위 상수들은 문제없이 계속 autoload되며 이들의 파일을 require할 필요가 없습니다.
일반 메서드 본문과 같이 런타임에만 실행되는 더 깊은 위치에 있는 상수들도 문제없습니다. 이는 부팅하는 동안 해당 상수를 정의하는 파일이 이미 eager load되었기 때문입니다.
대부분의 애플리케이션에서 이 변경사항은 아무런 조치가 필요하지 않습니다. 하지만 매우 드물게 production 환경에서 실행 중에 autoloading이 필요한 경우, Rails.application.config.enable_dependency_loading
을 true로 설정하세요.
11.7 XML Serialization
ActiveModel::Serializers::Xml
은 Rails에서 activemodel-serializers-xml
gem으로 분리되었습니다. 어플리케이션에서 XML serialization을 계속 사용하려면 Gemfile
에 gem "activemodel-serializers-xml"
을 추가하세요.
11.8 Legacy mysql
데이터베이스 어댑터 지원 제거
Rails 5에서는 legacy mysql
데이터베이스 어댑터에 대한 지원이 제거되었습니다. 대부분의 사용자는 대신 mysql2
를 사용할 수 있습니다. 이는 유지보수할 담당자를 찾으면 별도의 gem으로 전환될 예정입니다.
11.9 Debugger 지원 제거
Rails 5에서 필요로 하는 Ruby 2.2는 debugger
를 지원하지 않습니다. 대신 byebug
를 사용하세요.
11.10 bin/rails
를 사용하여 task와 test 실행하기
Rails 5에서는 rake 대신 bin/rails
를 통해 task와 test를 실행할 수 있는 기능이 추가되었습니다. 일반적으로 이러한 변경사항들은 rake와 병행되지만, 일부는 완전히 이전되었습니다.
새로운 test runner를 사용하려면 간단히 bin/rails test
를 입력하세요.
rake dev:cache
는 이제 bin/rails dev:cache
가 되었습니다.
사용 가능한 명령어 목록을 보려면 애플리케이션의 루트 디렉토리에서 bin/rails
를 실행하세요.
11.11 ActionController::Parameters
는 더 이상 HashWithIndifferentAccess
를 상속하지 않음
애플리케이션에서 params
를 호출하면 이제 hash 대신 객체를 반환합니다. 매개변수가 이미 permitted(허용)된 상태라면 어떠한 변경도 할 필요가 없습니다. 만약 permitted?
상태와 관계없이 hash를 읽을 수 있어야 하는 map
과 같은 메서드를 사용하고 있다면, 먼저 permit(허용)하고 hash로 변환하도록 애플리케이션을 업그레이드해야 합니다.
params.permit([:proceed_to, :return_to]).to_h
11.12 protect_from_forgery
는 이제 기본값이 prepend: false
입니다
protect_from_forgery
는 이제 prepend: false
가 기본값이며, 이는 애플리케이션에서 호출하는 시점에 callback chain에 삽입된다는 것을 의미합니다. 만약 protect_from_forgery
가 항상 먼저 실행되기를 원한다면, 애플리케이션에서 protect_from_forgery prepend: true
를 사용하도록 변경해야 합니다.
11.13 Default Template Handler가 이제 RAW입니다
확장자에 template handler가 없는 파일들은 raw handler를 사용해 렌더링됩니다. 이전에는 Rails가 ERB template handler를 사용해 파일을 렌더링했습니다.
파일을 raw handler로 처리하고 싶지 않다면, 적절한 template handler로 파싱될 수 있는 확장자를 파일에 추가해야 합니다.
11.14 Template Dependencies에 대한 와일드카드 매칭 추가
이제 template dependencies에 대해 와일드카드 매칭을 사용할 수 있습니다. 예를 들어, 템플릿을 다음과 같이 정의했다면:
<% # Template 의존성: recordings/threads/events/subscribers_changed %>
<% # Template 의존성: recordings/threads/events/completed %>
<% # Template 의존성: recordings/threads/events/uncompleted %>
이제 와일드카드를 사용하여 dependency를 한 번만 호출할 수 있습니다.
<% # Template Dependency: recordings/threads/events/* %>
11.15 ActionView::Helpers::RecordTagHelper
가 외부 gem(record_tag_helper)으로 이동됨
content_tag_for
와 div_for
는 content_tag
만 사용하도록 제거되었습니다. 이전 메소드들을 계속 사용하려면 Gemfile
에 record_tag_helper
gem을 추가하세요:
gem "record_tag_helper", "~> 1.0"
자세한 내용은 #18411을 참조하세요.
11.16 protected_attributes
Gem 지원 제거
Rails 5에서는 더 이상 protected_attributes
gem을 지원하지 않습니다.
11.17 activerecord-deprecated_finders
gem에 대한 지원 종료
activerecord-deprecated_finders
gem은 더 이상 Rails 5에서 지원되지 않습니다.
11.18 ActiveSupport::TestCase
의 기본 테스트 순서가 이제 임의 순서로 변경됨
애플리케이션에서 테스트가 실행될 때, 기본 순서가 :sorted
에서 :random
으로 변경되었습니다. 다음 config 옵션을 사용하여 :sorted
로 되돌릴 수 있습니다.
# config/environments/test.rb
Rails.application.configure do
config.active_support.test_order = :sorted
end
11.19 ActionController::Live
가 Concern
이 되었습니다
ActionController::Live
를 컨트롤러에 포함된 다른 모듈에 포함시킬 경우, 해당 모듈에 ActiveSupport::Concern
도 함께 extend해야 합니다. 또는 StreamingSupport
가 포함된 후에 컨트롤러에 직접 ActionController::Live
를 포함시키기 위해 self.included
hook을 사용할 수 있습니다.
이는 애플리케이션이 자체 streaming 모듈을 사용하고 있었다면, 다음과 같은 코드가 production 환경에서 동작하지 않을 수 있다는 것을 의미합니다:
# 이것은 Warden/Devise를 사용한 인증을 수행하는 streamed 컨트롤러를 위한 해결 방법입니다.
# https://github.com/plataformatec/devise/issues/2332 참조
# 해당 이슈에서 제안된 대로 라우터에서 인증하는 것이 또 다른 해결책입니다
class StreamingSupport
include ActionController::Live # Rails 5의 production 환경에서는 작동하지 않습니다
# extend ActiveSupport::Concern # 이 줄의 주석을 해제하지 않는 한
def process(name)
super(name)
rescue ArgumentError => e
if e.message == "uncaught throw :warden"
throw :warden
else
raise e
end
end
end
11.20 새로운 프레임워크 기본값
11.20.1 Active Record belongs_to
의 기본 필수 옵션
이제 belongs_to
는 기본적으로 association이 없는 경우 validation 오류를 발생시킵니다.
이는 association 별로 optional: true
를 사용하여 비활성화할 수 있습니다.
이 기본값은 새로운 애플리케이션에서 자동으로 설정됩니다. 기존 애플리케이션에서 이 기능을 추가하려면 initializer에서 활성화해야 합니다:
config.active_record.belongs_to_required_by_default = true
belongs_to
관계에서 belongs_to
연관이 유효하기 위해서는 연관된 레코드가 반드시 존재해야 합니다. belongs_to
관계를 선언할 때 optional: true
를 지정하여 이 기본 동작을 비활성화할 수 있습니다.
설정은 기본적으로 모든 모델에 대해 전역적으로 적용되지만, 모델별로 재정의할 수 있습니다. 이를 통해 모든 모델의 association이 기본적으로 필수가 되도록 마이그레이션하는 데 도움이 될 것입니다.
class Book < ApplicationRecord
# model이 아직 기본적으로 association을 필수로 요구할 준비가 되지 않음
self.belongs_to_required_by_default = false
belongs_to(:author)
end
class Car < ApplicationRecord
# model이 기본적으로 association을 필수로 요구할 준비가 됨
self.belongs_to_required_by_default = true
belongs_to(:pilot)
end
11.20.2 Form별 CSRF 토큰
Rails 5는 JavaScript로 생성된 form에서의 코드 주입 공격을 완화하기 위해 form별 CSRF 토큰을 지원합니다. 이 옵션을 활성화하면 애플리케이션의 form들은 각각 해당 form의 action과 method에 특화된 고유한 CSRF 토큰을 가지게 됩니다.
이 옵션은 각 폼마다 특정한 CSRF 토큰을 생성하도록 합니다. 이는 form 앨리먼트의 action
속성과 method
를 CSRF 토큰에 바인딩합니다. 이렇게 하면 제출된 폼이 원래 의도된 목적과 다른 엔드포인트로 재전송되는 것을 방지합니다.
11.20.3 Origin 체크를 통한 위조 방지
이제 CSRF 방어의 추가 수단으로 HTTP Origin
헤더를 사이트의 origin과 대조하여 확인하도록 애플리케이션을 설정할 수 있습니다. 설정 파일에서 다음을 true로 설정하세요:
Rails는 Cross-Origin Request Forgery 보호 기능을 사용할 때, 동일 출처(same origin)에서만 요청을 허용합니다. HTTP Origin
헤더가 있는 경우, Rails는 이 헤더가 요청의 호스트 헤더와 일치하는지 검증합니다. 이 기능은 config.action_controller.forgery_protection_origin_check = true
로 활성화됩니다.
11.20.4 Action Mailer Queue Name 구성 허용
기본 mailer queue 이름은 mailers
입니다. 이 구성 옵션을 사용하면 queue 이름을 전역적으로 변경할 수 있습니다. 구성에서 다음을 설정하세요:
config.action_mailer.deliver_later_queue_name = :new_queue_name
Action Mailer에서 deliver_later를 사용할 때 어떤 queue를 사용할지 지정합니다.
11.20.5 Action Mailer 뷰에서 Fragment Caching 지원
설정에서 config.action_mailer.perform_caching
을 설정하여 Action Mailer 뷰가 caching을 지원할지 여부를 결정할 수 있습니다.
config.action_mailer.perform_caching = true
Action Mailer가 fragment caching을 수행할지 여부를 지정합니다.
11.20.6 db:structure:dump
의 출력 설정
schema_search_path
또는 다른 PostgreSQL 확장 기능을 사용하는 경우, 스키마가 덤프되는 방식을 제어할 수 있습니다. 모든 덤프를 생성하려면 :all
로 설정하고, schema search path에서 생성하려면 :schema_search_path
로 설정하세요.
config.active_record.dump_schemas = :all
모든 데이터베이스의 스키마를 덤프합니다. 기본값은 :schema_search_path
입니다. main 데이터베이스가 아닌 다른 스키마(schema)나 데이터베이스가 있는 경우 :all
로 설정해주세요.
11.20.7 서브도메인과 함께 HSTS를 활성화하기 위한 SSL 옵션 구성
서브도메인을 사용할 때 HSTS를 활성화하려면 config에 다음과 같이 설정하세요:
config.ssl_options = { hsts: { subdomains: true } }
11.20.8 수신자의 타임존 보존
Ruby 2.4를 사용할 때, to_time
을 호출할 때 수신자의 타임존을 보존할 수 있습니다.
ActiveSupport.to_time_preserves_timezone = false
11.21 JSON/JSONB 직렬화 변경사항
Rails 5.0에서는 JSON/JSONB 속성의 직렬화 및 역직렬화 방식이 변경되었습니다. 이제 컬럼을 String
으로 설정하면 Active Record는 더 이상 그 문자열을 Hash
로 변환하지 않고 문자열 그대로 반환합니다. 이는 모델과 상호작용하는 코드에만 국한되지 않고 db/schema.rb
의 :default
컬럼 설정에도 영향을 미칩니다. 컬럼을 String
으로 설정하는 대신, 자동으로 JSON 문자열로 변환되는 Hash
를 전달하는 것이 권장됩니다.
12 Rails 4.1에서 Rails 4.2로 업그레이드
12.1 Web Console
먼저 Gemfile
의 :development
그룹에 gem "web-console", "~> 2.0"
를 추가하고 bundle install
을 실행하세요(Rails를 업그레이드했을 때 포함되지 않았을 것입니다). 설치가 완료되면, console helper(즉, <%= console %>
)를 활성화하고 싶은 view에 간단히 추가하면 됩니다. 개발 환경에서 보는 모든 에러 페이지에도 console이 제공됩니다.
12.2 Responders
respond_with
와 클래스 레벨의 respond_to
메소드들은 responders
gem으로 분리되었습니다. 이를 사용하기 위해서는 단순히 Gemfile
에 gem "responders", "~> 2.0"
를 추가하면 됩니다. responders
gem을 의존성에 포함시키지 않으면 respond_with
와 respond_to
(다시 말하지만, 클래스 레벨에서)에 대한 호출이 더 이상 작동하지 않을 것입니다:
# app/controllers/users_controller.rb
class UsersController < ApplicationController
respond_to :html, :json
def show
@user = User.find(params[:id])
respond_with @user
end
end
인스턴스 레벨의 respond_to
는 영향을 받지 않으며 추가 gem이 필요하지 않습니다:
# app/controllers/users_controller.rb
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
respond_to do |format|
format.html
format.json { render json: @user }
end
end
end
자세한 내용은 #16526을 참조하세요.
12.3 트랜잭션 콜백에서의 에러 처리
현재 Active Record는 after_rollback
또는 after_commit
콜백 내에서 발생하는 에러를 억제하고 로그에만 출력합니다. 다음 버전에서는 이러한 에러들이 더 이상 억제되지 않을 것입니다. 대신, 다른 Active Record 콜백들처럼 에러가 정상적으로 전파될 것입니다.
after_rollback
또는 after_commit
콜백을 정의할 때, 이 예정된 변경사항에 대한 deprecation 경고를 받게 될 것입니다. 준비가 되었다면, config/application.rb
에 다음 설정을 추가하여 새로운 동작을 적용하고 deprecation 경고를 제거할 수 있습니다:
config.active_record.raise_in_transactional_callbacks = true
#14488과 #16537에서 자세한 내용을 확인하세요.
12.4 Test case의 순서
Rails 5.0에서는 test case가 기본적으로 무작위 순서로 실행됩니다. 이러한 변화에 대비하여 Rails 4.2에서는 test 순서를 명시적으로 지정할 수 있는 새로운 configuration option인 active_support.test_order
를 도입했습니다. 이를 통해 :sorted
로 설정하여 현재 동작을 고정하거나, :random
으로 설정하여 미래의 동작을 선택할 수 있습니다.
이 option에 대한 값을 지정하지 않으면 deprecation warning이 발생합니다. 이를 방지하려면 test 환경에 다음 줄을 추가하세요:
# config/environments/test.rb
Rails.application.configure do
config.active_support.test_order = :sorted # 또는 선호하시는 대로 `:random`을 사용하세요
end
12.5 Serialized attributes
커스텀 coder를 사용할 때(예: serialize :metadata, JSON
), serialized attribute에 nil
을 할당하면 coder를 통과시키는 대신(예: JSON
coder를 사용할 때의 "null"
) 데이터베이스에 NULL
로 저장됩니다.
12.6 Production log level
Rails 5에서는 production 환경의 기본 log level이 (:info
에서) :debug
로 변경됩니다. 현재의 기본값을 유지하려면 production.rb
에 다음 라인을 추가하세요:
# 현재 기본값과 일치하도록 `:info`로 설정하거나,
# 향후 기본값을 적용하려면 `:debug`로 설정하세요.
config.log_level = :info
12.7 Rails 템플릿의 after_bundle
만약 모든 파일을 버전 컨트롤에 추가하는 Rails 템플릿이 있다면, Bundler가 실행되기 전에 실행되므로 생성된 binstub들을 추가하는데 실패합니다.
# template.rb
generate(:scaffold, "person name:string")
route "root to: 'people#index'"
rake("db:migrate")
git :init
git add: "."
git commit: %Q{ -m '최초 커밋' }
git
호출을 after_bundle
블록으로 감쌀 수 있습니다. 이는 binstub들이 생성된 후에 실행됩니다.
# template.rb
generate(:scaffold, "person name:string")
route "root to: 'people#index'"
rake("db:migrate")
after_bundle do
git :init
git add: "."
git commit: %Q{ -m '최초 커밋' }
end
12.8 Rails HTML Sanitizer
애플리케이션에서 HTML 조각을 sanitize하는 새로운 방법이 있습니다. 기존의 html-scanner 방식은 이제 공식적으로 Rails HTML Sanitizer
를 선호하는 방향으로 deprecated 되었습니다.
이는 sanitize
, sanitize_css
, strip_tags
, strip_links
메서드들이 새로운 구현으로 지원된다는 것을 의미합니다.
이 새로운 sanitizer는 내부적으로 Loofah를 사용합니다. Loofah는 Nokogiri를 사용하는데, 이는 C와 Java로 작성된 XML parser들을 래핑하고 있어서 어떤 Ruby 버전을 실행하더라도 sanitization이 더 빠를 것입니다.
새 버전은 sanitize
를 업데이트하여 강력한 scrubbing을 위해 Loofah::Scrubber
를 사용할 수 있게 되었습니다.
여기에서 scrubber의 예시를 확인하세요.
두 개의 새로운 scrubber도 추가되었습니다: PermitScrubber
와 TargetScrubber
입니다.
더 자세한 정보는 gem의 readme를 읽어보세요.
PermitScrubber
와 TargetScrubber
의 문서는 요소를 언제 어떻게 제거할지에 대해 완전한 제어를 할 수 있는 방법을 설명합니다.
만약 애플리케이션에서 이전 sanitizer 구현을 사용해야 한다면, Gemfile
에 rails-deprecated_sanitizer
를 포함하세요:
gem "rails-deprecated_sanitizer"
12.9 Rails DOM Testing
TagAssertions
모듈(assert_tag
와 같은 메서드를 포함)은 SelectorAssertions
모듈의 assert_select
메서드를 위해 deprecated 되었으며, 이는 rails-dom-testing gem으로 추출되었습니다.
12.10 Masked Authenticity Tokens
SSL 공격을 완화하기 위해, form_authenticity_token
은 이제 각 요청마다 다르게 마스킹됩니다. 따라서 토큰은 마스킹을 해제한 다음 복호화하여 검증됩니다. 결과적으로, 정적 세션 CSRF 토큰에 의존하는 non-rails form의 요청을 검증하는 모든 전략들은 이를 고려해야 합니다.
12.11 Action Mailer
이전에는 mailer 클래스에서 mailer 메서드를 호출하면 해당 인스턴스 메서드가 직접 실행되었습니다. Active Job과 #deliver_later
가 도입되면서 이는 더 이상 사실이 아닙니다. Rails 4.2에서는 deliver_now
또는 deliver_later
가 호출될 때까지 인스턴스 메서드의 실행이 지연됩니다. 예를 들어:
class Notifier < ActionMailer::Base
def notify(user)
puts "호출됨"
mail(to: user.email)
end
end
mail = Notifier.notify(user) # 이 시점에서는 아직 Notifier#notify가 호출되지 않음
mail = mail.deliver_now # "Called" 출력
대부분의 애플리케이션에서는 눈에 띄는 차이가 발생하지 않을 것입니다. 하지만 일부 non-mailer 메서드를 동기적으로 실행해야 하고, 이전에 동기적 프록시 동작에 의존하고 있었다면, mailer 클래스에서 직접 클래스 메서드로 정의해야 합니다:
class Notifier < ActionMailer::Base
def self.broadcast_notifications(users, ...)
users.each { |user| Notifier.notify(user, ...) }
end
end
위의 코드는 모든 users에 대해 notify를 호출합니다.
12.12 Foreign Key 지원
Migration DSL이 foreign key 정의를 지원하도록 확장되었습니다. Foreigner gem을 사용하고 계셨다면 이를 제거하는 것을 고려해보세요. Rails의 foreign key 지원은 Foreigner의 부분집합이라는 점을 주의하세요. 이는 모든 Foreigner 정의를 Rails migration DSL로 완벽하게 대체할 수는 없다는 것을 의미합니다.
마이그레이션 절차는 다음과 같습니다:
Gemfile
에서gem "foreigner"
를 제거합니다.bundle install
을 실행합니다.bin/rake db:schema:dump
를 실행합니다.db/schema.rb
가 필요한 옵션과 함께 모든 foreign key 정의를 포함하고 있는지 확인합니다.
13 Upgrading from Rails 4.0 to Rails 4.1
13.1 원격 <script>
태그로부터의 CSRF 보호
또는, "으악 내 테스트가 실패하고 있어!!!" 또는 "내 <script>
위젯이 망가졌어!!"
Cross-site request forgery (CSRF) 보호가 이제 JavaScript 응답이 있는 GET 요청도 포함합니다. 이는 제3자 사이트가 <script>
태그를 사용하여 민감한 데이터를 추출하기 위해 당신의 JavaScript를 원격으로 참조하는 것을 방지합니다.
이는 다음을 사용하는 기능 테스트와 통합 테스트가
get :index, format: :js
CSRF protection이 이제 트리거됩니다. 다음으로 전환하세요
xhr :get, :index, format: :js
XmlHttpRequest
를 명시적으로 테스트하기 위해서입니다.
자체적인 <script>
태그도 교차 출처로 간주되어 기본적으로 차단됩니다. 만약 <script>
태그로부터 JavaScript를 로드하려면, 이제 해당 액션들에 대해 명시적으로 CSRF 보호를 스킵해야 합니다.
13.2 Spring
애플리케이션 preloader로 Spring을 사용하려면 다음과 같이 해야 합니다:
Gemfile
에gem "spring", group: :development
를 추가하세요.bundle install
을 사용하여 spring을 설치하세요.bundle exec spring binstub
으로 Spring binstub을 생성하세요.
사용자가 정의한 rake 작업은 기본적으로 development
환경에서 실행됩니다. 다른 환경에서 실행하려면 Spring README를 참고하세요.
13.3 config/secrets.yml
애플리케이션의 secrets를 저장하기 위해 새로운 secrets.yml
규칙을 사용하고 싶다면 다음과 같이 해야 합니다:
config
폴더에 다음 내용으로secrets.yml
파일을 생성하세요:development: secret_key_base: test: secret_key_base: production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
production 환경에서 Rails 애플리케이션을 실행하는 사용자들을 위해
secret_token.rb
initializer에서 기존의secret_key_base
를 사용하여SECRET_KEY_BASE
환경 변수를 설정하세요. 또는secret_token.rb
initializer에서 기존secret_key_base
를secrets.yml
의production
섹션에<%= ENV["SECRET_KEY_BASE"] %>
를 대체하여 복사할 수도 있습니다.secret_token.rb
initializer를 제거하세요.rake secret
을 사용하여development
와test
섹션을 위한 새로운 키를 생성하세요.서버를 재시작하세요.
13.4 test helper 변경사항
만약 test helper에 ActiveRecord::Migration.check_pending!
호출이 포함되어 있다면 이를 제거할 수 있습니다. 이 검사는 이제 require "rails/test_help"
를 실행할 때 자동으로 수행되지만, helper에 이 라인을 남겨두어도 아무런 문제가 되지 않습니다.
13.5 Cookies serializer
Rails 4.1 이전에 생성된 애플리케이션들은 signed 및 encrypted cookie jar에 cookie 값을 직렬화하기 위해 Marshal
을 사용합니다. 애플리케이션에서 새로운 JSON
기반 형식을 사용하고 싶다면, 다음 내용으로 initializer 파일을 추가할 수 있습니다:
Rails.application.config.action_dispatch.cookies_serializer = :hybrid
:hybrid
serializer를 사용하면 기존의 Marshal로 직렬화된 cookie를 읽어들일 수 있지만, 새로 작성되는 cookie는 JSON 형식으로 직렬화됩니다.
이는 기존의 Marshal
로 직렬화된 쿠키를 새로운 JSON
기반 형식으로 투명하게 마이그레이션합니다.
:json
또는 :hybrid
시리얼라이저를 사용할 때는 모든 Ruby 객체가 JSON으로 직렬화될 수 있는 것은 아니라는 점에 주의해야 합니다. 예를 들어, Date
와 Time
객체는 문자열로 직렬화되며, Hash
의 키는 문자열화됩니다.
class CookiesController < ApplicationController
def set_cookie
cookies.encrypted[:expiration_date] = Date.tomorrow # => 목, 20 3월 2014
redirect_to action: "read_cookie"
end
def read_cookie
cookies.encrypted[:expiration_date] # => "2014-03-20"
end
end
쿠키에는 단순한 데이터(문자열과 숫자)만 저장하는 것이 좋습니다. 복잡한 객체를 저장해야 하는 경우, 후속 요청에서 값을 읽을 때 수동으로 변환을 처리해야 합니다.
쿠키 세션 저장소를 사용하는 경우, 이는 session
과 flash
해시에도 적용됩니다.
13.6 Flash 구조 변경
Flash 메시지 키가 문자열로 정규화 되었습니다. 여전히 심볼이나 문자열을 사용해서 접근할 수 있습니다. Flash를 반복할 때는 항상 문자열 키가 반환됩니다:
flash["string"] = "a string"
flash[:symbol] = "a symbol"
# Rails < 4.1
flash.keys # => ["string", :symbol]
# Rails >= 4.1
flash.keys # => ["string", "symbol"]
Flash message key들을 문자열과 비교할 때는 주의하세요.
13.7 JSON 처리의 변경사항
Rails 4.1에서 JSON 처리와 관련된 몇 가지 주요 변경사항이 있습니다.
13.7.1 MultiJSON 제거
MultiJSON은 수명이 다했으며 Rails에서 제거되었습니다.
현재 애플리케이션이 MultiJSON에 직접적으로 의존하고 있다면, 다음과 같은 옵션이 있습니다:
Gemfile
에 'multi_json'를 추가합니다. 단, 이는 향후 작동하지 않을 수 있습니다obj.to_json
와JSON.parse(str)
를 사용하여 MultiJSON에서 벗어나도록 마이그레이션합니다.
MultiJson.load
를 단순히 JSON.load
로 대체하지 마세요. 해당 API는 임의의 Ruby 객체를 역직렬화하기 위한 것이며 일반적으로 안전하지 않습니다. 대신 JSON.parse
를 사용하는 것이 좋습니다.
13.7.2 JSON gem 호환성
역사적으로, Rails는 JSON gem과 일부 호환성 문제가 있었습니다. Rails 애플리케이션 내에서 JSON.generate
와 JSON.dump
를 사용하면 예기치 않은 오류가 발생할 수 있었습니다.
Rails 4.1은 자체 인코더를 JSON gem으로부터 분리함으로써 이러한 문제를 해결했습니다. JSON gem API는 정상적으로 작동하지만, Rails 관련 기능에는 접근할 수 없습니다. 예를 들면:
class FooBar
def as_json(options = nil)
{ foo: "bar" }
end
end
irb> FooBar.new.to_json
=> "{\"foo\":\"bar\"}"
irb> JSON.generate(FooBar.new, quirks_mode: true)
=> "\"#<FooBar:0x007fa80a481610>\""
13.7.3 새로운 JSON 인코더
Rails 4.1의 JSON 인코더는 JSON gem을 활용하기 위해 재작성되었습니다. 대부분의 애플리케이션에서는 투명하게 변경될 것입니다. 하지만 재작성의 일환으로 인코더에서 다음 기능들이 제거되었습니다:
- 순환 데이터 구조 감지
encode_json
훅 지원BigDecimal
객체를 문자열 대신 숫자로 인코딩하는 옵션
애플리케이션이 이러한 기능들 중 하나에 의존하고 있다면, Gemfile
에 activesupport-json_encoder
gem을 추가하여 해당 기능들을 다시 사용할 수 있습니다.
13.7.4 Time 객체의 JSON 표현
시간 컴포넌트(Time
, DateTime
, ActiveSupport::TimeWithZone
)를 가진 객체의 #as_json
은 이제 기본적으로 밀리초 정밀도를 반환합니다. 밀리초 정밀도가 없는 이전 동작을 유지해야 한다면, initializer에 다음과 같이 설정하세요:
ActiveSupport::JSON::Encoding.time_precision = 0
이렇게 하면 JSON 출력에 밀리초가 포함되지 않습니다.
13.8 인라인 콜백 블록 내에서 return
사용
이전에는 Rails가 인라인 콜백 블록에서 다음과 같은 방식으로 return
을 사용하는 것을 허용했습니다:
class ReadOnlyModel < ActiveRecord::Base
before_save { return false } # 나쁜 예
end
이 동작은 의도적으로 지원된 적이 없습니다. ActiveSupport::Callbacks
의 내부 변경으로 인해 Rails 4.1에서는 더 이상 허용되지 않습니다. 인라인 callback 블록에서 return
문을 사용하면 callback이 실행될 때 LocalJumpError
가 발생합니다.
return
을 사용하는 인라인 callback 블록은 반환값을 평가하도록 리팩토링할 수 있습니다:
class ReadOnlyModel < ActiveRecord::Base
before_save { false } # 좋음
end
대안으로, return
을 선호한다면 명시적으로 메서드를 정의하는 것이 권장됩니다:
class ReadOnlyModel < ActiveRecord::Base
before_save :before_save_callback # GOOD
private
def before_save_callback
false
end
end
이 변경사항은 Active Record와 Active Model 콜백, 그리고 Action Controller의 필터(예: before_action
)를 포함하여 Rails에서 콜백이 사용되는 대부분의 곳에 적용됩니다.
자세한 내용은 이 pull request를 참조하세요.
13.9 Active Record fixtures에 정의된 메소드
Rails 4.1은 각 fixture의 ERB를 별도의 context에서 평가하므로, fixture에 정의된 helper 메소드는 다른 fixture에서 사용할 수 없습니다.
여러 fixture에서 사용되는 helper 메소드는 test_helper.rb
에서 새로 도입된 ActiveRecord::FixtureSet.context_class
에 포함된 module에 정의되어야 합니다.
module FixtureFileHelpers
def file_sha(path)
OpenSSL::Digest::SHA256.hexdigest(File.read(Rails.root.join("test/fixtures", path)))
end
end
# Fixture set의 컨텍스트 클래스에 FixtureFileHelpers 모듈을 포함시킵니다
ActiveRecord::FixtureSet.context_class.include FixtureFileHelpers
13.10 I18n 사용 가능한 locale 강제하기
Rails 4.1은 이제 I18n 옵션 enforce_available_locales
의 기본값을 true
로 설정합니다. 이는 I18n에 전달되는 모든 locale이 available_locales
목록에 선언되어 있어야 함을 의미합니다.
이를 비활성화하고 (I18n이 어떤 locale 옵션이든 허용하도록) 하려면 애플리케이션에 다음 설정을 추가하세요:
config.i18n.enforce_available_locales = false
이 설정을 통해 :en이나 다른 사용 가능한 locale을 포함하지 않은 locale이 있더라도 I18n에서 경고가 발생하지 않습니다.
이 옵션은 보안 조치로 추가되었으며, 사전에 알려진 경우가 아니라면 사용자 입력을 locale 정보로 사용할 수 없도록 하기 위한 것입니다. 따라서 매우 강력한 이유가 없다면 이 옵션을 비활성화하지 않는 것이 좋습니다.
13.11 Relation에서 호출되는 변경자(mutator) 메서드
Relation
은 더 이상 #map!
과 #delete_if
같은 변경자 메서드를 가지고 있지 않습니다. 이러한 메서드들을 사용하기 전에 #to_a
를 호출하여 Array
로 변환하세요.
이는 Relation
에서 직접 변경자 메서드를 호출하는 코드에서 발생할 수 있는 이상한 버그와 혼란을 방지하기 위한 것입니다.
# 이렇게 하는 대신
Author.where(name: "Hank Moody").compact!
# 이제는 이렇게 해야 합니다
authors = Author.where(name: "Hank Moody").to_a
authors.compact!
13.12 Default Scope의 변화
Default scope는 더이상 연결된 조건에 의해 덮어쓰여지지 않습니다.
이전 버전에서는 모델에서 default_scope
를 정의하면 동일 필드의 연결된 조건에 의해 덮어쓰여졌습니다. 이제는 다른 scope들처럼 병합됩니다.
이전:
class User < ActiveRecord::Base
default_scope { where state: "pending" }
scope :active, -> { where state: "active" }
scope :inactive, -> { where state: "inactive" }
end
User.all
# "users" 테이블에서 "users"."state" = 'pending'인 모든 레코드를 선택
User.active
# "users" 테이블에서 "users"."state" = 'active'인 모든 레코드를 선택
User.where(state: "inactive")
# "users" 테이블에서 "users"."state" = 'inactive'인 모든 레코드를 선택
죄송하지만 번역할 문서가 제공되지 않았습니다. 번역하고 싶은 Rails 가이드 문서를 공유해 주시면 번역을 도와드리겠습니다.
class User < ActiveRecord::Base
default_scope { where state: "pending" }
scope :active, -> { where state: "active" }
scope :inactive, -> { where state: "inactive" }
end
User.all
# "users" 테이블의 모든 레코드 중에서 "users"."state"가 'pending'인 것을 SELECT
User.active
# "users" 테이블에서 "users"."state"가 'pending'이고 "users"."state"가 'active'인 것을 SELECT
User.where(state: "inactive")
# "users" 테이블에서 "users"."state"가 'pending'이고 "users"."state"가 'inactive'인 것을 SELECT
이전 동작을 얻으려면 unscoped
, unscope
, rewhere
또는 except
를 사용하여 default_scope
조건을 명시적으로 제거해야 합니다.
class User < ActiveRecord::Base
default_scope { where state: "pending" }
scope :active, -> { unscope(where: :state).where(state: "active") }
scope :inactive, -> { rewhere state: "inactive" }
end
User.all
# "users" 테이블에서 "users"."state" = 'pending'인 모든 레코드 조회
User.active
# "users" 테이블에서 "users"."state" = 'active'인 모든 레코드 조회
User.inactive
# "users" 테이블에서 "users"."state" = 'inactive'인 모든 레코드 조회
13.13 문자열에서 콘텐츠 렌더링하기
Rails 4.1에서는 render
에 :plain
, :html
, :body
옵션이 도입되었습니다. 이러한 옵션들은 이제 문자열 기반 콘텐츠를 렌더링하는 데 선호되는 방식입니다. 응답을 어떤 content type으로 보낼지 지정할 수 있기 때문입니다.
render :plain
은 content type을text/plain
으로 설정합니다render :html
은 content type을text/html
로 설정합니다render :body
는 content type 헤더를 설정하지 않습니다
보안 관점에서, 응답 본문에 마크업이 없을 것으로 예상되는 경우 render :plain
을 사용해야 합니다. 대부분의 브라우저가 응답의 안전하지 않은 콘텐츠를 이스케이프 처리해주기 때문입니다.
향후 버전에서는 render :text
사용을 deprecate할 예정입니다. 따라서 더 정확한 :plain
, :html
, :body
옵션을 대신 사용하기 시작하세요. render :text
를 사용하면 콘텐츠가 text/html
로 전송되므로 보안 위험이 있을 수 있습니다.
13.14 PostgreSQL JSON과 hstore 데이터타입
Rails 4.1은 json
과 hstore
컬럼을 문자열 키를 가진 Ruby Hash
로 매핑합니다.
이전 버전에서는 HashWithIndifferentAccess
가 사용되었습니다. 이는 심볼을 통한 접근이
더 이상 지원되지 않는다는 것을 의미합니다. 이는 json
또는 hstore
컬럼을 기반으로 한
store_accessors
에도 해당됩니다. 반드시 문자열 키를 일관되게 사용하도록 하세요.
13.15 ActiveSupport::Callbacks
의 명시적인 블록 사용
Rails 4.1에서는 ActiveSupport::Callbacks.set_callback
을 호출할 때 명시적인 블록을 전달해야 합니다. 이 변경사항은 Rails 4.1 릴리스를 위해 ActiveSupport::Callbacks
가 대부분 재작성되면서 발생했습니다.
# 이전 Rails 4.0
set_callback :save, :around, ->(r, &block) { stuff; result = block.call; stuff }
# Rails 4.1에서 변경됨
set_callback :save, :around, ->(r, block) { stuff; result = block.call; stuff }
14 Upgrading from Rails 3.2 to Rails 4.0
애플리케이션이 현재 3.2.x보다 오래된 Rails 버전을 사용중이라면, Rails 4.0으로 업그레이드하기 전에 먼저 Rails 3.2로 업그레이드해야 합니다.
다음 변경사항들은 애플리케이션을 Rails 4.0으로 업그레이드하기 위한 것입니다.
14.1 HTTP PATCH
Rails 4는 config/routes.rb
에서 RESTful resource가 선언될 때 업데이트를 위한 주요 HTTP verb로 PATCH
를 사용합니다. update
액션은 여전히 사용되며, PUT
요청도 계속해서 update
액션으로 라우팅됩니다. 따라서 표준 RESTful 라우트만 사용하는 경우에는 변경할 필요가 없습니다:
resources :users
<%= @user에 대한 form_for 도우미를 사용해서 |f| %>
class UsersController < ApplicationController
def update
# 변경 필요 없음; PATCH가 선호되며 PUT도 여전히 작동함.
end
end
하지만 만약 PUT
HTTP method를 사용하는 custom route와 함께 리소스를 업데이트하기 위해 form_for
를 사용하는 경우에는 변경이 필요합니다:
resources :users do
put :update_name, on: :member
end
:member
키워드는 행동이 리소스의 한 멤버에서 수행되어야 한다는 것을 나타냅니다. 이는 ID가 포함된 URL인 /users/1/update_name을 생성합니다.
<%= form_for [ :update_name, @user ] do |f| %>
class UsersController < ApplicationController
def update_name
# 변경 필요; form_for는 존재하지 않는 PATCH 라우트를 사용하려고 할 것입니다.
end
end
해당 action이 public API에서 사용되지 않고 HTTP method를 자유롭게 변경할 수 있다면, route를 수정하여 put
대신 patch
를 사용할 수 있습니다:
resources :users do
patch :update_name, on: :member
end
:member
옵션을 사용하면 /users/:id/update_name
과 같이 멤버 리소스의 URL을 정의할 수 있습니다.
PUT
요청은 Rails 4에서 현재처럼 /users/:id
로 라우팅되어 update
로 전달됩니다. 따라서 실제 PUT 요청을 받는 API가 있다면 정상적으로 동작할 것입니다. 라우터는 /users/:id
로 오는 PATCH
요청도 update
액션으로 라우팅합니다.
만약 액션이 공개 API에서 사용되고 있어서 사용중인 HTTP 메서드를 변경할 수 없는 경우, form을 업데이트하여 PUT
메서드를 대신 사용할 수 있습니다:
<%= form_for [ :update_name, @user ], method: :put do |f| %>
이 코드는 form 을 생성하여 :update_name
과 @user
를 통해 생성된 경로로 PUT 요청을 보냅니다.
PATCH와 이 변경이 이루어진 이유에 대해 자세히 알아보려면 Rails 블로그의 이 포스트를 참고하세요.
14.1.1 미디어 타입에 대한 참고사항
PATCH
동사의 정오표는 PATCH
와 함께 'diff' 미디어 타입을 사용해야 한다고 명시하고 있습니다. 이러한 형식 중 하나가 JSON Patch입니다. Rails는 JSON Patch를 기본적으로 지원하지 않지만, 지원을 추가하는 것은 충분히 쉽습니다:
# 컨트롤러에서:
def update
respond_to do |format|
format.json do
# 부분 업데이트 수행
@article.update params[:article]
end
format.json_patch do
# 복잡한 변경 수행
end
end
end
# config/initializers/json_patch.rb
Mime::Type.register "application/json-patch+json", :json_patch
JSON Patch가 최근에 RFC가 되었기 때문에, 아직 훌륭한 Ruby 라이브러리가 많지 않습니다. Aaron Patterson의 hana가 그런 gem 중 하나이지만, 명세의 최근 변경사항들을 완전히 지원하지는 않습니다.
14.2 Gemfile
Rails 4.0은 Gemfile
에서 assets
group을 제거했습니다. 업그레이드할 때 Gemfile
에서 해당 라인을 제거해야 합니다. 또한 애플리케이션 파일(config/application.rb
)을 업데이트해야 합니다:
# Gemfile에 나열된 gem들을 require합니다. :test, :development, :production과 같이
# 특정 환경에 제한된 gem들도 포함됩니다.
Bundler.require(*Rails.groups)
14.3 vendor/plugins
Rails 4.0에서는 더 이상 vendor/plugins
에서 plugin을 로드하는 것을 지원하지 않습니다. plugin들을 gem으로 추출하고 Gemfile
에 추가하여 교체해야 합니다. gem으로 만들지 않기로 선택한 경우, 예를 들어 lib/my_plugin/*
로 옮기고 config/initializers/my_plugin.rb
에 적절한 initializer를 추가할 수 있습니다.
14.4 Active Record
Rails 4.0에서는 연관관계에서의 일부 불일치로 인해 Active Record의 identity map이 제거되었습니다. 애플리케이션에서 수동으로 활성화했다면, 더 이상 효과가 없는 다음 설정을 제거해야 합니다:
config.active_record.identity_map
.collection 연관관계의
delete
메서드는 이제destroy
메서드처럼 record 외에도Integer
나String
타입의 record id를 인자로 받을 수 있습니다. 이전에는 이러한 인자에 대해ActiveRecord::AssociationTypeMismatch
를 발생시켰습니다. Rails 4.0부터는delete
가 삭제하기 전에 자동으로 주어진 id와 일치하는 record를 찾습니다.Rails 4.0에서는 column이나 table의 이름이 변경될 때 관련 index들도 함께 이름이 변경됩니다. index 이름을 변경하는 migration이 있다면, 더 이상 필요하지 않습니다.
Rails 4.0에서는
serialized_attributes
와attr_readonly
를 클래스 메서드로만 변경했습니다. 이제 deprecated된 인스턴스 메서드는 사용하지 않아야 합니다. 클래스 메서드를 사용하도록 변경해야 합니다. 예:self.serialized_attributes
에서self.class.serialized_attributes
로.기본 coder를 사용할 때, serialized 속성에
nil
을 할당하면 YAML을 통해nil
값을 전달하는 대신 ("--- \n...\n"
) 데이터베이스에NULL
로 저장됩니다.Rails 4.0에서는 Strong Parameters를 위해
attr_accessible
과attr_protected
기능이 제거되었습니다. 원활한 업그레이드를 위해 Protected Attributes gem을 사용할 수 있습니다.Protected Attributes를 사용하지 않는다면,
whitelist_attributes
나mass_assignment_sanitizer
옵션과 같은 이 gem과 관련된 옵션들을 제거할 수 있습니다.Rails 4.0에서는 scope가 Proc이나 lambda 같은 callable 객체를 사용하도록 요구합니다:
scope :active, where(active: true) # 다음과 같이 변경 scope :active, -> { where active: true }
Rails 4.0에서는
ActiveRecord::Fixtures
대신ActiveRecord::FixtureSet
을 사용하도록 deprecated 되었습니다.Rails 4.0에서는
ActiveRecord::TestCase
대신ActiveSupport::TestCase
를 사용하도록 deprecated 되었습니다.Rails 4.0에서는 구식 해시 기반 finder API가 deprecated 되었습니다. 이는 이전에 "finder options"를 받았던 메서드들이 더 이상 그렇지 않다는 것을 의미합니다. 예를 들어,
Book.find(:all, conditions: { name: '1984' })
는Book.where(name: '1984')
를 사용하도록 deprecated 되었습니다.find_by_...
와find_by_...!
를 제외한 모든 동적 메서드가 deprecated 되었습니다. 변경 사항은 다음과 같습니다:find_all_by_...
는where(...)
로 변경find_last_by_...
는where(...).last
로 변경scoped_by_...
는where(...)
로 변경find_or_initialize_by_...
는find_or_initialize_by(...)
로 변경find_or_create_by_...
는find_or_create_by(...)
로 변경
where(...)
는 이전 finder들처럼 배열이 아닌 relation을 반환한다는 점에 주의하세요. 배열이 필요한 경우where(...).to_a
를 사용하세요.이러한 동등한 메서드들은 이전 구현과 동일한 SQL을 실행하지 않을 수 있습니다.
이전 finder들을 다시 활성화하려면 activerecord-deprecated_finders gem을 사용할 수 있습니다.
Rails 4.0에서는
has_and_belongs_to_many
관계의 기본 join table이 두 번째 테이블 이름에서 공통 접두사를 제거하도록 변경되었습니다. 공통 접두사를 가진 모델 간의 기존has_and_belongs_to_many
관계는join_table
옵션으로 지정되어야 합니다. 예를 들어:
class CatalogCategory < ActiveRecord::Base
has_and_belongs_to_many :catalog_products, join_table: "catalog_categories_catalog_products"
end
class CatalogProduct < ActiveRecord::Base
has_and_belongs_to_many :catalog_categories, join_table: "catalog_categories_catalog_products"
end
- prefix는 scope도 고려하므로,
Catalog::Category
와Catalog::Product
또는Catalog::Category
와CatalogProduct
간의 관계도 이와 유사하게 업데이트해야 합니다.
14.5 Active Resource
Rails 4.0에서는 Active Resource를 독립적인 gem으로 분리했습니다. 만약 이 기능이 여전히 필요하다면 Gemfile
에 Active Resource gem을 추가하면 됩니다.
14.6 Active Model
Rails 4.0에서는
ActiveModel::Validations::ConfirmationValidator
로 에러를 연결하는 방식이 변경되었습니다. 이제 확인 유효성 검사가 실패하면 에러는attribute
대신:#{attribute}_confirmation
에 연결됩니다.Rails 4.0에서는
ActiveModel::Serializers::JSON.include_root_in_json
의 기본값이false
로 변경되었습니다. 이제 Active Model Serializer와 Active Record 객체가 동일한 기본 동작을 가집니다. 이는config/initializers/wrap_parameters.rb
파일에서 다음 옵션을 주석 처리하거나 제거할 수 있다는 것을 의미합니다:# Disable root element in JSON by default. # ActiveSupport.on_load(:active_record) do # self.include_root_in_json = false # end
14.7 Action Pack
Rails 4.0은
ActiveSupport::KeyGenerator
를 도입하여 서명된 쿠키를 생성하고 검증하는 데 기반으로 사용합니다(다른 용도도 있음). 기존의secret_token
을 유지하고 새로운secret_key_base
를 추가하면 Rails 3.x에서 생성된 기존 서명된 쿠키들이 자동으로 업그레이드됩니다.# config/initializers/secret_token.rb Myapp::Application.config.secret_token = "existing secret token" Myapp::Application.config.secret_key_base = "new secret key base"
사용자 기반의 100%가 Rails 4.x를 사용하고 Rails 3.x로 롤백할 필요가 없다고 확신할 때까지
secret_key_base
를 설정하지 않는 것이 좋습니다. 이는 Rails 4.x에서 새로운secret_key_base
를 기반으로 서명된 쿠키가 Rails 3.x와 하위 호환되지 않기 때문입니다. 업그레이드가 완료되었다고 확신할 때까지 기존의secret_token
을 유지하고, 새로운secret_key_base
를 설정하지 않은 채로 deprecation 경고를 무시해도 됩니다.외부 애플리케이션이나 JavaScript가 Rails 앱의 서명된 세션 쿠키(또는 일반적인 서명된 쿠키)를 읽을 수 있어야 하는 경우, 이러한 의존성을 분리할 때까지
secret_key_base
를 설정하지 마세요.Rails 4.0은
secret_key_base
가 설정된 경우 쿠키 기반 세션의 내용을 암호화합니다. Rails 3.x는 쿠키 기반 세션의 내용을 서명했지만 암호화하지는 않았습니다. 서명된 쿠키는 앱에서 생성되었다는 것이 검증되고 변조가 불가능하다는 점에서 "안전"합니다. 하지만 최종 사용자가 내용을 볼 수 있으며, 내용을 암호화하면 성능 저하 없이 이러한 문제/우려를 제거할 수 있습니다.암호화된 세션 쿠키로의 이전에 대한 자세한 내용은 Pull Request #9978을 참조하세요.
Rails 4.0은
ActionController::Base.asset_path
옵션을 제거했습니다. assets pipeline 기능을 사용하세요.Rails 4.0은
ActionController::Base.page_cache_extension
옵션을 deprecated 했습니다. 대신ActionController::Base.default_static_extension
을 사용하세요.Rails 4.0은 Action Pack에서 Action 및 Page 캐싱을 제거했습니다. 컨트롤러에서
caches_action
을 사용하려면actionpack-action_caching
gem을,caches_page
를 사용하려면actionpack-page_caching
gem을 추가해야 합니다.Rails 4.0은 XML 파라미터 파서를 제거했습니다. 이 기능이 필요한 경우
actionpack-xml_parser
gem을 추가해야 합니다.Rails 4.0은 nil을 반환하는 심볼이나 proc을 사용하는 기본
layout
조회를 변경했습니다. "레이아웃 없음" 동작을 얻으려면 nil 대신 false를 반환하세요.Rails 4.0은 기본 memcached 클라이언트를
memcache-client
에서dalli
로 변경했습니다. 업그레이드하려면Gemfile
에gem "dalli"
를 추가하면 됩니다.Rails 4.0은 컨트롤러에서
dom_id
와dom_class
메서드를 deprecated 했습니다(뷰에서는 계속 사용 가능). 이 기능이 필요한 컨트롤러에ActionView::RecordIdentifier
모듈을 포함해야 합니다.Rails 4.0은
link_to
헬퍼의:confirm
옵션을 deprecated 했습니다. 대신 data 속성을 사용해야 합니다(예:data: { confirm: 'Are you sure?' }
). 이 deprecation은 이를 기반으로 하는 헬퍼(link_to_if
나link_to_unless
등)에도 적용됩니다.Rails 4.0은
assert_generates
,assert_recognizes
,assert_routing
의 작동 방식을 변경했습니다. 이제 이러한 assertions는ActionController::RoutingError
대신Assertion
을 발생시킵니다.Rails 4.0은 충돌하는 명명된 라우트가 정의되면
ArgumentError
를 발생시킵니다. 이는 명시적으로 정의된 명명된 라우트나resources
메서드로 인해 발생할 수 있습니다. 다음은example_path
라는 라우트가 충돌하는 두 예시입니다:get "one" => "test#example", as: :example get "two" => "test#example", as: :example
resources :examples get "clashing/:id" => "test#example", as: :example
첫 번째 경우에는 여러 route에 대해 동일한 이름을 사용하지 않으면 됩니다. 두 번째 경우에는 resources
메서드가 제공하는 only
또는 except
옵션을 사용하여 Routing Guide에 자세히 설명된 대로 생성되는 route를 제한할 수 있습니다.
Rails 4.0은 유니코드 문자 route를 그리는 방식도 변경했습니다. 이제 유니코드 문자 route를 직접 그릴 수 있습니다. 이미 이러한 route를 그린 경우 다음과 같이 변경해야 합니다:
get Rack::Utils.escape("こんにちは"), controller: "welcome", action: "index"
다음과 같이 변경:
get "こんにちは", controller: "welcome", action: "index"
Rails 4.0은
match
를 사용하는 route가 반드시 request method를 지정하도록 요구합니다. 예시:# Rails 3.x match "/" => "root#index" # 다음과 같이 변경 match "/" => "root#index", via: :get # 또는 get "/" => "root#index"
Rails 4.0은
ActionDispatch::BestStandardsSupport
middleware를 제거했습니다.<!DOCTYPE html>
는 이미 https://msdn.microsoft.com/en-us/library/jj676915(v=vs.85).aspx 에 따라 standards mode를 트리거하며 ChromeFrame 헤더는config.action_dispatch.default_headers
로 이동되었습니다.애플리케이션 코드에서 middleware에 대한 참조도 모두 제거해야 합니다. 예시:
# 예외 발생 config.middleware.insert_before(Rack::Lock, ActionDispatch::BestStandardsSupport)
또한 환경 설정에서
config.action_dispatch.best_standards_support
를 확인하고 있다면 제거하십시오.Rails 4.0은
config.action_dispatch.default_headers
를 설정하여 HTTP 헤더를 구성할 수 있습니다. 기본값은 다음과 같습니다:config.action_dispatch.default_headers = { "X-Frame-Options" => "SAMEORIGIN", "X-XSS-Protection" => "1; mode=block" }
애플리케이션이 특정 페이지를 <frame>
또는 <iframe>
에서 로드해야 하는 경우, X-Frame-Options
를 명시적으로 ALLOW-FROM ...
또는 ALLOWALL
로 설정해야 할 수 있습니다.
Rails 4.0에서는 asset precompile 시
vendor/assets
와lib/assets
에서 JS/CSS가 아닌 asset들을 자동으로 복사하지 않습니다. Rails 애플리케이션과 엔진 개발자들은 이러한 asset들을app/assets
에 넣거나config.assets.precompile
을 설정해야 합니다.Rails 4.0에서는 액션이 요청 포맷을 처리하지 못할 때
ActionController::UnknownFormat
이 발생합니다. 기본적으로 이 예외는 406 Not Acceptable로 응답하지만 이제 이를 재정의할 수 있습니다. Rails 3에서는 항상 406 Not Acceptable이 반환되었고 재정의할 수 없었습니다.Rails 4.0에서는
ParamsParser
가 요청 파라미터를 파싱하는데 실패할 경우 일반적인ActionDispatch::ParamsParser::ParseError
예외가 발생합니다. 예를 들어 낮은 수준의MultiJson::DecodeError
대신 이 예외를 rescue해야 합니다.Rails 4.0에서는 URL 접두사로 제공되는 앱에 엔진이 마운트될 때
SCRIPT_NAME
이 적절하게 중첩됩니다. 더 이상 덮어쓴 URL 접두사를 해결하기 위해default_url_options[:script_name]
을 설정할 필요가 없습니다.Rails 4.0은
ActionController::Integration
대신ActionDispatch::Integration
을 사용하도록 권장합니다.Rails 4.0은
ActionController::IntegrationTest
대신ActionDispatch::IntegrationTest
를 사용하도록 권장합니다.Rails 4.0은
ActionController::PerformanceTest
대신ActionDispatch::PerformanceTest
를 사용하도록 권장합니다.Rails 4.0은
ActionController::AbstractRequest
대신ActionDispatch::Request
를 사용하도록 권장합니다.Rails 4.0은
ActionController::Request
대신ActionDispatch::Request
를 사용하도록 권장합니다.Rails 4.0은
ActionController::AbstractResponse
대신ActionDispatch::Response
를 사용하도록 권장합니다.Rails 4.0은
ActionController::Response
대신ActionDispatch::Response
를 사용하도록 권장합니다.Rails 4.0은
ActionController::Routing
대신ActionDispatch::Routing
를 사용하도록 권장합니다.
14.8 Active Support
Rails 4.0에서는 j
가 이미 ActionView::Helpers::JavaScriptHelper#escape_javascript
에서 사용되고 있기 때문에 ERB::Util#json_escape
의 별칭인 j
를 제거했습니다.
14.8.1 Cache
Rails 3.x와 4.0 사이에 캐싱 방식이 변경되었습니다. cache namespace를 변경하고 빈 캐시로 배포해야 합니다.
14.9 Helpers 로딩 순서
한 개 이상의 디렉토리에서 helper를 로딩하는 순서가 Rails 4.0에서 변경되었습니다. 이전에는 모든 helper를 수집한 후 알파벳순으로 정렬했습니다. Rails 4.0으로 업그레이드한 후에는 helper가 로딩된 디렉토리의 순서를 유지하고 각 디렉토리 내에서만 알파벳순으로 정렬됩니다. helpers_path
파라미터를 명시적으로 사용하지 않는 한, 이 변경사항은 engine에서 helper를 로딩하는 방식에만 영향을 미칩니다. 만약 이 순서에 의존하고 있다면, 업그레이드 후에 올바른 메서드들이 사용 가능한지 확인해야 합니다. engine이 로딩되는 순서를 변경하고 싶다면, config.railties_order=
메서드를 사용할 수 있습니다.
14.10 Active Record Observer와 Action Controller Sweeper
ActiveRecord::Observer
와 ActionController::Caching::Sweeper
는 rails-observers
gem으로 분리되었습니다. 이러한 기능이 필요한 경우 rails-observers
gem을 추가해야 합니다.
14.11 sprockets-rails
assets:precompile:primary
와assets:precompile:all
이 제거되었습니다. 대신assets:precompile
을 사용하세요.config.assets.compress
옵션은 다음과 같이config.assets.js_compressor
로 변경되어야 합니다:config.assets.js_compressor = :uglifier
14.12 sass-rails
- 두 개의 인자를 가진
asset-url
은 더 이상 사용되지 않습니다. 예를 들어:asset-url("rails.png", image)
는asset-url("rails.png")
가 됩니다.
15 Rails 3.1에서 Rails 3.2로 업그레이드
현재 애플리케이션이 Rails 3.1.x 이전 버전이라면, Rails 3.2로 업그레이드를 시도하기 전에 먼저 Rails 3.1로 업그레이드해야 합니다.
다음 변경사항들은 애플리케이션을 최신 Rails 3.2.x 버전으로 업그레이드하기 위한 것입니다.
15.1 Gemfile
Gemfile
에 다음과 같은 변경사항을 적용하세요.
gem "rails", "3.2.21"
group :assets do
gem "sass-rails", "~> 3.2.6"
gem "coffee-rails", "~> 3.2.2"
gem "uglifier", ">= 1.0.3"
end
15.2 config/environments/development.rb
development 환경에 추가해야 할 몇 가지 새로운 configuration 설정이 있습니다:
# Active Record 모델에 대한 mass assignment 보호에 대해 예외 발생시키기
config.active_record.mass_assignment_sanitizer = :strict
# 지정된 시간보다 오래 걸리는 쿼리에 대해 쿼리 계획 로깅하기
# (SQLite, MySQL, PostgreSQL에서 동작)
config.active_record.auto_explain_threshold_in_seconds = 0.5
15.3 config/environments/test.rb
mass_assignment_sanitizer
설정은 config/environments/test.rb
파일에도 추가되어야 합니다:
# Active Record 모델에 대한 mass assignment 보호에서 예외 발생시키기
config.active_record.mass_assignment_sanitizer = :strict
15.4 vendor/plugins
Rails 3.2는 vendor/plugins
를 deprecate했고 Rails 4.0에서는 완전히 제거될 예정입니다. Rails 3.2 업그레이드의 필수 사항은 아니지만, plugin들을 gem으로 추출하고 Gemfile
에 추가하는 방식으로 교체하기 시작할 수 있습니다. gem으로 만들지 않기로 선택했다면, 예를 들어 lib/my_plugin/*
로 옮기고 config/initializers/my_plugin.rb
에 적절한 initializer를 추가할 수 있습니다.
15.5 Active Record
Option :dependent => :restrict
가 belongs_to
에서 제거되었습니다. 관련 객체가 있는 경우 객체 삭제를 방지하려면 :dependent => :destroy
를 설정하고 관련된 객체의 destroy 콜백에서 연관관계의 존재 여부를 확인한 후 false
를 반환하면 됩니다.
16 Rails 3.0에서 Rails 3.1로 업그레이드하기
현재 애플리케이션이 3.0.x 이전 버전의 Rails를 사용중이라면, Rails 3.1 업데이트를 시도하기 전에 먼저 Rails 3.0으로 업그레이드해야 합니다.
다음 변경사항들은 Rails의 마지막 3.1.x 버전인 Rails 3.1.12로 애플리케이션을 업그레이드하기 위한 것입니다.
16.1 Gemfile
Gemfile
에 다음과 같이 변경사항을 적용하세요.
gem "rails", "3.1.12"
gem "mysql2"
# 새로운 asset pipeline에 필요함
group :assets do
gem "sass-rails", "~> 3.1.7"
gem "coffee-rails", "~> 3.1.1"
gem "uglifier", ">= 1.0.3"
end
# jQuery는 Rails 3.1의 기본 JavaScript 라이브러리입니다
gem "jquery-rails"
16.2 config/application.rb
asset pipeline은 다음과 같은 추가 사항이 필요합니다:
config.assets.enabled = true
config.assets.version = "1.0"
Asset Pipeline을 활성화하거나 비활성화합니다. 기본값은 true 입니다. version 설정은 asset이 만료되도록 강제하기 위해 모든 asset URL의 suffix로 사용되는 문자열입니다.
만약 애플리케이션이 리소스로 "/assets" 라우트를 사용하고 있다면, 충돌을 피하기 위해 assets에 사용되는 prefix를 변경할 수 있습니다:
# 기본값은 '/assets'
config.assets.prefix = "/asset-files"
16.3 config/environments/development.rb
RJS 설정인 config.action_view.debug_rjs = true
를 제거하세요.
asset pipeline을 활성화한 경우 다음 설정들을 추가하세요:
# asset을 압축하지 않음
config.assets.compress = false
# asset을 로드하는 라인을 확장함
config.assets.debug = true
16.4 config/environments/production.rb
다시 한번 말씀드리면, 아래의 대부분 변경사항들은 asset pipeline을 위한 것입니다. Asset Pipeline 가이드에서 이것들에 대해 더 자세히 읽어볼 수 있습니다.
JavaScript와 CSS 압축
config.assets.compress = true
미리 컴파일된 asset이 없을 경우 assets pipeline으로 폴백하지 않음
config.assets.compile = false
assets URL에 대한 digest 생성
config.assets.digest = true
기본값은 Rails.root.join("public/assets")
config.assets.manifest = YOUR_PATH
추가 assets 미리 컴파일 (application.js, application.css 및 모든 JS/CSS가 아닌 파일들은 이미 추가됨)
config.assets.precompile += %w( admin.js admin.css )
SSL을 통한 앱 접근 강제, Strict-Transport-Security 사용, 보안 쿠키 사용
config.force_ssl = true
16.5 config/environments/test.rb
테스트 환경에 다음 내용을 추가하여 성능 테스트에 도움을 받을 수 있습니다:
# 성능을 위한 Cache-Control과 함께 테스트용 static asset 서버 설정
config.public_file_server.enabled = true
config.public_file_server.headers = {
"Cache-Control" => "public, max-age=3600"
}
16.6 config/initializers/wrap_parameters.rb
매개변수를 중첩된 hash로 래핑하려면 다음 내용으로 이 파일을 추가하세요. 새로운 애플리케이션에서는 이것이 기본적으로 활성화되어 있습니다.
# 이 파일을 수정한 후에는 서버를 재시작하세요.
# 이 파일에는 기본적으로 활성화되어 있는 ActionController::ParamsWrapper의
# 설정이 포함되어 있습니다.
# JSON용 parameter wrapping을 활성화합니다. :format을 빈 배열로 설정하여 비활성화할 수 있습니다.
ActiveSupport.on_load(:action_controller) do
wrap_parameters format: [:json]
end
# 기본적으로 JSON의 root element를 비활성화합니다.
ActiveSupport.on_load(:active_record) do
self.include_root_in_json = false
end
16.7 config/initializers/session_store.rb
session key를 새로운 것으로 변경하거나 모든 session을 제거해야 합니다:
# in config/initializers/session_store.rb
AppName::Application.config.session_store :cookie_store, key: "SOMETHINGNEW"
"or"은 대안이나 선택을 나타내는 "또는"이라고 번역됩니다.
$ bin/rake db:sessions:clear
16.8 뷰에서 asset helper 참조의 :cache와 :concat 옵션 제거하기
- Asset Pipeline을 사용하면서 :cache와 :concat 옵션은 더 이상 사용되지 않으므로, 뷰에서 이러한 옵션들을 삭제하세요.