rubyonrails.org에서 더 보기:

GitHub에서 이 파일을 읽지 마세요. 가이드는 https://guides.rubyonrails.org 에서 제공됩니다.

Ruby on Rails 3.0 릴리스 노트

Rails 3.0은 귀여운 조랑말과 무지개입니다! 저녁을 요리해주고 빨래를 개줄 거예요. Rails 3.0이 오기 전의 삶이 어떻게 가능했는지 의문이 들 것입니다. 지금까지 만든 Rails 버전 중 최고입니다!

하지만 진지하게 말하자면, 정말 좋은 것들이 많습니다. Merb 팀이 합류하면서 가져온 모든 좋은 아이디어들이 있습니다. 프레임워크 불가지론, 더 슬림하고 빠른 내부 구조, 그리고 맛있는 API들을 가져왔죠. Merb 1.x에서 Rails 3.0으로 오신다면, 많은 부분이 익숙할 것입니다. Rails 2.x에서 오시는 분들도 좋아하실 겁니다.

우리의 내부 정리에 관심이 없더라도, Rails 3.0은 여러분을 기쁘게 할 것입니다. 새로운 기능들과 개선된 API들이 많이 있습니다. Rails 개발자가 되기에 이보다 더 좋은 시기는 없었습니다. 주요 하이라이트는 다음과 같습니다:

  • RESTful 선언에 중점을 둔 완전히 새로운 router
  • Action Controller를 모델로 한 새로운 Action Mailer API (이제 multipart 메시지 전송의 고통 없이!)
  • 관계 대수를 기반으로 구축된 새로운 Active Record 체인형 쿼리 언어
  • Prototype, jQuery 등을 위한 드라이버가 있는 비침투적 JavaScript 헬퍼 (인라인 JS의 종말)
  • Bundler를 통한 명시적 의존성 관리

이 모든 것 위에, 우리는 친절한 경고와 함께 이전 API들을 deprecate하려 노력했습니다. 즉, 최신 모범 사례에 맞춰 모든 오래된 코드를 즉시 다시 작성할 필요 없이 기존 애플리케이션을 Rails 3로 이전할 수 있습니다.

이 릴리스 노트는 주요 업그레이드를 다루지만, 모든 작은 버그 수정과 변경 사항을 포함하지는 않습니다. Rails 3.0은 250명 이상의 작성자가 작성한 거의 4,000개의 commit으로 구성되어 있습니다! 모든 것을 보고 싶다면, GitHub의 메인 Rails 저장소에 있는 commit 목록을 확인하세요.

Rails 3 설치 방법:

# 설정에 sudo가 필요한 경우 sudo를 사용하세요
$ gem install rails

1 Rails 3로 업그레이드하기

기존 애플리케이션을 업그레이드하는 경우, 업그레이드 전에 충분한 test coverage를 확보하는 것이 좋습니다. 또한 Rails 3로 업그레이드하기 전에 먼저 Rails 2.3.5로 업그레이드하고 애플리케이션이 예상대로 작동하는지 확인해야 합니다. 그런 다음 다음과 같은 변경 사항에 주의를 기울이세요:

1.1 Rails 3는 최소 Ruby 1.8.7이 필요합니다

Rails 3.0은 Ruby 1.8.7 이상이 필요합니다. 이전 Ruby 버전들에 대한 지원은 공식적으로 중단되었으며, 가능한 한 빨리 업그레이드해야 합니다. Rails 3.0은 Ruby 1.9.2와도 호환됩니다.

Ruby 1.8.7 p248과 p249에는 Rails 3.0을 중단시키는 marshalling 버그가 있다는 점에 유의하세요. 하지만 Ruby Enterprise Edition은 1.8.7-2010.02 릴리스부터 이 문제가 수정되었습니다. 1.9 계열에서는 Ruby 1.9.1이 Rails 3.0에서 segfault를 일으키기 때문에 사용할 수 없으므로, Rails 3을 1.9.x와 함께 사용하고 싶다면 원활한 사용을 위해 1.9.2를 선택하세요.

1.2 Rails Application 객체

동일한 프로세스에서 여러 Rails 어플리케이션을 실행하기 위한 기반 작업의 일환으로, Rails 3는 Application 객체의 개념을 도입했습니다. Application 객체는 어플리케이션별 설정을 모두 보유하고 있으며, 이전 Rails 버전의 config/environment.rb와 매우 유사한 성격을 가지고 있습니다.

이제 각 Rails 어플리케이션은 반드시 해당하는 application 객체를 가져야 합니다. application 객체는 config/application.rb에 정의됩니다. 기존 어플리케이션을 Rails 3로 업그레이드하는 경우, 이 파일을 추가하고 config/environment.rb에서 적절한 설정들을 config/application.rb로 이동해야 합니다.

1.3 script/* 가 script/rails로 대체되었습니다

새로운 script/railsscript 디렉토리에 있던 모든 스크립트들을 대체합니다. 하지만 script/rails를 직접 실행하지는 않습니다. rails 명령어가 Rails 애플리케이션의 루트에서 실행되고 있음을 감지하고 스크립트를 대신 실행합니다. 의도된 사용법은 다음과 같습니다:

$ rails console                      # script/console 대신
$ rails g scaffold post title:string # script/generate scaffold post title:string 대신

Rails의 모든 옵션 목록을 보려면 rails --help를 실행하세요.

1.4 Dependencies와 config.gem

config.gem 메소드는 더 이상 사용되지 않으며 bundlerGemfile을 사용하는 것으로 대체되었습니다. 아래의 Vendoring Gems를 참조하세요.

1.5 업그레이드 과정

업그레이드 과정을 돕기 위해 Rails Upgrade라는 plugin이 생성되어 일부 과정을 자동화할 수 있습니다.

plugin을 설치한 다음 rake rails:upgrade:check를 실행하여 앱에서 업데이트가 필요한 부분을 확인할 수 있습니다(업데이트 방법에 대한 정보 링크 포함). 또한 현재 config.gem 호출을 기반으로 Gemfile을 생성하는 task와 현재 routes 파일에서 새로운 routes 파일을 생성하는 task도 제공합니다. plugin을 설치하려면 다음을 실행하세요:

$ ruby script/plugin install git://github.com/rails/rails_upgrade.git

Rails Upgrade가 공식 플러그인이 된 것에 대한 예시는 Rails Upgrade is now an Official Plugin에서 확인할 수 있습니다.

Rails Upgrade 도구 외에도 더 많은 도움이 필요하다면, IRC와 rubyonrails-talk에서 비슷한 작업을 하고 있고 아마도 같은 문제에 부딪히고 있는 사람들이 있을 것입니다. 다른 사람들이 여러분의 지식을 통해 도움을 받을 수 있도록 업그레이드 경험을 블로그에 공유하는 것을 잊지 마세요!

2 Rails 3.0 애플리케이션 생성하기

# 'rails' RubyGem이 설치되어 있어야 합니다
$ rails new myapp
$ cd myapp

2.1 Gem 벤더링

Rails는 이제 애플리케이션 루트에 있는 Gemfile을 사용하여 애플리케이션을 시작하는 데 필요한 gem들을 결정합니다. 이 GemfileBundler에 의해 처리되며, Bundler는 모든 의존성을 설치합니다. 시스템 gem에 의존하지 않도록 모든 의존성을 애플리케이션에 로컬로 설치할 수도 있습니다.

추가 정보: - bundler 홈페이지

2.2 Edge 버전 사용하기

BundlerGemfile은 새로운 전용 bundle 명령어를 통해 Rails 애플리케이션을 쉽게 프리징할 수 있게 해주므로, rake freeze는 더 이상 관련이 없어져 제거되었습니다.

Git 저장소에서 직접 번들링하고 싶다면, --edge 플래그를 전달할 수 있습니다:

$ rails new myapp --edge

Rails repository를 로컬에 체크아웃해두고 이를 사용해 애플리케이션을 생성하고 싶다면, --dev 플래그를 전달하면 됩니다:

$ ruby /path/to/rails/bin/rails new myapp --dev

3 Rails 아키텍처의 변경사항

Rails의 아키텍처에는 6가지 주요 변경사항이 있습니다.

3.1 Railties 재구성

Railties는 전체 Rails 프레임워크에 일관된 plugin API를 제공하고 generator와 Rails binding을 완전히 재작성하도록 업데이트되었습니다. 그 결과로 개발자들은 이제 일관되고 정의된 방식으로 generator와 애플리케이션 프레임워크의 모든 중요한 단계에 연결할 수 있게 되었습니다.

3.2 모든 Rails 핵심 컴포넌트가 분리되어 있습니다

Merb와 Rails의 통합으로, 가장 큰 작업 중 하나는 Rails 핵심 컴포넌트 간의 강한 결합을 제거하는 것이었습니다. 이제 이것이 달성되었고, 모든 Rails 핵심 컴포넌트는 plugin 개발에 사용할 수 있는 동일한 API를 사용하고 있습니다. 이는 여러분이 만드는 모든 plugin이나 핵심 컴포넌트 대체제(DataMapper나 Sequel과 같은)가 Rails 핵심 컴포넌트가 접근할 수 있는 모든 기능에 접근할 수 있으며, 원하는 대로 확장하고 개선할 수 있다는 것을 의미합니다.

더 많은 정보: - The Great Decoupling

3.3 Active Model 추상화

핵심 컴포넌트들의 분리 작업 중 하나로 Action Pack에서 Active Record와의 모든 연결을 추출하는 것이었습니다. 이 작업은 이제 완료되었습니다. 이제 모든 새로운 ORM 플러그인은 Action Pack과 원활하게 작동하기 위해 Active Model 인터페이스만 구현하면 됩니다.

더 많은 정보: - Make Any Ruby Object Feel Like ActiveRecord

3.4 Controller 추상화

핵심 컴포넌트들을 분리하는 과정에서 중요한 부분 중 하나는 view 렌더링 등을 처리하기 위해 HTTP 개념과 분리된 기본 상위 클래스를 만드는 것이었습니다. 이렇게 생성된 AbstractController는 모든 라이브러리에서 공통 코드를 제거하고 Abstract Controller에 넣음으로써 ActionControllerActionMailer를 크게 단순화할 수 있게 해주었습니다.

추가 정보: - Rails Edge Architecture

3.5 Arel 통합

Arel(또는 Active Relation)은 Active Record의 기반으로 채택되었으며 이제 Rails에서 필수적입니다. Arel은 Active Record를 단순화하고 Active Record의 relation 기능을 위한 기반을 제공하는 SQL 추상화를 제공합니다.

더 많은 정보: - Why I wrote Arel

3.6 Mail Extraction

Action Mailer는 시작부터 TMail을 소스 트리에 포함시키는 것 외에도 monkey patch, pre parser, delivery/receiver agent 등을 가지고 있었습니다. 버전 3에서는 모든 이메일 메시지 관련 기능을 Mail gem으로 추출하여 변경했습니다. 이는 코드 중복을 줄이고 Action Mailer와 이메일 파서 간의 명확한 경계를 만드는데 도움이 됩니다.

추가 정보: - New Action Mailer API in Rails 3

4 Documentation

Rails 트리의 문서는 모든 API 변경 사항과 함께 업데이트되고 있으며, Rails Edge Guides도 Rails 3.0의 변경 사항을 반영하여 하나씩 업데이트되고 있습니다. 하지만 guides.rubyonrails.org는 계속해서 Rails의 안정 버전만 포함할 것입니다(현재는 3.0이 출시될 때까지 버전 2.3.5).

추가 정보: - Rails Documentation Projects

5 Internationalization

Rails 3에서는 최신 I18n gem이 제공하는 많은 속도 개선을 포함하여 I18n 지원에 많은 작업이 이루어졌습니다.

  • 모든 객체에 대한 I18n - ActiveModel::TranslationActiveModel::Validations를 포함하여 어떤 객체에도 I18n 동작을 추가할 수 있습니다. 또한 번역을 위한 errors.messages 폴백도 있습니다.
  • 속성에 기본 번역을 가질 수 있습니다.
  • Form Submit Tag는 객체 상태에 따라 자동으로 올바른 상태(Create 또는 Update)를 가져오고, 그에 따른 올바른 번역을 가져옵니다.
  • I18n이 있는 Label도 이제 속성 이름만 전달하면 작동합니다.

추가 정보: - Rails 3 I18n changes

6 Railties

주요 Rails 프레임워크의 분리로 인해 Railties는 프레임워크, engine 또는 plugin을 가능한 한 쉽고 확장 가능하게 연결할 수 있도록 대대적인 개편을 했습니다:

  • 각 애플리케이션은 이제 자체 네임스페이스를 가지며, 예를 들어 YourAppName.boot로 애플리케이션이 시작되어 다른 애플리케이션과의 상호 작용이 훨씬 쉬워졌습니다.
  • Rails.root/app 아래의 모든 것이 이제 load path에 추가되어, app/observers/user_observer.rb를 만들면 Rails가 수정 없이 로드합니다.
  • Rails 3.0은 이제 모든 종류의 Rails 전반의 설정 옵션에 대한 중앙 저장소를 제공하는 Rails.config 객체를 제공합니다.

    애플리케이션 생성에 test-unit, Active Record, Prototype, Git의 설치를 건너뛸 수 있는 추가 플래그가 추가되었습니다. 또한 새로운 --dev 플래그가 추가되어 Gemfile이 Rails checkout을 가리키도록 애플리케이션을 설정합니다(rails 바이너리의 경로로 결정됨). 자세한 내용은 rails --help를 참조하세요.

Railties generator는 Rails 3.0에서 많은 주목을 받았으며, 기본적으로:

  • Generator가 완전히 다시 작성되어 이전 버전과 호환되지 않습니다.
  • Rails template API와 generator API가 병합되었습니다(이전의 것과 동일).
  • Generator는 더 이상 특별한 경로에서 로드되지 않고 Ruby load path에서 찾습니다. 따라서 rails generate foogenerators/foo_generator를 찾습니다.
  • 새로운 generator는 hook을 제공하므로 모든 템플릿 엔진, ORM, 테스트 프레임워크가 쉽게 연결될 수 있습니다.
  • 새로운 generator를 사용하면 Rails.root/lib/templates에 복사본을 배치하여 템플릿을 재정의할 수 있습니다.
  • Rails::Generators::TestCase도 제공되어 자신만의 generator를 만들고 테스트할 수 있습니다.

또한, Railties generator가 생성한 view도 개편되었습니다:

  • Views는 이제 p 태그 대신 div 태그를 사용합니다.
  • 이제 scaffold에서는 edit과 new view에서 중복된 코드 대신 _form partial을 사용합니다.
  • Scaffold form은 이제 f.submit을 사용하며, 전달된 객체의 상태에 따라 "Create ModelName" 또는 "Update ModelName"을 반환합니다.

마지막으로 rake task에 몇 가지 개선 사항이 추가되었습니다:

  • rake db:forward가 추가되어 migration을 개별적으로 또는 그룹으로 진행할 수 있게 됐습니다.
  • rake routes CONTROLLER=x가 추가되어 하나의 controller에 대한 routes만 볼 수 있게 됐습니다.

Railties는 이제 다음 사항들을 deprecate합니다:

  • RAILS_ROOT 대신 Rails.root
  • RAILS_ENV 대신 Rails.env
  • RAILS_DEFAULT_LOGGER 대신 Rails.logger

PLUGIN/rails/tasksPLUGIN/tasks는 더 이상 로드되지 않으며, 이제 모든 task는 PLUGIN/lib/tasks에 있어야 합니다.

자세한 정보:

7 Action Pack

Action Pack에는 내부적으로나 외부적으로 중요한 변화가 있었습니다.

7.1 Abstract Controller

Abstract Controller는 Action Controller의 일반적인 부분을 재사용 가능한 모듈로 추출하여, 어떤 라이브러리든 template 렌더링, partial 렌더링, helper, 번역, 로깅, 요청-응답 사이클의 모든 부분을 사용할 수 있게 합니다. 이러한 추상화 덕분에 ActionMailer::Base는 이제 AbstractController를 상속받아 Mail gem에 Rails DSL을 감싸기만 하면 됩니다.

또한 이는 Action Controller를 정리할 기회를 제공하여, 코드를 단순화하기 위해 추상화할 수 있는 것들을 추출했습니다.

하지만 Abstract Controller는 사용자가 직접 다루는 API가 아니며, Rails를 일상적으로 사용하면서 마주치게 되지는 않을 것입니다.

더 자세한 정보: - Rails Edge Architecture

7.2 Action Controller

  • application_controller.rb는 이제 기본적으로 protect_from_forgery가 활성화되어 있습니다.
  • cookie_verifier_secret는 더 이상 사용되지 않으며, 대신 Rails.application.config.cookie_secret을 통해 할당되고 별도의 파일인 config/initializers/cookie_verification_secret.rb로 이동되었습니다.
  • session_store는 이전에 ActionController::Base.session에서 구성되었으나, 이제 Rails.application.config.session_store로 이동되었습니다. 기본 설정은 config/initializers/session_store.rb에서 이루어집니다.
  • cookies.secure를 사용하면 cookie.secure[:key] => value로 쿠키에 암호화된 값을 설정할 수 있습니다.
  • cookies.permanent를 사용하면 cookie.permanent[:key] => value로 쿠키 해시에 영구적인 값을 설정할 수 있으며, 검증 실패 시 서명된 값에 대해 예외가 발생합니다.
  • 이제 respond_to 블록 내의 format 호출에 :notice => 'This is a flash message' 또는 :alert => 'Something went wrong'를 전달할 수 있습니다. flash[] 해시는 이전과 동일하게 작동합니다.
  • respond_with 메서드가 컨트롤러에 추가되어 기존의 format 블록을 단순화했습니다.
  • ActionController::Responder가 추가되어 응답 생성 방식에 더 많은 유연성을 제공합니다.

사용 중단:

  • filter_parameter_loggingconfig.filter_parameters << :password 사용을 권장하며 더 이상 사용되지 않습니다.

추가 정보:

7.3 Action Dispatch

Action Dispatch는 Rails 3.0에서 새롭게 도입되었으며, 라우팅을 위한 새롭고 깔끔한 구현을 제공합니다.

  • 라우터의 대대적인 정리와 재작성이 이루어졌으며, Rails 라우터는 이제 Rails DSL이 탑재된 rack_mount입니다. 이는 독립형 소프트웨어입니다.
  • 각 애플리케이션에서 정의된 라우트들은 이제 Application 모듈 내에서 네임스페이스화 되었습니다. 예를 들면:

    # 이전 방식:
    
    ActionController::Routing::Routes.draw do |map|
      map.resources :posts
    end
    
    # 새로운 방식:
    
    AppName::Application.routes do
      resources :posts
    end
    
  • 라우터에 match 메소드가 추가되었으며, 매칭된 라우트에 모든 Rack 애플리케이션을 전달할 수 있습니다.

  • 라우터에 constraints 메소드가 추가되어, 정의된 제약 조건으로 라우터를 보호할 수 있습니다.

  • 라우터에 scope 메소드가 추가되어, 다른 언어나 다른 액션에 대한 라우트를 네임스페이스화할 수 있습니다. 예를 들면:

    scope 'es' do
      resources :projects, :path_names => { :edit => 'cambiar' }, :path => 'proyecto'
    end
    
    # edit 액션에 대해 /es/proyecto/1/cambiar를 제공합니다
    
  • match '/', :to => path의 단축어로 라우터에 root 메소드가 추가되었습니다.

  • match에 선택적 세그먼트를 전달할 수 있습니다. 예를 들어 match "/:controller(/:action(/:id))(.:format)"에서 괄호로 묶인 각 세그먼트는 선택사항입니다.

  • 라우트는 블록을 통해 표현될 수 있습니다. 예를 들어 controller :home { match '/:action' }를 호출할 수 있습니다.

참고. 이전 스타일의 map 명령은 하위 호환성 레이어를 통해 여전히 작동하지만, 3.1 릴리스에서는 제거될 예정입니다.

지원 중단

  • non-REST 애플리케이션을 위한 catch all 라우트(/:controller/:action/:id)는 이제 주석 처리되었습니다.
  • 라우트의 :path_prefix는 더 이상 존재하지 않으며, :name_prefix는 이제 주어진 값 끝에 자동으로 "_"를 추가합니다.

추가 정보: * The Rails 3 Router: Rack it Up * Revamped Routes in Rails 3 * Generic Actions in Rails 3

7.4 Action View

7.4.1 Unobtrusive JavaScript

Action View 헬퍼들에 대한 주요 재작성이 이루어졌으며, Unobtrusive JavaScript(UJS) 훅을 구현하고 기존의 인라인 AJAX 명령을 제거했습니다. 이를 통해 Rails는 헬퍼에서 UJS 훅을 구현하기 위해 호환되는 모든 UJS 드라이버를 사용할 수 있게 되었습니다.

이는 이전의 모든 remote_<method> 헬퍼들이 Rails 코어에서 제거되어 Prototype Legacy Helper로 이동되었다는 것을 의미합니다. 이제 HTML에 UJS 훅을 추가하려면 :remote => true를 전달하면 됩니다. 예를 들면:

위 코드에서 :remote => true는 form 이 AJAX를 통해 제출되도록 합니다.

Produces:

생성물:

<form action="http://host.com" id="create-post" method="post" data-remote="true">

위 폼은 데이터를 GET이나 POST로 제출할 때 일반적인 submit 대신 Ajax 요청을 보냅니다.

7.4.2 블록이 있는 Helpers

form_for 또는 div_for와 같이 블록의 내용을 삽입하는 helper는 이제 <%=를 사용합니다.

<%= form_for @post do |f| %>
  ...
<% end %>

이러한 종류의 자체 helper는 수동으로 출력 버퍼에 추가하는 대신 문자열을 반환해야 합니다.

cache 또는 content_for와 같이 다른 작업을 수행하는 helper는 이 변경의 영향을 받지 않으며, 이전과 같이 &lt;%가 필요합니다.

7.4.3 기타 변경사항

  • 이제 모든 view 템플릿에서 HTML 출력이 기본적으로 escape 처리되므로 h(string)을 호출할 필요가 없습니다. escape되지 않은 문자열을 원한다면 raw(string)을 호출하세요.
  • Helper는 이제 기본적으로 HTML5를 출력합니다.
  • Form label helper는 이제 단일 값으로 I18n에서 값을 가져오므로, f.label :name:name 번역을 가져옵니다.
  • I18n select label은 이제 :en.support.select 대신 :en.helpers.select여야 합니다.
  • ERB 템플릿 내의 Ruby 보간법 끝에 HTML 출력의 후행 캐리지 리턴을 제거하기 위해 마이너스 기호를 배치할 필요가 없습니다.
  • Action View에 grouped_collection_select helper가 추가되었습니다.
  • content_for?가 추가되어 렌더링하기 전에 view에서 콘텐츠의 존재 여부를 확인할 수 있습니다.
  • form helper에 :value => nil을 전달하면 기본값을 사용하는 대신 필드의 value 속성을 nil로 설정합니다
  • form helper에 :id => nil을 전달하면 해당 필드가 id 속성 없이 렌더링됩니다
  • image_tag:alt => nil을 전달하면 img 태그가 alt 속성 없이 렌더링됩니다

8 Active Model

Active Model은 Rails 3.0에서 새롭게 도입되었습니다. Active Model 인터페이스를 구현하여 Rails와 상호 작용하기 위해 ORM 라이브러리가 사용할 수 있는 추상화 계층을 제공합니다.

8.1 ORM 추상화와 Action Pack 인터페이스

핵심 컴포넌트들의 분리 작업의 일환으로 Action Pack에서 Active Record와의 모든 연결을 분리했습니다. 이 작업은 현재 완료되었습니다. 이제 모든 새로운 ORM 플러그인은 Action Pack과 원활하게 작동하기 위해 Active Model 인터페이스만 구현하면 됩니다.

추가 정보: - Ruby 객체를 ActiveRecord처럼 동작하게 만들기

8.2 Validations

Validation들은 Active Record에서 Active Model로 이동되어 Rails 3에서 ORM 라이브러리 전반에 걸쳐 작동하는 validation 인터페이스를 제공합니다.

  • 이제 모든 validates 클래스 메소드에 대한 옵션을 전달할 수 있는 validates :attribute, options_hash 단축 메소드가 있으며, validate 메소드에 여러 옵션을 전달할 수 있습니다.
  • validates 메소드는 다음과 같은 옵션들을 가집니다:
    • :acceptance => Boolean.
    • :confirmation => Boolean.
    • :exclusion => { :in => Enumerable }.
    • :inclusion => { :in => Enumerable }.
    • :format => { :with => Regexp, :on => :create }.
    • :length => { :maximum => Fixnum }.
    • :numericality => Boolean.
    • :presence => Boolean.
    • :uniqueness => Boolean.

Rails 버전 2.3 스타일의 모든 validation 메소드들은 Rails 3.0에서도 여전히 지원됩니다. 새로운 validates 메소드는 기존 API를 대체하는 것이 아니라 모델 validation을 추가적으로 돕기 위해 설계되었습니다.

또한 validator 객체를 전달할 수 있으며, 이를 Active Model을 사용하는 객체들 사이에서 재사용할 수 있습니다:

class TitleValidator < ActiveModel::EachValidator
  Titles = ['Mr.', 'Mrs.', 'Dr.']
  def validate_each(record, attribute, value)
    unless Titles.include?(value)
      record.errors[attribute] << '유효한 호칭이어야 합니다'
    end
  end
end
class Person
  include ActiveModel::Validations
  attr_accessor :title
  validates :title, :presence => true, :title => true
end

# 또는 Active Record인 경우

class Person < ActiveRecord::Base
  validates :title, :presence => true, :title => true 
end

introspection도 지원합니다:

User의 모든 validator를 가져옵니다
User의 :login 속성에 대한 validator를 가져옵니다

추가 정보:

9 Active Record

Rails 3.0에서 Active Record는 많은 관심을 받았습니다. Active Model로의 추상화, Arel을 사용한 Query 인터페이스의 전면 업데이트, validation 업데이트, 그리고 많은 개선 및 수정이 포함되었습니다. Rails 2.x API는 버전 3.1까지 지원될 호환성 레이어를 통해 모두 사용할 수 있습니다.

9.1 Query Interface

Active Record는 Arel을 통해 이제 핵심 메서드에서 relation을 반환합니다. Rails 2.3.x의 기존 API는 여전히 지원되며 Rails 3.1까지는 deprecate되지 않고 Rails 3.2까지는 제거되지 않을 것입니다. 하지만 새로운 API는 모두 relation을 반환하여 서로 연결할 수 있는 다음과 같은 새로운 메서드를 제공합니다:

  • where - relation에 조건을 제공하여 반환될 내용을 결정합니다.
  • select - 데이터베이스에서 반환받고자 하는 모델의 속성을 선택합니다.
  • group - 제공된 속성으로 relation을 그룹화합니다.
  • having - 그룹 relation을 제한하는 표현식을 제공합니다(GROUP BY 제약조건).
  • joins - relation을 다른 테이블과 조인합니다.
  • clause - 조인 relation을 제한하는 표현식을 제공합니다(JOIN 제약조건).
  • includes - 다른 relation을 미리 로드하여 포함합니다.
  • order - 제공된 표현식을 기반으로 relation을 정렬합니다.
  • limit - relation을 지정된 레코드 수로 제한합니다.
  • lock - 테이블에서 반환된 레코드를 잠급니다.
  • readonly - 데이터의 읽기 전용 복사본을 반환합니다.
  • from - 둘 이상의 테이블에서 관계를 선택하는 방법을 제공합니다.
  • scope - (이전의 named_scope) relation을 반환하고 다른 relation 메서드와 연결될 수 있습니다.
  • with_scope - 그리고 with_exclusive_scope도 이제 relation을 반환하므로 연결될 수 있습니다.
  • default_scope - 또한 relation과 함께 작동합니다.

더 자세한 정보:

9.2 개선사항

  • Active Record 객체에 :destroyed?가 추가되었습니다.
  • Active Record 관계에 :inverse_of가 추가되어 데이터베이스에 접근하지 않고도 이미 로드된 관계의 인스턴스를 가져올 수 있게 되었습니다.

9.3 패치와 Deprecation

또한, Active Record 브랜치에서 많은 수정사항이 있었습니다:

  • SQLite 2 지원이 중단되고 SQLite 3으로 대체되었습니다.
  • MySQL의 컬럼 순서 지원.
  • PostgreSQL adapter의 TIME ZONE 지원이 수정되어 더 이상 잘못된 값을 삽입하지 않습니다.
  • PostgreSQL의 테이블 이름에서 다중 스키마 지원.
  • PostgreSQL의 XML 데이터 타입 컬럼 지원.
  • table_name이 이제 캐시됩니다.
  • Oracle adapter에서도 많은 버그 수정과 함께 대규모 작업이 수행되었습니다.

다음과 같은 deprecation도 있습니다:

  • Active Record 클래스의 named_scope는 deprecated 되었으며 단순히 scope로 이름이 변경되었습니다.
  • scope 메소드에서는 :conditions => {} finder 메소드 대신 relation 메소드를 사용해야 합니다. 예: scope :since, lambda {|time| where("created_at > ?", time) }
  • save(false)는 deprecated 되었으며, save(:validate => false)를 사용해야 합니다.
  • Active Record를 위한 I18n 오류 메시지는 :en.activerecord.errors.template에서 :en.errors.template로 변경되어야 합니다.
  • model.errors.on은 deprecated 되었으며 model.errors[]를 사용해야 합니다.
  • validates_presence_of => validates... :presence => true
  • ActiveRecord::Base.colorize_loggingconfig.active_record.colorize_logging은 deprecated 되었으며 Rails::LogSubscriber.colorize_logging 또는 config.colorize_logging을 사용해야 합니다.

State Machine 구현이 몇 달 동안 Active Record edge에 있었지만, Rails 3.0 릴리스에서는 제거되었습니다.

10 Active Resource

Active Resource도 Active Model로 추출되어 Action Pack과 함께 Active Resource 객체를 원활하게 사용할 수 있게 되었습니다.

  • Active Model을 통한 validation 추가.
  • 관찰 훅 추가.
  • HTTP 프록시 지원.
  • digest 인증 지원 추가.
  • 모델 네이밍을 Active Model로 이동.
  • Active Resource 속성을 인디퍼런트 액세스가 가능한 Hash로 변경.
  • first, last, all 별칭을 동등한 find scope에 추가.
  • find_every는 이제 아무것도 반환되지 않을 때 ResourceNotFound 오류를 반환하지 않습니다.
  • 객체가 valid?하지 않으면 ResourceInvalid를 발생시키는 save! 추가.
  • update_attributeupdate_attributes가 Active Resource 모델에 추가되었습니다.
  • exists? 추가.
  • SchemaDefinitionSchema로, define_schemaschema로 이름 변경.
  • 원격 오류를 로드하기 위해 content-type 대신 Active Resources의 format 사용.
  • schema 블록에 instance_eval 사용.
  • @response가 #code나 #message에 응답하지 않을 때 ActiveResource::ConnectionError#to_s 수정, Ruby 1.9 호환성 처리.
  • JSON 형식의 오류 지원 추가.
  • load가 숫자 배열에서 작동하도록 보장.
  • 원격 리소스가 삭제되었을 때 410 응답을 인식.
  • Active Resource 연결에서 SSL 옵션을 설정하는 기능 추가.
  • 연결 타임아웃 설정이 Net::HTTP open_timeout에도 영향을 미침.

Deprecations:

  • save(false)save(:validate => false)를 선호하여 deprecated 되었습니다.
  • Ruby 1.9.2: URI.parse.decode는 deprecated 되었고 더 이상 라이브러리에서 사용되지 않습니다.

11 Active Support

Active Support에서는 cherry pickable하게 만들기 위한 큰 노력이 있었습니다. 즉, 일부분을 사용하기 위해 전체 Active Support 라이브러리를 require할 필요가 없어졌습니다. 이를 통해 Rails의 다양한 핵심 컴포넌트들이 더 가벼워질 수 있습니다.

Active Support의 주요 변경사항은 다음과 같습니다:

  • 사용되지 않는 메서드들을 제거하는 대대적인 라이브러리 정리.
  • Active Support는 더 이상 TZInfo, Memcache Client, Builder의 vendor 버전을 제공하지 않습니다. 이들은 모두 의존성으로 포함되어 bundle install 명령으로 설치됩니다.
  • Safe buffer가 ActiveSupport::SafeBuffer에 구현되었습니다.
  • Array.uniq_byArray.uniq_by!가 추가되었습니다.
  • Array#rand가 제거되고 Ruby 1.9의 Array#sample이 백포트되었습니다.
  • TimeZone.seconds_to_utc_offset가 잘못된 값을 반환하는 버그가 수정되었습니다.
  • ActiveSupport::Notifications middleware가 추가되었습니다.
  • ActiveSupport.use_standard_json_time_format의 기본값이 true로 변경되었습니다.
  • ActiveSupport.escape_html_entities_in_json의 기본값이 false로 변경되었습니다.
  • Integer#multiple_of?는 0을 인자로 받을 수 있으며, 수신자가 0이 아닌 경우 false를 반환합니다.
  • string.charsstring.mb_chars로 이름이 변경되었습니다.
  • ActiveSupport::OrderedHash가 이제 YAML을 통한 역직렬화가 가능합니다.
  • LibXML과 Nokogiri를 사용하는 XmlMini용 SAX 기반 파서가 추가되었습니다.
  • 객체가 #present?한 경우 해당 객체를, 그렇지 않으면 nil을 반환하는 Object#presence가 추가되었습니다.
  • #include?의 반대를 반환하는 String#exclude? core extension이 추가되었습니다.
  • DateTime 속성을 가진 모델에서 to_yaml이 올바르게 작동하도록 Active Support의 DateTimeto_i가 추가되었습니다.
  • Enumerable#include?와의 일관성을 위해 Enumerable#exclude?가 추가되어 if !x.include?를 피할 수 있게 되었습니다.
  • Rails에서 XSS 이스케이핑이 기본적으로 활성화되도록 변경되었습니다.
  • ActiveSupport::HashWithIndifferentAccess에서 deep-merging을 지원합니다.
  • Enumerable#sum이 이제 :size에 응답하지 않는 경우에도 모든 enumerable에서 작동합니다.
  • 길이가 0인 duration의 inspect가 빈 문자열 대신 '0 seconds'를 반환합니다.
  • ModelNameelementcollection이 추가되었습니다.
  • String#to_timeString#to_datetime이 소수점 초를 처리합니다.
  • before와 after 콜백에서 사용되는 :before:after에 응답하는 around filter 객체에 대한 새로운 콜백 지원이 추가되었습니다.
  • ActiveSupport::OrderedHash#to_a 메서드가 정렬된 배열 세트를 반환합니다. Ruby 1.9의 Hash#to_a와 일치합니다.
  • MissingSourceFile는 상수로 존재하지만 이제 LoadError와 동일합니다.
  • 하위 클래스에서 상속 가능하고 덮어쓸 수 있는 클래스 레벨 속성을 선언할 수 있는 Class#class_attribute가 추가되었습니다.
  • ActiveRecord::Associations에서 DeprecatedCallbacks가 최종적으로 제거되었습니다.
  • Object#metaclass가 이제 Ruby와 일치하도록 Kernel#singleton_class로 변경되었습니다.

다음 메서드들은 Ruby 1.8.7과 1.9에서 사용 가능하기 때문에 제거되었습니다:

  • Integer#even?Integer#odd?
  • String#each_char
  • String#start_with?String#end_with? (3인칭 별칭은 유지됨)
  • String#bytesize

  • Object#tap

  • Symbol#to_proc

  • Object#instance_variable_defined?

  • Enumerable#none?

Ruby 1.8.7의 초기 패치 레벨에서 여전히 필요하기 때문에 REXML에 대한 보안 패치는 Active Support에 남아있습니다. Active Support는 이를 적용해야 하는지 여부를 알고 있습니다.

다음 메서드들은 프레임워크에서 더 이상 사용되지 않아 제거되었습니다:

  • Kernel#daemonize
  • Object#remove_subclasses_of Object#extend_with_included_modules_from, Object#extended_by
  • Class#remove_class
  • Regexp#number_of_captures, Regexp.unoptionalize, Regexp.optionalize, Regexp#number_of_captures

12 Action Mailer

Action Mailer는 이메일 라이브러리로 TMail을 새로운 Mail로 교체하면서 새로운 API를 받았습니다. Action Mailer 자체가 거의 완전히 다시 작성되었으며 거의 모든 코드가 수정되었습니다. 그 결과 Action Mailer는 이제 Abstract Controller를 상속받고 Mail gem을 Rails DSL로 감싸기만 합니다. 이로 인해 Action Mailer의 코드량과 다른 라이브러리와의 중복이 상당히 줄어들었습니다.

  • 이제 모든 mailer는 기본적으로 app/mailers에 있습니다.
  • 이제 attachments, headers, mail 세 가지 메서드를 사용하는 새로운 API로 이메일을 보낼 수 있습니다.
  • Action Mailer는 이제 attachments.inline 메서드를 사용한 인라인 첨부 파일을 기본적으로 지원합니다.
  • Action Mailer의 이메일 발송 메서드는 이제 Mail::Message 객체를 반환하며, 이 객체에 deliver 메시지를 보내 자신을 전송할 수 있습니다.
  • 모든 전송 메서드는 이제 Mail gem으로 추상화되었습니다.
  • mail 전송 메서드는 모든 유효한 메일 헤더 필드와 그 값 쌍의 해시를 받을 수 있습니다.
  • mail 전송 메서드는 Action Controller의 respond_to와 비슷하게 작동하며, 명시적 또는 암시적으로 템플릿을 렌더링할 수 있습니다. Action Mailer는 필요에 따라 이메일을 멀티파트 이메일로 변환합니다.
  • mail 블록 내의 format.mime_type 호출에 proc을 전달하여 특정 유형의 텍스트를 명시적으로 렌더링하거나, 레이아웃 또는 다른 템플릿을 추가할 수 있습니다. proc 내부의 render 호출은 Abstract Controller에서 가져온 것이며 동일한 옵션을 지원합니다.
  • mailer 단위 테스트였던 것들이 기능 테스트로 이동되었습니다.
  • Action Mailer는 이제 모든 헤더 필드와 본문의 자동 인코딩을 Mail Gem에 위임합니다.
  • Action Mailer가 이메일 본문과 헤더를 자동으로 인코딩합니다.

Deprecations:

  • :charset, :content_type, :mime_version, :implicit_parts_order는 모두 ActionMailer.default :key => value 스타일 선언을 위해 deprecated 되었습니다.
  • Mailer 동적 create_method_namedeliver_method_name은 deprecated 되었습니다. 이제 Mail::Message 객체를 반환하는 method_name만 호출하세요.
  • ActionMailer.deliver(message)는 deprecated 되었습니다. 단순히 message.deliver를 호출하세요.
  • template_root는 deprecated 되었습니다. mail 생성 블록 내의 format.mime_type 메서드에서 proc 내부의 render 호출에 옵션을 전달하세요.
  • 인스턴스 변수를 정의하는 body 메서드(body {:ivar => value})는 deprecated 되었습니다. 메서드에서 직접 인스턴스 변수를 선언하면 뷰에서 사용할 수 있습니다.
  • app/models에 있는 mailer는 deprecated 되었습니다. 대신 app/mailers를 사용하세요.

더 자세한 정보:

13 Credits

Rails에 기여한 모든 분들의 목록을 확인해보세요. Rails 3를 만들기 위해 수많은 시간을 투자한 모든 분들께 감사드립니다.

Rails 3.0 릴리스 노트는 Mikel Lindsaar가 작성했습니다.



맨 위로