Rails에서 스캐폴드를 생성하면 일반적인 respond_to
가 표시됩니다. 블록:
def destroy
@task.destroy
respond_to do |format|
format.html { redirect_to tasks_url, notice: 'Task was successfully destroyed.' }
format.json { head :no_content }
end
end
그러나 index
와 같은 일부 작업은 , 가지고 있지 않습니다!
# GET /tasks
# GET /tasks.json
def index
@tasks = Task.all
end
이것은 나쁘다. 왜요? /tasks.txt
를 누르면 , 및 txt
앱에서 지원하지 않는 경우 잘못된 오류가 표시됩니다.
ActionView::MissingTemplate (Missing template tasks/index, application/index with {:locale=>[:en], :formats=>[:text], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}
이것은 옳지 않습니다. 고객에게 올바른 파일을 찾을 수 없다는 것이 아니라 지원하지 않는 형식을 요청하고 있다고 알려야 합니다.
UnknownFormat
인 경우 오류가 발생하면 더 나은 응답 코드를 반환할 수 있습니다. 대신 이러한 오류가 관련 없는 다른 오류와 함께 섞여 처리하기가 정말 어려울 것입니다.
respond_to
를 추가할 수 있습니다. index
차단 액션:
# GET /tasks
# GET /tasks.json
def index
@tasks = Task.all
respond_to do |format|
format.html
format.json
end
end
그러면 예상했던 예외 및 오류 코드가 표시됩니다.
Started GET "/tasks.txt" for 127.0.0.1 at 2014-11-03 22:05:12 -0800
Processing by TasksController#index as TEXT
Completed 406 Not Acceptable in 21ms
ActionController::UnknownFormat (ActionController::UnknownFormat):
app/controllers/tasks_controller.rb:8:in `index'
훨씬 낫다. 하지만 respond_to
로 모든 컨트롤러를 어지럽힙니다. 미쳤어. 레일이 아닌 느낌입니다. DRY를 위반합니다. 컨트롤러가 실제로 하고 있는 작업에서 주의를 분산시킵니다.
여전히 잘못된 형식을 올바르게 처리하고 싶습니다. 그래서 당신은 무엇을합니까?
respond_to
바로가기
개체를 렌더링하기 위해 특별한 작업을 수행하지 않는 경우 바로 가기를 사용할 수 있습니다. 작성하는 경우:
def index
@tasks = Task.all
respond_to :html, :json
end
전체 respond_to
를 작성하는 것과 같은 방식으로 작동합니다. index
의 블록 . 작업이 알고 있는 모든 형식에 대해 Rails에 알리는 짧은 방법입니다. 그리고 다른 작업이 다른 형식을 지원하는 경우 많은 코드 없이 이러한 차이를 처리하는 좋은 방법입니다.
컨트롤러 수준에서 형식 처리
그러나 일반적으로 컨트롤러의 각 작업은 동일한 형식. index
인 경우 json
에 응답 new
도 마찬가지입니다. , 및 create
, 그리고 다른 모든 것. 그래서 respond_to
전체 컨트롤러에 영향을 미칩니다.
class TasksController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
respond_to :html, :json
# GET /tasks
# GET /tasks.json
def index
@tasks = Task.all
respond_with(@tasks)
end
그리고 이것은 실제로 작동합니다:
Started GET "/tasks.txt" for 127.0.0.1 at 2014-11-03 22:17:37 -0800
Processing by TasksController#index as TEXT
Completed 406 Not Acceptable in 7ms
ActionController::UnknownFormat (ActionController::UnknownFormat):
app/controllers/tasks_controller.rb:8:in `index'
우리가 얻고자 했던 바로 그 종류의 오류입니다! 그리고 그것을 하기 위해 각 작업을 엉망으로 만들 필요가 없었습니다.
모델의 상태에 따라 다른 작업을 하고 싶을 때가 있습니다. 예를 들어 create
의 경우 , 모델이 유효한지 여부에 따라 양식을 리디렉션하거나 다시 렌더링합니다.
Rails는 이것을 처리할 수 있습니다. 그러나 respond_with
를 사용하여 확인하려는 개체를 알려야 합니다. . 따라서 다음 대신:
def create
@task = Task.new(task_params)
respond_to do |format|
if @task.save
format.html { redirect_to @task, notice: 'Task was successfully created.' }
format.json { render :show, status: :created, location: @task }
else
format.html { render :new }
format.json { render json: @task.errors, status: :unprocessable_entity }
end
end
end
다음과 같이 작성할 수 있습니다.
def create
@task = Task.new(task_params)
flash[:notice] = "Task was successfully created." if @task.save
respond_with(@task)
end
이렇게 하면 응답하는 형식에서 코드를 분리할 수 있습니다. Rails에게 한 번 말할 수 있습니다. 처리하려는 형식. 모든 작업에서 반복할 필요는 없습니다.
응답자 보석
Rails 4.2에는 다음과 같은 캐치가 있습니다. respond_with
더 이상 포함되지 않습니다. 하지만 responders
를 설치하면 되돌릴 수 있습니다. 보석. 그리고 responders
gem은 다른 멋진 기능을 제공합니다.
respond_with
에서 플래시 메시지를 설정할 수 있습니다. responders :flash
를 포함하여 컨트롤러 상단:
class TasksController < ApplicationController
responders :flash
편리하게도 로케일 파일에서 이러한 플래시 메시지의 기본값을 설정할 수 있습니다.
또한 responders
가 있는 경우 Gemfile
의 gem Rails 스캐폴드를 생성하면 생성기가 respond_with
를 사용하여 컨트롤러를 생성합니다. respond_to
대신 :
class TasksController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
respond_to :html, :json
def index
@tasks = Task.all
respond_with(@tasks)
end
def show
respond_with(@task)
end
# ...
이것은 Rails와 함께 제공되는 비계보다 훨씬 깨끗합니다.
마지막으로 특정 컨트롤러 작업에 대한 형식으로만 응답하려는 경우 respond_to
를 호출할 수 있습니다. 여러 번:
class TasksController < ApplicationController
respond_to :html
respond_to :js, only: :create
end
마지막 팁에 대한 의견에 Jeroen Weeink에게 감사드립니다!
respond_with
또는 respond_to
?
다른 형식에 대해 다른 정보를 반환하려는 경우 몇 가지 옵션이 있습니다. 컨트롤러 수준 respond_to
respond_with
와 결합 짧은 컨트롤러를 얻는 좋은 방법입니다. 그러나 모든 컨트롤러 작업이 동일한 형식에 응답하고 Rails가 기대하는 방식으로 작동할 때 가장 도움이 되는 경향이 있습니다.
그러나 때로는 다르게 작동하는 몇 가지 작업을 원할 수 있습니다. 한 줄짜리 respond_to
이러한 상황을 처리하는 데 좋습니다.
더 많은 제어가 필요한 경우 전체 respond_to
를 사용하세요. 블록을 사용하여 원하는 대로 각 형식을 처리할 수 있습니다.
이들 중 하나를 사용하면 지원하지 않는 형식에 대한 요청에 올바른 오류가 발생합니다. 또한 앱과 클라이언트 모두 혼란을 훨씬 덜 수 있습니다.