2010-12-17 5 views
7

Rails 3 애플리케이션 용 JSONP API를 만들려고합니다. 지금 내 컨트롤러에서 나는이 패턴에 따라 행동을 많이 가지고 :이 그대로 작동하지만respond_with와 같은 메소드를 오버라이드하여 Rails 3 컨트롤러를 마르는 방법?

# This is from my users_controller.rb, as an example 

def index 
    @users = User.all 
    respond_with(@users, :callback => params[:callback]) 
end 

을, 나는 respond_with에 모든 행동의 호출에서 :callback => params[:callback]을 반복하지 않아도하여 건조하고 싶습니다 . 어떻게해야합니까?

업데이트 : 그건 내 위의 코드에 대한 추악한 실현 한 것은이 :callback => params[:callback] 옵션은 어떤 응답 형식뿐만 아니라 JSON을 위해 전달 될 것입니다. 다음 코드는 아마 더 정확 :

def index 
    @users = User.all 
    respond_with(@users) do |format| 
    format.json { render :json => @users, :callback => params[:callback]} 
    end 
end 

이 나는이 문제를 해결하기 위해 고려 한 몇 가지 방법이 있습니다,하지만 난 그들에게 작업하는 방법을 알아낼 수 없습니다 :

  • 재정의 render (아마도 응용 프로그램 컨트롤러에서) :callback => params[:callback] 매개 변수를 자동으로 포함하는 :jsonp 옵션을 사용할 수 있습니다. 이 방법 나는 약간 짧은 다음에 위의 코드를 변경할 수 있습니다 :
def index 
    @users = User.all 
    respond_with(@users) do |format| 
    format.json { render :jsonp => @users} 
    end 
end
  • 내 문제를 해결하기 위해 to_json을 재정의하는 응답을 만듭니다. 그렇게하면 블록을 생략하고 respond_with(@users, :responder => 'MyResponder')으로 전화하여 문제를 해결할 수 있습니다. 또는 plataformatec's responders gem을 사용하는 응용 프로그램 응답자에이 코드를 포함하여 respond_with(@users)만으로도 충분할 수 있습니다.

답변

1

오늘 #rubyonrails IRC 채널에서 나를 도와 주신 samuelkadolph에게 감사드립니다. 그는 편의를 위해 아래에 복사 this gist에서 솔루션 제공 : 나는 아직 내 응용 프로그램이 시도하지 않은

def custom_respond_with(*resources, &block) 
    options = resources.extract_options! 

    if options[:callback] 
    old_block = block 
    block = lambda do |format| 
     old_block.call(format) if block_given? 
     format.json { render :json => [] } 
    end 
    end 

    respond_with(*(resources << options), &block) 
end 

,하지만 나는 그것이 작동해야 볼 수 있습니다. 그는 또한이 메서드의 이름을 변경하고 정의의 마지막 줄을 super(*(resources << options), &block)으로 변경하여 간단히 respond_with 메서드 자체를 재정의 할 수 있음을 확인했습니다.

나는 이것이 나를 위해 일할 것이라고 생각한다. 그러나, 나는 여전히 커스텀 리스폰 더를 작성하는 법을 아는 것에 관심이있다. (더 우아한 해결책이 될 것입니다.)

업데이트 : 나는 이것을 내 응용 프로그램에서 시험해 보았고 약간의 변경이 이루어졌습니다. 이 작업을하려면 내가 위해서는 if params[:callback]if options[:callback]을 변경했다

def custom_respond_with(*resources, &block) 
    options = resources.extract_options! 

    if params[:callback] 
    old_block = block 
    block = lambda do |format| 
     old_block.call(format) if block_given? 
     format.json { render :json => resources, :callback => params[:callback] } 
    end 
    end 

    respond_with(*(resources << options), &block) 
end 

참고 : 여기에 자동으로 JSON 요청에 :callback => params[:callback] 옵션을 제공하도록 설계 내와 ApplicationController의 private 섹션에서 지금 사용하고 버전이며, .

1

이것은 응답기 솔루션에 비해 약간 낮은 기술이지만, 이것을 처리하기 위해 appliation_controller.rb에 개인 메서드를 만드는 방법은 무엇입니까? params 변수를 사용할 수 있으며 @users 객체를 전달할 수 있습니다.

#application_controller.rb 
private 
    def jsonp(my_object) 
    render :json => my_object, :callback => params[:callback] 
    end 

#controller 
def index 
    @users = User.all 
    respond_with(@users) do |format| 
    format.json { jsonp(@users)} 
    end 
end 
8

기술적으로 JSON 결과가 아닌 JavaScript 응답 (JSON-P 콜백에 대한 함수 호출)을 얻으므로 JSON에 콜백 매개 변수를 렌더링하는 것은 올바르지 않습니다. 위의 응답이 명확하게 JSON하지만 자바 스크립트가 아니므로 당신이

render :json => my_object, :callback => params[:callback] 

을 가지고 /users?callback=func에 대한 요청이 들어 오면 그렇다면, 레일, 잘못된 콘텐츠 형식 application/json

func({…}) 

대답한다.

내가 사용하는 솔루션과 함께 또는 콜백없이 올바르게 응답

def respond_with_json(item) 
    respond_with do |format| 
    format.json { render :json => item } 
    format.js { render :json => item, :callback => params[:callback] } 
    end 
end 

입니다. 상기 솔루션이 적용, 우리가 얻을 :

def custom_respond_with(*resources, &block) 
    options = resources.extract_options! 

    if params[:callback] 
    old_block = block 
    block = lambda do |format| 
     old_block.call(format) if block_given? 
     format.js { render :json => resources[0], :callback => params[:callback] } 
    end 
    end 

    respond_with(*(resources << options), &block) 
end 

또한, resources[0]에 대한 수정주의 그렇지 않으면 플랫 연산자의 결과로 추가 배열에 resources 포장 끝낸다.

+0

감사합니다. 아주 좋은 지적입니다! – evanrmurphy

3

이렇게 할 수있는 보석은 rack-jsonp-middleware입니다.

설치 지침은 사이트에 거의 반영되지 않지만 사용하는 약간의 Rails 프로젝트를 만들었습니다. 커밋을 살펴보고 미들웨어를 설치하고 실행하기 위해 수행 한 작업을 확인할 수 있습니다.

https://github.com/rwilcox/rack_jsonp_example

+1

이것은 통합이 거의 필요없는 멋진 보석입니다. 매우 깨끗하고 우아한 솔루션. 너에게 충분히 감사 할 수 없다. – plainjimbo

0

또한이 answer을 확인할 수 있습니다. 기본적으로 컨트롤러에 대한 "기본"respond_to를 만들 수 있으므로 모든 작업을 기본적으로 json에 응답하도록 만들 수 있습니다.

그게 당신이 묻는 것입니까?

관련 문제