[ruby-on-rails] Rails : respond_to 블록은 어떻게 작동합니까?

나는이를 통해 갈거야 레일스 시작하기 가이드 및 6.7와 혼동되었다. 스캐 폴드를 생성 한 후 컨트롤러에서 다음과 같은 자동 생성 블록을 찾습니다.

def index
  @posts = Post.all

  respond_to do |format|
    format.html  # index.html.erb
    format.json  { render :json => @posts }
  end
end

respond_to 블록이 실제로 어떻게 작동하는지 이해하고 싶습니다. 어떤 유형의 변수가 형식입니까? 형식 객체의 .html 및 .json 메소드입니까? 문서 에 대한

ActionController::MimeResponds::ClassMethods::respond_to

질문에 대답하지 않습니다.



답변

저는 Ruby를 처음 사용하고 동일한 코드를 고수했습니다. 내가 끊은 부분은 내가 찾은 대답보다 약간 더 근본적이었습니다. 이것은 누군가를 도울 수도 아닐 수도 있습니다.

  • respond_to수퍼 클래스의 메소드입니다 ActionController.
  • 델리게이트와 같은 블록이 필요합니다. 블록은 do까지 end|format|대한 인수로 까지 입니다.
  • respond_to는 블록에 응답자를 전달하여 블록을 실행합니다 format.

http://api.rubyonrails.org/v4.1/classes/ActionController/Responder.html

  • Responder방법을 포함하지 않습니다 .html또는 .json, 그러나 우리는 이러한 방법을 어쨌든 전화! 이 부분은 나에게 루프를 던졌다.
  • 루비라는 기능이 method_missing있습니다. 존재하지 않는 메소드를 호출하면 (예 : json또는 html) Ruby는 method_missing메소드를 대신 호출합니다 .

http://ruby-metaprogramming.rubylearning.com/html/ruby_metaprogramming_2.html

  • Responder클래스는 사용 method_missing등록의 일종으로. ‘json’을 호출하면 json으로 직렬화하여 확장자가 .json 인 요청에 응답하도록 지시합니다. html기본 방식 (협약 및 뷰 사용)으로 .html 요청을 처리하도록하려면 인수없이 호출해야합니다 .

JS와 유사한 의사 코드를 사용하여 다음과 같이 작성할 수 있습니다.

// get an instance to a responder from the base class
var format = get_responder()

// register html to render in the default way
// (by way of the views and conventions)
format.register('html')

// register json as well. the argument to .json is the second
// argument to method_missing ('json' is the first), which contains
// optional ways to configure the response. In this case, serialize as json.
format.register('json', renderOptions)

이 부분은 나에게 지옥을 혼란스럽게했다. 여전히 직관적이지 않습니다. 루비는이 기술을 꽤 많이 사용하는 것 같습니다. 전체 클래스 ( responder)가 메소드 구현이됩니다. 를 활용 method_missing하려면 클래스의 인스턴스가 필요하므로 메소드와 유사한 객체를 전달하는 콜백을 전달해야합니다. 20 년 동안 C와 같은 언어로 코딩 한 사람에게는 이것이 매우 역행적이고 직관적이지 않습니다. 나쁘지 않아! 그러나 그것은 그런 종류의 배경을 가진 많은 사람들이 고개를 숙여 야 할 필요가 있습니다.

ps는 RoR 4.2 respond_to에서 응답자 gem 으로 추출되었습니다 .


답변

이것은 Rails 헬퍼 메소드를 이용하는 Ruby 코드 블록입니다. 아직 블록에 익숙하지 않다면 Ruby에서 블록을 많이 볼 수 있습니다.

respond_toController 클래스 (또는 그 슈퍼 클래스)에 첨부 된 Rails 헬퍼 메소드입니다. View로 전송 될 응답 (브라우저로 이동)을 참조합니다.

귀하의 예제에서 블록은 브라우저가 html 또는 json 데이터를 요청할 때마다 컨트롤러에서보기로 전송되도록 블록의 ‘형식’매개 변수를 전달하여 데이터를 형식화하는 것입니다.

로컬 컴퓨터에 있고 Post 비계를 설정 한 경우을 방문하여 http://localhost:3000/posts모든 게시물을 html 형식으로 볼 수 있습니다. 그러나 다음을 입력 http://localhost:3000/posts.json하면 서버에서 보낸 json 객체에 모든 게시물이 표시됩니다.

이것은 서버에서 json을 앞뒤로 전달 해야하는 자바 스크립트가 많은 응용 프로그램을 만드는 데 매우 편리합니다. 원하는 경우 레일 백엔드에 json API를 쉽게 만들고 Post 컨트롤러의 인덱스보기와 같은 하나의보기 만 전달할 수 있습니다. 그런 다음 Jquery 또는 Backbone (또는 둘 다) 과 같은 자바 스크립트 라이브러리를 사용하여 데이터를 조작하고 고유 한 인터페이스를 만들 수 있습니다. 이를 비동기 UI 라고하며 실제로 인기가 있습니다 (Gmail은 하나임). 그것들은 매우 빠르며 최종 사용자에게 웹상에서 더 데스크탑 같은 경험을 제공합니다. 물론 이것은 데이터 형식의 장점 중 하나 일뿐입니다.

Rails 3 작성 방법은 다음과 같습니다.

    class PostsController < ApplicationController
      # GET /posts
      # GET /posts.xml


      respond_to :html, :xml, :json

      def index
        @posts = Post.all

        respond_with(@posts)
      end

#
# All your other REST methods
#

end

놓음으로써 respond_to :html, :xml, :json클래스의 상단에, 당신은 당신이 컨트롤러가 귀하의 의견에 보내려고하는 모든 형식을 선언 할 수 있습니다.

그런 다음 컨트롤러 방법에서 respond_with (@whatever_object_you_have) 만하면됩니다.

Rails가 자동 생성하는 것보다 코드를 약간 단순화합니다.

이것의 내부 작동에 대해 알고 싶다면

내가 이해 한 내용에서 Rails는 객체를 검사하여 실제 형식이 무엇인지 결정합니다. ‘형식’변수 값은이 내부 검사를 기반으로합니다. Rails는 약간의 정보만으로도 많은 것을 할 수 있습니다. 간단한 @post 또는 : post가 얼마나 멀리 갈지 놀랄 것입니다.

예를 들어 다음과 같은 _user.html.erb 부분 파일이있는 경우 :

_user.html.erb

<li>    
    <%= link_to user.name, user %>
</li>

그런 다음 인덱스 뷰에서 이것만으로 Rails에게 ‘사용자’부분을 찾고 모든 ‘사용자’객체를 반복해야한다는 것을 알 수 있습니다.

index.html.erb

 <ul class="users">
   <%= render @users %>     
 </ul>

Rails에게 ‘user’부분을 찾고 모든 ‘users’객체를 반복해야한다는 것을 알려줍니다.

이 블로그 게시물이 유용하다는 것을 알 수 있습니다 : http://archives.ryandaigle.com/articles/2009/8/6/what-s-new-in-edge-rails-cleaner-restful-controllers-w-respond_with

https://github.com/rails/rails 소스를 살펴볼 수도 있습니다.


답변

내가 아는 것으로부터, respond_to는 ActionController에 연결된 메소드이므로 모든 단일 컨트롤러에서 사용할 수 있습니다. 모든 컨트롤러가 ActionController에서 상속되기 때문입니다. Rails respond_to 메소드는 다음과 같습니다.

def respond_to(&block)
  responder = Responder.new(self)
  block.call(responder)
  responder.respond
end

여기에 표시된 것처럼 블록을 전달합니다 .

respond_to <<**BEGINNING OF THE BLOCK**>> do |format|
  format.html
  format.xml  { render :xml => @whatever }
end <<**END OF THE BLOCK**>>

| 형식 | part는 블록이 기대하는 인수이므로 respond_to 메소드 내에서 사용할 수 있습니다. 어떻게?

글쎄, 우리는 블록에 접두사 &를 붙이고 respond_to 메소드로 전달하면 그 블록을 Proc로 취급합니다. 인수에는 “.xml”, “.html”이 있으므로 호출 할 메소드로 사용할 수 있습니다.

respond_to 클래스에서 기본적으로하는 것은 Responder 클래스의 인스턴스에 대한 “.html, .xml, .json”메서드를 호출하는 것입니다.


답변

respond_to 블록이 실제로 어떻게 작동하는지 이해하고 싶습니다. 어떤 유형의 변수가 형식입니까? 형식 객체의 .html 및 .json 메소드입니까?

내용을 이해하기 위해 format먼저 소스를 respond_to살펴볼 수 있지만, 실제로 살펴보아야 할 것은 retrieve_response_from_mimes 의 코드임을 알게 될 것입니다 .

여기에서 respond_to(코드에서) 전달 된 블록 이 실제로 콜렉터 인스턴스 (블록 내에서 참조 됨 format) 와 함께 호출되고 전달됨을 알 수 있습니다. 콜렉터는 기본적으로 mime 유형의 레일에 대해 알고있는 방법을 기반으로 메소드를 생성합니다 (Rails 시작시 믿고 있음) .

예, .htmland .json는 Collector (일명 format) 클래스 에서 (런타임에) 정의 된 메소드 입니다.


답변

응답자 등록의 메타 프로그래밍 (Parched Squid의 답변 참조)을 사용하면 다음과 같은 멋진 작업을 수행 할 수 있습니다.

def index
  @posts = Post.all

  respond_to do |format|
    format.html  # index.html.erb
    format.json  { render :json => @posts }
    format.csv   { render :csv => @posts }
    format.js
  end
end

csv 행은 /posts.csv를 방문 할 때 각 게시물에서 to_csv가 호출되도록합니다. 이를 통해 레일 사이트에서 데이터를 CSV (또는 다른 형식)로 쉽게 내보낼 수 있습니다.

js 줄은 자바 스크립트 파일 /posts.js (또는 /posts.js.coffee)가 렌더링 / 실행되도록합니다. jQuery UI 팝업을 사용하여 Ajax 지원 사이트를 만드는 가벼운 방법이라는 것을 알았습니다.


답변

어떤 유형의 변수가 형식입니까?

Java POV에서 형식은 익명 인터페이스의 함축입니다. 이 인터페이스에는 각 MIME 유형마다 이름이 지정된 하나의 메소드가 있습니다. 해당 메소드 중 하나를 호출 할 때 (블록을 ​​전달 함) 레일이 사용자가 해당 컨텐츠 유형을 원한다고 생각하면 블록을 호출합니다.

물론,이 익명의 글루 객체는 실제로 인터페이스를 구현하지 않는다는 점입니다. 메소드 호출을 동적으로 잡아서 알고있는 MIME 유형의 이름 인 경우 문제를 해결합니다.

개인적으로, 나는 그것이 이상하게 보인다고 생각합니다 : 당신이 전달하는 블록이 실행 됩니다. 형식 레이블과 블록의 해시를 전달하는 것이 더 의미가 있습니다. 그러나-그것이 RoR에서 수행 된 방식입니다.


답변

Ryan Bigg의 글은 약간 구식입니다.

http://ryanbigg.com/2009/04/how-rails-works-2-mime-types-respond_to

실제로, 그것은 당신이 찾고있는 것보다 조금 더 자세 할 수 있습니다. 결과적으로 MIME 유형이로드되는 방법을 이해해야하는 등 많은 문제가 발생합니다.