
rabl 0.8.6 + CVE-2014-4671 수정
RABL(Ruby API Builder Language)은 JSON, XML, MessagePack, PList 및 BSON을 생성하기 위한 Rails 및 Padrino Ruby 템플릿 시스템입니다. ActiveRecord의 'to_json' 메서드를 사용할 때, API 생성을 위한 더 표현적이고 강력한 솔루션이 필요하다고 느꼈습니다. 이는 특히 JSON 표현이 복잡하거나 데이터베이스에 정의된 정확한 스키마와 일치하지 않을 때 더욱 그렇습니다.
특히, 다음과 같은 기능을 쉽게 사용하고 싶었습니다:
ActiveRecord의 'to_json' 메서드를 사용하여 JSON 응답을 생성해 본 사람이라면 누구나 이 제한적인 접근 방식의 고통을 느껴보았을 것입니다. RABL은 API 응답 생성에 완전히 새로운 접근 방식을 도입하여 이러한 문제를 해결하기 위해 만들어진 일반 템플릿 시스템입니다.
RABL의 핵심은 API 데이터 표현을 애플리케이션의 뷰 계층으로 미루어 MVC 원칙을 준수하는 것입니다. RABL에 대한 일반적인 오해에 대한 설명은 RABL 이해하기 가이드를 확인하시기 바랍니다. 이 가이드는 이 프로젝트에 대한 혼란을 해소하는 데 도움이 될 것입니다.
v0.8.0(2013년 2월 14일 출시)에서는 multi_json 의존성을 제거하고 Oj(또는 JSON)을 json 파서로 사용합니다. 코드를 단순화하고 의존성을 하나 줄였지만 MultiJson에 대한 참조를 제거해야 할 수도 있습니다.
v0.6.14(2012년 6월 28일 출시)에서는 RSpec으로 템플릿을 테스트할 때 render_views 사용이 필요합니다. 그렇지 않으면 컨트롤러는 ERB 템플릿과 마찬가지로 단순히 render 명령을 전달합니다.
RABL을 gem으로 설치하세요:``` gem install rabl
또는 Gemfile에 추가하세요:```ruby
# Gemfile
gem 'rabl'
# Also add either `oj` or `yajl-ruby` as the JSON parser
gem 'oj'
하고 bundle install을 실행하여 의존성을 설치하세요.
Rails 2.3.8 (이상), Rails 3.X 또는 Padrino를 사용하는 경우 RABL은 설정 없이 작동합니다.
중요: Padrino를 사용할 때는 rabl 젬이 Gemfile에서 padrino 젬 뒤에 나열되어 있는지 확인하세요. 그렇지 않으면 Rabl이 템플릿 엔진으로 제대로 등록되지 않습니다.
Sinatra 또는 다른 tilt 기반 프레임워크에서는 간단히 등록하세요:```ruby Rabl.register!
and RABL이 초기화되어 사용할 준비가 됩니다. Sinatra와 함께 사용하려면 [시나트라 사용법](https://github.com/nesquena/rabl/wiki/Setup-for-Sinatra) 가이드를 확인하세요.
## 개요 ##
RABL을 사용하여 모든 Ruby 객체에서 JSON 및 XML 기반 API를 생성할 수 있습니다. RABL을 사용하면 데이터는 일반적으로 주로 모델(ORM에 구애받지 않음)에서 파생되며, API 출력의 표현은 간단한 Ruby DSL을 사용하여 뷰 템플릿 내에서 설명됩니다. 이렇게 하면 원하는 JSON 또는 XML에서 데이터를 분리하여 유지할 수 있습니다.
RABL을 설치한 후(위에서 설명됨) RABL 뷰 템플릿을 구성한 다음 컨트롤러(또는 라우트)에서 Sinatra, Padrino 또는 Rails 애플리케이션에서 템플릿을 매우 쉽게 렌더링할 수 있습니다. [Padrino](http://padrinorb.com)을 예로 들어, 블로그 게시물로 채워진 `Post` 모델이 있다고 가정할 때, 라우트를 생성하여 API 표현(JSON 및 XML 모두)을 렌더링할 수 있습니다.```ruby
# app/app.rb
get "/posts", :provides => [:json, :xml] do
@user = current_user
@posts = Post.order("id DESC")
render "posts/index"
end
그러면 @posts의 API 출력을 표현하기 위해 다음과 같은 RABL 템플릿을 생성할 수 있습니다.```ruby
collection @posts attributes :id, :title, :subject child(:user) { attributes :full_name } node(:read) { |post| post.read_by?(@user) }
다음 JSON 또는 XML을 `http://localhost:3000/posts.json`을 방문할 때 출력합니다.```js
[{ "post" :
{
"id" : 5, title: "...", subject: "...",
"user" : { full_name : "..." },
"read" : true
}
}]
이것은 기본 개요이지만, 부분 템플릿(partials), 상속(inheritance), 사용자 정의 노드(custom nodes) 등 더 많은 내용이 있습니다. 아래에서 RABL의 전체 세부 정보를 읽어보세요.
RABL은 작동을 위해 거의 또는 전혀 구성이 필요하지 않도록 설계되었습니다. 대부분의 시나리오에서 그렇지만, 필요에 따라 애플리케이션에서 다음과 같은 전역 설정을 지정할 수 있습니다 (이 블록은 완전히 선택 사항입니다):```ruby
require 'rabl' Rabl.configure do |config|
end
각 옵션은 RABL 출력과 관련된 동작을 지정합니다. `include_json_root`가 비활성화되면 각 최상위 객체의 루트 노드가 출력에서 제거되며, `enable_json_callbacks`는 들어오는 요청에 'callback' 매개변수가 있는 경우 'jsonp' 스타일 콜백 출력을 지원합니다.
`include_child_root`가 false로 설정되면 응답의 하위 객체는 기본적으로 루트 노드를 포함하지 않습니다. 이를 통해 원하는 응답 구조를 더욱 세밀하게 조정할 수 있습니다.
`cache_engine`이 설정되면 `fetch` 메서드를 가진 클래스에 할당해야 합니다. 예제는 [기본 엔진](https://github.com/nesquena/rabl/blob/master/lib/rabl/cache_engine.rb)을 참조하십시오.
`perform_caching`이 `true`로 설정되면 캐싱을 수행합니다. Rails를 사용하는 경우 이 옵션을 무시해도 됩니다. Rails의 `config.action_controller.perform_caching`과 동일합니다.
`cache_sources`가 `true`로 설정되면 템플릿 조회가 캐시되어 성능이 향상됩니다. 캐시는 애플리케이션 내에서 `Rabl.reset_source_cache!`를 실행하여 수동으로 초기화할 수 있습니다.
`cache_all_output`이 `true`로 설정되면 컬렉션의 일부로 사용되는 각 개별 템플릿을 포함한 모든 템플릿이 별도로 캐시됩니다. 또한 child, glue 및 partial 내의 모든 것도 별도로 캐시됩니다. 단일 템플릿만 캐시하려면 아래 '캐싱' 섹션을 참조하십시오.
`escape_all_output`이 `true`로 설정되고 ActiveSupport를 사용할 수 있는 경우, 속성 출력은 [ERB::Util.html_escape](http://corelib.rubyonrails.org/classes/ERB/Util.html)를 사용하여 이스케이프됩니다. 사용자 정의 노드는 이스케이프되지 않으므로 `ERB::Util.h(value)`를 사용하십시오.
`view_paths`가 경로로 설정되면 이 뷰 경로가 애플리케이션 내의 모든 rabl 템플릿에 대해 확인됩니다. 특히 엔진에 Rabl을 포함하고 다른 Rails 앱 내에서 뷰 경로를 사용하는 경우 이 경로에 추가하십시오.
`raise_on_missing_attribute`가 `true`로 설정되면 Rabl이 존재하지 않는 속성을 렌더링하려고 할 때마다 RuntimeError가 발생합니다. 그렇지 않으면 속성이 단순히 생략됩니다. 개발 중에 이 값을 true로 설정하면 코드의 견고성을 높이는 데 도움이 될 수 있지만, 프로덕션 코드에서는 `true`를 사용하지 않는 것이 좋습니다.
`replace_nil_values_with_empty_strings`가 `true`로 설정되면 `nil`이며 일반적으로 응답에서 `null`로 표시되는 모든 값이 빈 문자열로 변환됩니다.
기본 JSON 인코딩 엔진으로 [oj](https://github.com/ohler55/oj)를 사용하려면 Gemfile에 다음을 추가하기만 하면 됩니다:```ruby
# Gemfile
gem 'oj'
그리고 RABL은 JSON 응답을 인코딩하기 위해 해당 엔진을 자동으로 사용합니다. 루비 데이터에서 JSON으로 변환하기 위한 dump 또는 encode 메소드를 정의하는 자신만의 커스텀 json_engine을 설정하세요:```ruby
config.json_engine = ActiveSupport::JSON
### 형식 구성 ###
RABL은 MessagePack, BSON, Plist에 대한 구성을 지원합니다. 자세한 내용은 [형식 구성](https://github.com/nesquena/rabl/wiki/Configuring-Formats) 페이지를 확인하세요.
## 사용법 ##
### 객체 할당 ###
템플릿에서 사용할 데이터 객체를 선언하려면:```ruby
# app/views/users/show.json.rabl
object @user
또는 객체에 대한 별칭을 지정하십시오:```ruby object @user => :person
또는 객체 컬렉션을 전달합니다:```ruby
collection @users
# => [ { "user" : { ... } } ]
또는 컬렉션의 루트 노드 레이블을 지정하십시오:```ruby collection @users => :people
또는 컬렉션의 하위 레이블과 루트 레이블을 모두 지정할 수도 있습니다:```ruby
collection @users, :root => "people", :object_root => "user"
# => { "people" : [ { "user" : { ... } } ] }
그리고 이것은 렌더링을 위한 기본 데이터로 사용되거나, 객체 루트를 명시적으로 비활성화합니다:```ruby collection @users, :root => "people", :object_root => false
또한 응답의 최상위 레벨이 어떤 객체에도 직접 매핑되지 않는 특이한 경우가 있을 수 있습니다:```ruby
object false
node(:some_count) { |m| @user.posts.count }
child(@user) { attribute :name }
그러한 경우, 객체는 'false'로 할당될 수 있으며 노드는 자유롭게 구성될 수 있습니다.
응답에 대해 몇 가지 간단한 속성을 정의하기 위한 템플레이터의 기본 사용법:```ruby
attributes :id, :foo, :bar
또는 별칭 속성과 함께 사용하세요:```ruby
# Take the value of model attribute `foo` and name the node `bar`
attribute :foo => :bar
# => { bar : 5 }
또는 여러 개의 별칭 속성도:```ruby attributes :bar => :baz, :dog => :animal
또는 조건이 참일 경우에만 속성을 표시합니다:```ruby
# m is the object being rendered, also supports :unless
attributes :foo, :bar, :if => lambda { |m| m.condition? }
명명된 속성과 별칭 속성은 같은 줄에 결합할 수 없습니다. 현재 이는 작동하지 않습니다:```ruby attributes :foo, :bar => :baz # throws exception
### 자식 노드 ###
종종 응답은 부모 모델과 연결된 데이터에서 중첩된 정보를 포함해야 합니다:```ruby
child :address do
attributes :street, :city, :zip, :state
end
또한 자식 노드의 객체 루트를 비활성화할 수 있습니다:```ruby child :posts, :object_root => false do attributes :id, :title end
또한 임의의 데이터 소스에서 자식 노드를 추가할 수 있습니다:```ruby
child @posts => :foobar do
attributes :id, :title
end
또는 모델 연관을 별칭과 함께 사용하세요:```ruby
child :posts => :foobar do attributes :id, :title end
또한 현재 객체를 전달할 수 있습니다:```ruby
object @user
child :posts do |user|
attribute :title unless user.suspended?
end
또한 하위 속성을 다시 루트 노드에 추가할 수 있습니다:```ruby
glue @post do attributes :id => :post_id, :name => :post_name end
부모 객체에 추가 속성을 추가하려면 glue를 사용하세요.
현재 객체를 전달할 수도 있습니다:```ruby
object @user
glue(@post) {|user| attribute :title if user.active? }
이는 node 블록의 결과를 기반으로 json 응답을 생성합니다.```ruby
node :full_name do |u| u.first_name + " " + u.last_name end
또는 조건이 참인 경우에만 존재하는 사용자 정의 노드:```ruby
# m is the object being rendered, also supports :unless
node(:foo, :if => lambda { |m| m.has_foo? }) do |m|
m.foo
end
또는 이름을 전달하지 않고 노드 블록을 응답에 병합하세요:```ruby node do |u| { :full_name => u.first_name + " " + u.last_name }
end
이와 같은 사용자 정의 노드를 사용하여 모델의 모든 데이터를 활용하는 값의 유연한 표현을 만들 수 있습니다.
### Partials ###
더 복잡한 연관 관계에서 사용자 정의 노드를 구성하려면 종종 다른 데이터 객체에 접근해야 합니다. RABL 부분 템플릿을 렌더링하여 다른 데이터 객체의 rabl 표현에 접근할 수 있습니다:```ruby
node :location do
{ :city => @city, :address => partial("users/address", :object => @address) }
end
또는 상위 모델과 연관된 객체에 접근할 수도 있습니다:```ruby node :location do |m| { :city => m.city, :address => partial("users/address", :object => m.address) } end
이 방법을 사용하여 API에 대해 임의로 복잡한 노드를 구성할 수 있습니다. 이 방식으로 표현을 구성하려는 각 객체에 대해 RABL 템플릿이 정의되어 있어야 합니다.
### 상속 ###
많은 템플릿 빌더의 또 다른 일반적인 문제는 불필요한 코드 중복입니다. 일반적으로 여러 엔드포인트에서 객체의 많은 표현이 공통 속성이나 노드를 공유합니다. 'post' 객체의 노드는 대부분의 엔드포인트 참조에서 동일하거나 유사할 수 있습니다.
RABL은 다른 "기본" rabl 템플릿과 추가 속성을 확장할 수 있습니다:```ruby
# app/views/users/advanced.json.rabl
extends "users/base" # another RABL template in "app/views/users/base.json.rabl"
node :can_drink do |m|
m.age > 21
end
중복을 줄이기 위해 하위 노드를 구성하는 동안 다른 rabl 템플릿을 확장할 수도 있습니다:```ruby
child @address do extends "address/item" end
부분 템플릿과 상속을 사용하면 템플릿에서 코드 중복을 크게 줄일 수 있습니다.
더 많은 예제는 [템플릿 재사용 위키 페이지](https://github.com/nesquena/rabl/wiki/Reusing-templates)에서 확인할 수 있습니다.
### 부분에서 지역 변수 전달 ###
부분 템플릿을 렌더링하거나 템플릿을 확장할 때 임의의 지역 변수 집합을 전달할 수 있습니다.
예를 들어, `posts/:id.json`에 특정 게시물 및 관련 댓글에 대한 정보를 표시하고 싶지만 다른 경우에는 해당 댓글을 숨기고 싶다면 지역 변수를 사용하여 이를 수행할 수 있습니다.```ruby
# app/views/posts/index.json.rabl
collection @posts
extends('posts/show', :locals => { :hide_comments => true })
# or using partial instead of extends
# node(false) { |post| partial('posts/show', :object => :post, :locals => { :hide_comments => true })}
그런 다음 하위 템플릿의 로컬 변수에 접근합니다:```ruby
object @post
attributes :id, :title, :body, :created_at node(:comments) { |post| post.comments } unless locals[:hide_comments]
이는 부분 템플릿을 확장하거나 렌더링할 때 고급 도구로 유용할 수 있습니다.
### 템플릿 범위 ###
RABL에서는 API 응답을 구축하는 데 필요한 모든 것에 접근할 수 있습니다. 각 RABL 템플릿은 컨트롤러
인스턴스 변수뿐만 아니라 모든 뷰 헬퍼와 라우팅 URL에 완전히 접근할 수 있습니다.```ruby
# app/some/template.rabl
object @post
# Access instance variables
child(@user => :user) { ... }
# or Rails helpers
node(:formatted_body) { |post| simple_format(post.body) }
응답을 구성하는 데 필요한 적절한 데이터를 가져오는 데 문제가 없어야 합니다.
API에서는 종종 2차 또는 3차 수준의 노드를 구성해야 할 필요가 있습니다. 'quiz' 모델에 많은 'questions'이 있고 각 질문에는 많은 'answers'가 있다고 가정해 보겠습니다. 이 계층 구조를 RABL에서 아주 쉽게 표시할 수 있습니다:```ruby
object @quiz attribute :title child :questions do attribute :caption child :answers do # Use inheritance to reduce duplication extends "answers/item" end end
이는 퀴즈 노드에서 예상하는 대로 중첩된 질문과 답변, 그리고 포함된 질문과 답변이 있는 퀴즈 객체를 표시합니다.
RABL은 이러한 표현을 정의할 수 있도록 자식 노드 내에서 임의의 깊이로 중첩될 수 있습니다.
### 캐싱 ###
RABL은 템플릿에 대한 내장 캐싱 지원을 제공하며, 조각 캐싱 전략을 활용합니다. 캐싱은 현재 Rails에서만 **사용 가능**하지만, 다른 프레임워크에 대한 지원은 향후 릴리스에서 계획되어 있습니다. 가장 간단한 캐싱 사용법은 다음과 같습니다:```ruby
# app/views/users/show.json.rabl
object @quiz
cache @quiz # key = rabl/quiz/[cache_key]
attribute :title
Caching can significantly speed up the rendering of RABL templates in production and is strongly recommended when possible. For more a more detailed look at caching, check out the Caching guide on the wiki.
There are situations where an application requires RABL templates to be rendered outside
a traditional view context. For instance, to render RABL within a Rake task or to create
message queue payloads. For this case, Rabl.render can be used as show below:
# In a Rake task, background job, or message queue
output = Rabl.render("users/show", @user, :view_path => "app/views", :format => :json)
``````ruby
Rabl.render(object, template, :view_path => 'app/views', :format => :json) #=> "{...json...}"
Rabl::Renderer의 편의 메서드를 사용하여 객체를 렌더링할 수도 있습니다:```ruby
Rabl::Renderer.json(@post, 'posts/show')
Rabl::Renderer.xml(@post, 'posts/show')
이 메서드들은 RABL을 사용하여 객체를 원하는 형식으로 자유롭게 변환할 수 있도록 해줍니다.```ruby
Rabl::Renderer.new('posts/show', @post, :view_path => 'app/views', :format => 'hash').render
템플릿에서 사용할 다른 인스턴스 변수를 다음과 같이 전달할 수도 있습니다:```ruby Rabl::Renderer.new('posts/show', @post, :locals => { :custom_title => "Hello world!" })
그런 다음 템플릿에서 다음과 같이 `@custom_title`을 사용할 수 있습니다:```
attribute :content
node(:title) { @custom_title }
```
### 컨텐츠 타입 헤더 ###
현재 RABL에서는 응답의 content-type이 자동으로 설정되지 않습니다. 이는 RABL이 모든 Rack 기반 프레임워크에서 작동하고 가능한 한 포맷에 무관하도록 설계되었기 때문입니다. 자세한 내용은 [이 이슈](https://github.com/nesquena/rabl/issues/185#issuecomment-4501232)를 확인해 주시고, 아이디어나 패치가 있으면 알려주세요.
그동안 필요하다면 적절한 content-type을 설정하시기 바랍니다. Rails와 Padrino 모두에서 일반적으로 매우 간단합니다. 해당 컨트롤러에 before_filter를 사용하거나 액션에서 직접 지정하는 것을 권장합니다.
## 리소스 ##
RABL과 관련된 많은 리소스가 있으며, [RABL Wiki](https://github.com/nesquena/rabl/wiki)와 아래에 자세히 설명된 많은 튜토리얼 및 가이드가 포함되어 있습니다. [RABL 사이트](http://nesquena.github.com/rabl)도 확인할 수 있습니다.
### 고급 사용법 ###
고급 사용법에 대한 리소스 링크:
* [복잡성 관리](https://github.com/nesquena/rabl/wiki/Managing-complexity-with-presenters)
* [프로덕션 최적화](https://github.com/nesquena/rabl/wiki/Rabl-In-Production)
* [Grape 통합](https://github.com/nesquena/rabl/wiki/Using-Rabl-with-Grape)
* [RABL을 사용한 트리 구조 JSON 렌더링](https://github.com/nesquena/rabl/issues/70)
* [RABL에서의 레이아웃 (erb, haml 및 rabl)](https://github.com/nesquena/rabl/wiki/Using-Layouts)
* [Backbone 또는 Ember.js 통합](https://github.com/nesquena/rabl/wiki/Backbone-Integration)
* [Rails 엔진과 RABL](https://github.com/nesquena/rabl/wiki/Setup-rabl-with-rails-engines)
자신의 사용 예를 추가하고 알려주시면 여기에 추가하겠습니다! 또한 다른 사용 예를 위해 [RABL Wiki](https://github.com/nesquena/rabl/wiki)를 확인하세요.
### 튜토리얼 ###
튜토리얼은 처음 시작할 때 항상 도움이 됩니다:
* [Railscasts #322](http://railscasts.com/episodes/322-rabl) - Ryan Bates가 RABL을 설명합니다
* [BackboneRails](http://www.backbonerails.com/) - Brian Mann의 훌륭한 스크린캐스트
* [RABL과 Padrino로 API 만들기](http://blog.crowdint.com/2012/10/22/rabl-with-padrino.html)
* http://blog.joshsoftware.com/2011/12/23/designing-rails-api-using-rabl-and-devise/
* http://engineering.gomiso.com/2011/06/27/building-a-platform-api-on-rails/
* http://blog.lawrencenorton.com/better-json-requests-with-rabl
* http://www.rodrigoalvesvieira.com/developing-json-api-rails-rabl/
* http://tech.favoritemedium.com/2011/06/using-rabl-in-rails-json-web-api.html
* http://seesparkbox.com/foundry/better_rails_apis_with_rabl
* http://blog.dcxn.com/2011/06/22/rails-json-templates-through-rabl
* http://teohm.github.com/blog/2011/05/31/using-rabl-in-rails-json-web-api
여기에 나열되지 않은 다른 유용한 리소스가 있으면 알려주세요.
### 관련 라이브러리 ###
RABL의 기능을 보완하거나 확장할 수 있는 다른 라이브러리들이 있습니다:
* [versioncake](https://github.com/bwillis/versioncake) - RABL API를 쉽게 버전 관리할 수 있는 훌륭한 라이브러리
* [gon](https://github.com/gazay/gon) - RABL 지원이 통합되어 Rails 변수를 JS에 노출합니다.
* [rabl-rails](https://github.com/ccocchi/rabl-rails) - RABL과 Rails를 위한 [속도에 중점을 둔](https://github.com/ccocchi/rabl-benchmark/blob/master/BENCHMARK) 재구현.
여기에 나열되지 않은 다른 관련 라이브러리가 있으면 알려주세요.
### 문제 해결 ###
* [컬렉션에 대한 중복 호출](https://github.com/nesquena/rabl/issues/142#issuecomment-2969107)
* [RABL 뷰 테스트](https://github.com/nesquena/rabl/issues/130#issuecomment-4179285)
### 예제 ###
[예제](https://github.com/nesquena/rabl/tree/master/examples) 디렉토리를 참조하세요.
## 이슈 ##
전체 목록은 [Issues](https://github.com/nesquena/rabl/issues) 탭을 확인하세요:
* 엄격한 벤치마킹 및 성능 최적화
## 작성자 및 기여자 ##
[Miso](http://gomiso.com)에 감사드리며, 이 프로젝트를 저희 애플리케이션을 위해 만들고 공개할 수 있게 해주셨습니다!
* [Nathan Esquenazi](https://github.com/nesquena) - 프로젝트 창시자
* [Arthur Chiu](https://github.com/achiu) - 핵심 유지보수자, Riot 테스트 전문가
* [Tim Lee](https://github.com/timothy1ee) - RABL은 Miso CTO가 선택한 훌륭한 이름입니다.
* [David Sommers](https://github.com/databyte) - 템플릿 해석, 캐싱 지원 등
* [Rick Thomas](https://github.com/rickthomasjr) - extends 옵션 및 Sinatra 테스트 추가
* [Benjamin Yu](https://github.com/byu) - msgpack 포맷 지원 추가
* [Chris Kimpton](https://github.com/kimptoc) - 문서화 및 wiki 도움
* [Marjun](https://github.com/mpagalan) - xml 옵션 설정 추가
* [Anton Orel](https://github.com/skyeagle) - Rails 3.1 호환성 추가
* [Sasha Koss](https://github.com/kossnocorp) - multi_json 지원 추가
* [Matthew Schulkind](https://github.com/mschulkind) - 설정 및 테스트 정리
* [Luke van der Hoeven](https://github.com/plukevdh) - 템플릿에서 비ORM 객체 지원
* [Andrey Voronkov](https://github.com/Antiarchitect) - BSON 포맷 지원 추가
* [Alli Witheford](https://github.com/alzeih) - Plist 포맷 지원 추가
* [Ryan Bigg](https://github.com/radar) - 템플릿 해석 코드 개선
* [Ivan Vanderbyl](https://github.com/ivanvanderbyl) - 범용 렌더러 추가
* [Cyril Mougel](https://github.com/shingara) - cache_engine 플러그형 지원 및 렌더러 조정 추가
* [Teng Siong Ong](https://github.com/siong1987) - 렌더러 인터페이스 개선
* [Brad Dunbar](https://github.com/braddunbar) - 현재 객체를 블록으로 전달
그 외 많은 기여자들은 [CHANGELOG](https://github.com/nesquena/rabl/blob/master/CHANGELOG.md)에 나열되어 있습니다.
다른 포맷 지원에 기여하고 싶으신가요? [msgpack 지원](https://github.com/nesquena/rabl/pull/69), [plist 지원](https://github.com/nesquena/rabl/pull/153), [BSON 지원](https://github.com/nesquena/rabl/pull/163) 패치를 참고하세요.
포크하여 기여해 주세요, 이 프로젝트를 개선하는 데 도움을 주시면 감사하겠습니다!
이 프로젝트는 [OSS Manifesto](http://ossmanifesto.org)의 구성원입니다.
## 영감 ##
RABL에 영감을 준 몇 가지 훌륭한 라이브러리들이 있으며 아래에 나열되어 있습니다:
* [Tequila](https://github.com/inem/tequila)
* [JSON Builder](https://github.com/dewski/json_builder)
* [Argonaut](https://github.com/jbr/argonaut)
이 모든 훌륭한 프로젝트에 다시 한번 감사드립니다.
## 저작권 ##
저작권 © 2011-2012 Nathan Esquenazi. 자세한 내용은 [MIT-LICENSE](https://github.com/nesquena/rabl/blob/master/MIT-LICENSE)를 참조하세요.