README.ko.md in sinatra-1.4.5 vs README.ko.md in sinatra-1.4.6

- old
+ new

@@ -52,25 +52,28 @@ * [Less 템플릿](#less-템플릿) * [Liquid 템플릿](#liquid-템플릿) * [Markdown 템플릿](#markdown-템플릿) * [Textile 템플릿](#textile-템플릿) * [RDoc 템플릿](#rdoc-템플릿) + * [AsciiDoc 템플릿](#asciidoc-템플릿) * [Radius 템플릿](#radius-템플릿) * [Markaby 템플릿](#markaby-템플릿) * [RABL 템플릿](#rabl-템플릿) * [Slim 템플릿](#slim-템플릿) * [Creole 템플릿](#creole-템플릿) + * [MediaWiki 템플릿](#mediawiki-템플릿) * [CoffeeScript 템플릿](#coffeescript-템플릿) * [Stylus 템플릿](#stylus-템플릿) * [Yajl 템플릿](#yajl-템플릿) * [WLang 템플릿](#wlang-템플릿) * [템플릿에서 변수에 접근하기](#템플릿에서-변수에-접근하기) * [템플릿에서의 `yield` 와 중첩 레이아웃](#템플릿에서의-yield-와-중첩-레이아웃) * [인라인 템플릿](#인라인-템플릿) * [이름을 가지는 템플릿(Named Templates)](#이름을-가지는-템플릿named-templates) * [파일 확장자 연결하기](#파일-확장자-연결하기) * [나만의 고유한 템플릿 엔진 추가하기](#나만의-고유한-템플릿-엔진-추가하기) + * [템플릿 검사를 위한 커스텀 로직 사용하기](#템플릿-검사를-위한-커스텀-로직-사용하기) * [필터(Filters)](#필터filters) * [헬퍼(Helpers)](#헬퍼helpers) * [세션(Sessions) 사용하기](#세션sessions-사용하기) * [중단하기(Halting)](#중단하기halting) * [넘기기(Passing)](#넘기기passing) @@ -160,36 +163,37 @@ 라우터 패턴에는 이름을 가진 매개변수가 포함될 수 있으며, `params` 해시로 접근할 수 있습니다. ``` ruby get '/hello/:name' do # "GET /hello/foo" 및 "GET /hello/bar"와 매치 - # params[:name]은 'foo' 또는 'bar' - "Hello #{params[:name]}!" + # params['name']은 'foo' 또는 'bar' + "Hello #{params['name']}!" end ``` 또한 블록 매개변수를 통하여도 이름을 가진 매개변수에 접근할 수 있습니다. ``` ruby get '/hello/:name' do |n| # "GET /hello/foo" 및 "GET /hello/bar"와 매치 - # params[:name]은 'foo' 또는 'bar' + # params['name']은 'foo' 또는 'bar' + # n 에는 params['name']가 저장 "Hello #{n}!" end ``` -라우터 패턴에는 스플랫(splat, 또는 와일드카드)도 매개변수도 포함될 수 있으며, 이럴 경우 `params[:splat]` 배열을 통해 접근할 수 있습니다. +라우터 패턴에는 스플랫(splat, 또는 와일드카드)도 매개변수도 포함될 수 있으며, 이럴 경우 `params['splat']` 배열을 통해 접근할 수 있습니다. ``` ruby get '/say/*/to/*' do # /say/hello/to/world와 매치 - params[:splat] # => ["hello", "world"] + params['splat'] # => ["hello", "world"] end get '/download/*.*' do # /download/path/to/file.xml과 매치 - params[:splat] # => ["path/to/file", "xml"] + params['splat'] # => ["path/to/file", "xml"] end ``` 블록 매개변수로도 접근할 수 있습니다. @@ -200,19 +204,20 @@ ``` 라우터는 정규표현식으로 매치할 수 있습니다. ``` ruby -get %r{/hello/([\w]+)} do - "Hello, #{params[:captures].first}!" +get /\A\/hello\/([\w]+)\z/ do + "Hello, #{params['captures'].first}!" end ``` 블록 매개변수로도 사용가능합니다. ``` ruby get %r{/hello/([\w]+)} do |c| + # "GET /meta/hello/world", "GET /hello/world/1234" 등과 매치 "Hello, #{c}!" end ``` 라우터 패턴에는 선택적인(optional) 매개변수도 올 수 있습니다. @@ -221,20 +226,31 @@ get '/posts.?:format?' do # "GET /posts" 는 물론 "GET /posts.json", "GET /posts.xml" 와 같은 어떤 확장자와도 매칭 end ``` +쿼리 파라메터로도 이용가능 합니다. + +``` ruby +get '/posts' do + # matches "GET /posts?title=foo&author=bar" + title = params['title'] + author = params['author'] + # uses title and author variables; query is optional to the /posts route +end +``` + 한편, 경로 탐색 공격 방지(path traversal attack protection, 아래 참조)를 비활성화시키지 않았다면, 요청 경로는 라우터와 매칭되기 이전에 수정될 수 있습니다. ### 조건(Conditions) 라우터는 사용자 에이전트(user agent)같은 다양한 매칭 조건을 포함할 수 있습니다. ``` ruby get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do - "Songbird 버전 #{params[:agent][0]}을 사용하는군요!" + "Songbird 버전 #{params['agent'][0]}을 사용하는군요!" end get '/foo' do # songbird 브라우저가 아닌 경우 매치 end @@ -253,10 +269,11 @@ get '/', :provides => ['rss', 'atom', 'xml'] do builder :feed end ``` +`provides`는 request의 허용된 해더를 검색합니다. 사용자 정의 조건도 쉽게 만들 수 있습니다. ``` ruby set(:probability) { |value| condition { rand <= value } } @@ -449,12 +466,13 @@ 기본값은 <tt>settings.views</tt>. </dd> <dt>layout</dt> <dd> - 레이아웃을 사용할지 여부 (<tt>true</tt> 또는 <tt>false</tt>), 만약 이 값이 심볼일 경우, - 사용할 템플릿을 지정. 예제: <tt>erb :index, :layout => !request.xhr?</tt> + 레이아웃을 사용할지 여부 (<tt>true</tt> 또는 <tt>false</tt>), 만약 + 이 값이 심볼일 경우, 사용할 템플릿을 지정. 예제: + <tt>erb :index, :layout => !request.xhr?</tt> </dd> <dt>content_type</dt> <dd> 템플릿이 생성하는 Content-Type, 기본값은 템플릿 언어에 의존. @@ -543,11 +561,11 @@ #### Builder 템플릿 <table> <tr> <td>의존성</td> - <td><a href="http://builder.rubyforge.org/">builder</a></td> + <td><a href="https://github.com/jimweirich/builder">builder</a></td> </tr> <tr> <td>파일 확장자</td> <td><tt>.builder</tt></td> </tr> @@ -656,12 +674,12 @@ <td>의존성</td> <td> <a href="https://github.com/rtomayko/rdiscount" title="RDiscount">RDiscount</a>, <a href="https://github.com/vmg/redcarpet" title="RedCarpet">RedCarpet</a>, <a href="http://deveiate.org/projects/BlueCloth" title="BlueCloth">BlueCloth</a>, - <a href="http://kramdown.rubyforge.org/" title="kramdown">kramdown</a>, - <a href="http://maruku.rubyforge.org/" title="maruku">maruku</a> + <a href="http://kramdown.gettalong.org/" title="kramdown">kramdown</a>, + <a href="https://github.com/bhollis/maruku" title="maruku">maruku</a> 중 아무거나 </td> </tr> <tr> <td>파일 확장</td> @@ -729,11 +747,11 @@ #### RDoc 템플릿 <table> <tr> <td>의존성</td> - <td><a href="http://rdoc.rubyforge.org/">rdoc</a></td> + <td><a href="http://rdoc.sourceforge.net/" title="RDoc">rdoc</a></td> </tr> <tr> <td>파일 확장자</td> <td><tt>.rdoc</tt></td> </tr> @@ -759,16 +777,36 @@ RDoc에서 루비를 호출할 수 없기 때문에, RDoc으로 작성된 레이아웃은 사용할 수 없습니다. 하지만, `:layout_engine` 옵션으로 레이아웃의 템플릿을 다른 렌더링 엔진으로 렌더링 할 수는 있습니다. +#### AsciiDoc 템플릿 + +<table> + <tr> + <td>의존성</td> + <td><a href="http://asciidoctor.org/" title="Asciidoctor">Asciidoctor</a></td> + </tr> + <tr> + <td>파일 확장자</td> + <td><tt>.asciidoc</tt>, <tt>.adoc</tt> and <tt>.ad</tt></td> + </tr> + <tr> + <td>예제</td> + <td><tt>asciidoc :README, :layout_engine => :erb</tt></td> + </tr> +</table> + +AsciiDoc 템플릿에서는 루비 메서드를 호출할 수 없기 +때문에, 거의 대부분의 경우 locals를 전달해야 합니다. + #### Radius 템플릿 <table> <tr> <td>의존성</td> - <td><a href="http://radius.rubyforge.org/">radius</a></td> + <td><a href="https://github.com/jlong/radius" title="Radius">radius</a></td> </tr> <tr> <td>파일 확장자</td> <td><tt>.radius</tt></td> </tr> @@ -867,10 +905,45 @@ Creole에서 루비를 호출할 수 없기 때문에, Creole으로 작성된 레이아웃은 사용할 수 없습니다. 하지만, `:layout_engine` 옵션으로 레이아웃의 템플릿을 다른 렌더링 엔진으로 렌더링 할 수는 있습니다. +#### MediaWiki 템플릿 + +<table> + <tr> + <td>의존성</td> + <td><a href="https://github.com/nricciar/wikicloth" title="WikiCloth">WikiCloth</a></td> + </tr> + <tr> + <td>파일 확장자</td> + <td><tt>.mediawiki</tt> and <tt>.mw</tt></td> + </tr> + <tr> + <td>예제</td> + <td><tt>mediawiki :wiki, :layout_engine => :erb</tt></td> + </tr> +</table> + +MediaWiki 마크업에서는 메서드 호출 뿐 아니라 locals 전달도 불가능합니다. +따라서 일반적으로는 다른 렌더링 엔진과 함께 사용하게 됩니다. + +``` ruby +erb :overview, :locals => { :text => mediawiki(:introduction) } +``` + +다른 템플릿 속에서 `mediawiki` 메서드를 호출할 수도 있습니다. + +``` ruby +%h1 Hello From Haml! +%p= mediawiki(:greetings) +``` + +MediaWiki에서 루비를 호출할 수 없기 때문에, MediaWiki으로 작성된 레이아웃은 +사용할 수 없습니다. 하지만, `:layout_engine` 옵션으로 레이아웃의 템플릿을 +다른 렌더링 엔진으로 렌더링 할 수는 있습니다. + #### CoffeeScript 템플릿 <table> <tr> <td>의존성</td> @@ -983,31 +1056,31 @@ <td>예제</td> <td><tt>wlang :index, :locals => { :key => 'value' }</tt></td> </tr> </table> -WLang 템플릿에서는 루비 메서드(`yield` 제외)를 호출할 수 없기 -때문에, 거의 대부분의 경우 locals를 전달해야 합니다. 그래도 +WLang 템플릿에서는 루비 메서드를 사용하는게 일반적이지 않기 +때문에, 거의 대부분의 경우 locals를 전달합니다. 그래도 WLang으로 쓰여진 레이아웃과 `yield`는 지원합니다. ### 템플릿에서 변수에 접근하기 템플릿은 라우터 핸들러와 같은 맥락(context)에서 평가됩니다. 라우터 핸들러에서 설정한 인스턴스 변수들은 템플릿에서 직접 접근 가능합니다. ``` ruby get '/:id' do - @foo = Foo.find(params[:id]) + @foo = Foo.find(params['id']) haml '%h1= @foo.name' end ``` 명시적으로 로컬 변수의 해시를 지정할 수도 있습니다. ``` ruby get '/:id' do - foo = Foo.find(params[:id]) + foo = Foo.find(params['id']) haml '%h1= bar.name', :locals => { :bar => foo } end ``` 이 방법은 주로 템플릿을 다른 템플릿 속에서 파셜(partial)로 렌더링할 @@ -1129,10 +1202,26 @@ ``` 위 코드는 `./views/index.myat` 를 렌더합니다. Tilt에 대한 더 자세한 내용은 https://github.com/rtomayko/tilt 참조하세요. +### 템플릿 검사를 위한 커스텀 로직 사용하기 + +고유한 템플릿 룩업을 구현하기 위해서는 `#find_template` 메서드를 만드셔야 합니다. + +``` ruby +configure do + set :views [ './views/a', './views/b' ] +end + +def find_template(views, name, engine, &block) + Array(views).each do |v| + super(v, name, engine, &block) + end +end +``` + ## 필터(Filters) 사전 필터(before filter)는 라우터와 동일한 맥락에서 매 요청 전에 평가되며 요청과 응답을 변형할 수 있습니다. 필터에서 설정된 인스턴스 변수들은 라우터와 템플릿에서 접근 가능합니다. @@ -1143,11 +1232,11 @@ request.path_info = '/foo/bar/baz' end get '/foo/*' do @note #=> 'Hi!' - params[:splat] #=> 'bar/baz' + params['splat'] #=> 'bar/baz' end ``` 사후 필터(after filter)는 라우터와 동일한 맥락에서 매 요청 이후에 평가되며 마찬가지로 요청과 응답을 변형할 수 있습니다. 사전 필터와 라우터에서 설정된 @@ -1170,11 +1259,11 @@ before '/protected/*' do authenticate! end after '/create/:slug' do |slug| - session[:last_slug] = slug + session['last_slug'] = slug end ``` 라우터와 마찬가지로, 필터 역시 조건을 취할 수 있습니다. @@ -1199,11 +1288,11 @@ "#{name}bar" end end get '/:name' do - bar(params[:name]) + bar(params['name']) end ``` 또는, 헬퍼 메서드는 별도의 모듈 속에 정의할 수도 있습니다. @@ -1228,15 +1317,15 @@ ``` ruby enable :sessions get '/' do - "value = " << session[:value].inspect + "value = " << session['value'].inspect end get '/:value' do - session[:value] = params[:value] + session['value'] = params['value'] end ``` `enable :sessions`은 실은 모든 데이터를 쿠키 속에 저장하는 것에 주의하세요. 이 방식이 바람직하지 않을 수도 있습니다. (예를 들어, 많은 양의 데이터를 @@ -1247,15 +1336,15 @@ ``` ruby use Rack::Session::Pool, :expire_after => 2592000 get '/' do - "value = " << session[:value].inspect + "value = " << session['value'].inspect end get '/:value' do - session[:value] = params[:value] + session['value'] = params['value'] end ``` 보안 강화을 위해서, 쿠키 속의 세션 데이터는 세션 시크릿(secret)으로 사인(sign)됩니다. Sinatra는 무작위 시크릿을 생성합니다. 하지만, 이 @@ -1322,11 +1411,11 @@ 라우터는 `pass`를 사용하여 다음 번 매칭되는 라우터로 처리를 넘길 수 있습니다. ``` ruby get '/guess/:who' do - pass unless params[:who] == 'Frank' + pass unless params['who'] == 'Frank' 'You got me!' end get '/guess/*' do 'You missed!' @@ -1438,23 +1527,21 @@ set :server, :thin connections = [] get '/subscribe' do # register a client's interest in server events - stream(:keep_open) { |out| connections << out } - - # purge dead connections - connections.reject!(&:closed?) - - # acknowledge - "subscribed" + stream(:keep_open) do |out| + connections << out + # purge dead connections + connections.reject!(&:closed?) + end end -post '/message' do +post '/:message' do connections.each do |out| # notify client that a new message has arrived - out << params[:message] << "\n" + out << params['message'] << "\n" # indicate client to connect again out.close end @@ -1570,16 +1657,16 @@ ``` ruby enable :sessions get '/foo' do - session[:secret] = 'foo' + session['secret'] = 'foo' redirect to('/bar') end get '/bar' do - session[:secret] + session['secret'] end ``` ### 캐시 컨트롤(Cache Control) @@ -1609,18 +1696,18 @@ before do expires 500, :public, :must_revalidate end ``` -캐시를 잘 사용하려면, `etag` 또는 `last_modified`의 사용을 고려해야 할 것이다. +캐시를 잘 사용하려면, `etag` 또는 `last_modified`을 사용해 보세요. 무거운 작업을 하기 *전*에 이들 헬퍼를 호출하길 권장합니다. 이렇게 하면, 클라이언트 캐시에 현재 버전이 이미 들어 있을 경우엔 즉각 응답을 뿌릴(flush) 것입니다. ``` ruby -get '/article/:id' do - @article = Article.find params[:id] +get "/article/:id" do + @article = Article.find params['id'] last_modified @article.updated_at etag @article.sha1 erb :article end ``` @@ -1672,11 +1759,11 @@ etag '', :new_resource => true, :kind => :weak ``` ### 파일 전송하기(Sending Files) -파일을 전송하려면, `send_file` 헬퍼 메서드를 사용하면 됩니다. +응답(response)으로 파일의 컨탠츠를 리턴하려면, `send_file` 헬퍼 메서드를 사용하면 됩니다. ``` ruby get '/' do send_file 'foo.png' end @@ -1690,26 +1777,26 @@ 옵션들: <dl> <dt>filename</dt> - <dd>응답에서의 파일명. 기본값은 실제 파일명.</dd> + <dd>응답에서 사용되는 파일명. 기본값은 실제 파일명.</dd> <dt>last_modified</dt> <dd>Last-Modified 헤더값. 기본값은 파일의 mtime.</dd> <dt>type</dt> - <dd>사용할 컨텐츠 유형. 없으면 파일 확장자로부터 유추.</dd> + <dd>Content-Type 헤더값. 없으면 파일 확장자로부터 유추.</dd> <dt>disposition</dt> <dd> - Content-Disposition에서 사용됨. 가능한 값들: <tt>nil</tt> (기본값), + Content-Disposition 헤더값. 가능한 값들: <tt>nil</tt> (기본값), <tt>:attachment</tt> 및 <tt>:inline</tt> </dd> <dt>length</dt> - <dd>Content-Length, 기본값은 파일 크기.</dd> + <dd>Content-Length 헤더값, 기본값은 파일 크기.</dd> <dt>status</dt> <dd> 전송할 상태 코드. 오류 페이지로 정적 파일을 전송할 경우에 유용. @@ -1978,25 +2065,27 @@ <tt>rul</tt> 헬퍼는, 만약 두 번째 매개변수로 <tt>false</tt>를 전달하지만 않는다면, 여전히 절대경로 URL을 생성할 것임에 유의. </dd> <dd>기본값은 비활성.</dd> - <dt>add_charsets</dt> + <dt>add_charset</dt> <dd> <tt>content_type</tt>가 문자셋 정보에 자동으로 추가하게 될 마임(mime) 타입. 이 옵션은 오버라이딩하지 말고 추가해야 함. - <tt>settings.add_charsets << "application/foobar"</tt> + <tt>settings.add_charset << "application/foobar"</tt> </dd> <dt>app_file</dt> <dd> 메인 애플리케이션 파일의 경로. 프로젝트 루트, 뷰, public 폴더, 인라인 템플릿을 파악할 때 사용됨. </dd> <dt>bind</dt> - <dd>바인드할 IP 주소(기본값: <tt>0.0.0.0</tt> <em>이나</em> `environment`가 개발로 설정 되어있으면 <tt>localhost</tt>). 오직 빌트인(built-in) 서버에서만 사용됨.</dd> + <dd>바인드할 IP 주소(기본값: <tt>0.0.0.0</tt> <em>이나</em> + `environment`가 개발로 설정 되어있으면 <tt>localhost</tt>). 오직 + 빌트인(built-in) 서버에서만 사용됨.</dd> <dt>default_encoding</dt> <dd>인코딩을 알 수 없을 때 인코딩(기본값은 <tt>"utf-8"</tt>).</dd> <dt>dump_errors</dt> @@ -2178,27 +2267,34 @@ ``` ### 에러 `error` 핸들러는 라우터 또는 필터에서 뭐든 오류가 발생할 경우에 호출됩니다. +하지만 개발 환경에서는 예외 확인 옵션을 `:after_handler`로 설정되어 있을 경우에만 +실행됨을 주의하세요. + +``` ruby +set :show_exceptions, :after_handler +``` + 예외 객체는 Rack 변수 `sinatra.error`로부터 얻을 수 있습니다. ``` ruby error do - '고약한 오류가 발생했군요 - ' + env['sinatra.error'].name + '고약한 오류가 발생했군요 - ' + env['sinatra.error'].message end ``` -사용자 정의 오류는 이렇게 정의한다. +사용자 정의 오류는 이렇게 정의합니다. ``` ruby error MyCustomError do '무슨 일이 생겼나면요...' + env['sinatra.error'].message end ``` -그런 다음, 이 오류가 발생하면 이렇게 처리한다. +그런 다음, 이 오류가 발생하면 이렇게 처리합니다. ``` ruby get '/' do raise MyCustomError, '안좋은 일' end @@ -2231,13 +2327,13 @@ ``` Sinatra는 개발 환경에서 동작할 때 브라우저에 괜찮은 스택 트레이스와 추가적인 디버그 정보를 보여주기 위해 특별한 `not_found` 와 `error` 핸들러를 설치합니다. -## Rack 미들웨어(Rack Middleware) +## Rack 미들웨어(Middleware) -Sinatra는 [Rack](http://rack.rubyforge.org/) 위에서 동작하며, Rack은 루비 웹 +Sinatra는 [Rack](http://rack.github.io/) 위에서 동작하며, Rack은 루비 웹 프레임워크를 위한 최소한의 표준 인터페이스입니다. Rack이 애플리케이션 개발자들에게 제공하는 가장 흥미로운 기능은 "미들웨어(middleware)"에 대한 지원입니다. 여기서 미들웨어란 서버와 여러분의 애플리케이션 사이에 위치하면서 HTTP 요청/응답을 모니터링하거나/조작함으로써 다양한 유형의 공통 기능을 제공하는 컴포넌트입니다. @@ -2254,11 +2350,11 @@ get '/hello' do 'Hello World' end ``` -`use`문법은 [Rack::Builder](http://rack.rubyforge.org/doc/classes/Rack/Builder.html]) DSL +`use`문법은 [Rack::Builder](http://rubydoc.info/github/rack/rack/master/Rack/Builder) DSL (rackup 파일에서 가장 많이 사용)에서 정의한 것과 동일합니다. 예를 들어, `use` 메서드는 블록이나 여러 개의/가변적인 인자도 받을 수 있습니다. ``` ruby use Rack::Auth::Basic do |username, password| @@ -2281,14 +2377,14 @@ Sinatra 테스트는 많은 Rack 기반 테스팅 라이브러리, 프레임워크를 사용하여 작성가능합니다. 그 중 [Rack::Test](http://rdoc.info/github/brynary/rack-test/master/frames)를 권장합니다. ``` ruby require 'my_sinatra_app' -require 'test/unit' +require 'minitest/autorun' require 'rack/test' -class MyAppTest < Test::Unit::TestCase +class MyAppTest < Minitest::Test include Rack::Test::Methods def app Sinatra::Application end @@ -2483,12 +2579,12 @@ enable :sessions get('/login') { haml :login } post('/login') do - if params[:name] == 'admin' && params[:password] == 'admin' - session['user_name'] = params[:name] + if params['name'] == 'admin' && params['password'] == 'admin' + session['user_name'] = params['name'] else redirect '/login' end end end @@ -2605,12 +2701,12 @@ # 이봐요, 전 애플리케이션 범위에 있다구요! get '/define_route/:name' do # '/define_route/:name'의 요청 범위 @value = 42 - settings.get("/#{params[:name]}") do - # "/#{params[:name]}"의 요청 범위 + settings.get("/#{params['name']}") do + # "/#{params['name']}"의 요청 범위 @value # => nil (동일한 요청이 아님) end "라우터가 정의됨!" end @@ -2685,13 +2781,13 @@ 1.9.3은 완전하게 지원되고 권장합니다. 이전 버전에서 1.9.3으로 전환할 경우 모든 세션이 무효화되므로 주의하세요. 1.9.3에 대한 지원은 Sinatra 2.0 이전에는 중단되지 않을 것입니다. </dd> - <dt>Ruby 2.0.0</dt> + <dt>Ruby 2.x</dt> <dd> - 2.0.0은 완전하게 지원되고 권장합니다. 현재 공식 지원 중지 계획은 없습니다. + 2.x은 완전하게 지원되고 권장합니다. 현재 공식 지원 중지 계획은 없습니다. </dd> <dt>Rubinius</dt> <dd> Rubinius는 공식적으로 지원됩니다. (Rubinius >= 2.x) @@ -2718,13 +2814,13 @@ 공식적으로 지원하지 않는다는 것의 의미는 무언가가 그 플랫폼에서만 잘못되고 지원되는 플랫폼에서는 그러지 않을 경우, 우리의 문제가 아니라 그 플랫폼의 문제로 간주한다는 뜻입니다. -또한 우리는 CI를 ruby-head (곧 나올 2.1.0) 브랜치에 맞춰 실행하지만, +또한 우리는 CI를 ruby-head (MRI의 이후 릴리즈) 브랜치에 맞춰 실행하지만, 계속해서 변하고 있기 때문에 아무 것도 보장할 수는 없습니다. -2.1.0가 완전히 지원되길 기대합시다. +앞으로 나올 2.x가 완전히 지원되길 기대합시다. Sinatra는 선택한 루비 구현체가 지원하는 어떠한 운영체제에서도 작동해야 합니다. 현재 Cardinal, SmallRuby, BlueRuby 또는 1.8.7 이전의 루비 버전에서는 @@ -2823,10 +2919,10 @@ 도움이 필요한가요? 패치를 하셨나요? * [이슈 트래커](http://github.com/sinatra/sinatra/issues) * [트위터](http://twitter.com/sinatra) * [메일링 리스트](http://groups.google.com/group/sinatrarb/topics) * IRC: [#sinatra](irc://chat.freenode.net/#sinatra) http://freenode.net -* [Sinatra Book](http://sinatra-book.gittr.com) Cookbook 튜토리얼 +* [Sinatra Book](https://github.com/sinatra/sinatra-book/) Cookbook 튜토리얼 * [Sinatra Recipes](http://recipes.sinatrarb.com/) 커뮤니티가 만드는 레시피 * http://rubydoc.info에 있는 [최종 릴리스](http://rubydoc.info/gems/sinatra) 또는 [current HEAD](http://rubydoc.info/github/sinatra/sinatra)에 대한 API 문서 * [CI server](http://travis-ci.org/sinatra/sinatra)