Rails에서 routing parameters와 동일한 이름의 파라미터 처리하기

Rails에서 파라미터 값은 params를 통해 받아옵니다. 이 과정 중 레일즈에서 기본으로 설정한 값이 있어 읽어오지 못하는 경우가 있습니다. 바로 이런 케이스입니다.

Request

GET /testzzz HTTP/1.1
..blahblah...

{"supersecretdata":"no","action":{"params":"data","abcd":"efg"}}

일 때 action의 하위 값들을 꺼내고 싶었으나 params로 action을 찍어보면 사용자가 전송한 json 데이터가 아닌 rails의 action이 나타납니다.

p params[:action]

=>

create

Routing Paramters

이유는 간단합니다. 제가 사용한 action이라는 파라미터 이름과 Rails 자체에서 사용하는 Routing Parameter의 이름과 충돌이 발생하기 때문입니다.

The params hash will always contain the :controller and :action keys, but you should use the methods controller_name and action_name instead to access these values. Any other parameters defined by the routing, such as :id, will also be available. As an example, consider a listing of clients where the list can show either active or inactive clients. We can add a route which captures the :status parameter in a “pretty” URL:

https://edgeguides.rubyonrails.org/action_controller_overview.html

대표적인게 aciton, controller 같은 값들이죠. 보통 이런 값으로 파라미터 이름을 주지 말라곤 하지만, 떄에 따라서 어쩔 수 없이 사용해야할 경우가 있습니다.

Solution

고민하다가 혹시나 해서 Rails의 request(rack) 객체를 하나씩 다 살펴보다 보니 RAW_POST_DATA 에 대해 찾게 되었습니다. 여기에 실제 요청의 값들이 모두 들어가는데, 이 값만 밖으로 꺼낸다면 action이나 controller의 이름으로 값을 받고 처리할 수 있게 됩니다.

한참 구글링하다보니 아주 다행히도 Rails에서 미리 고려하여 메소드로 분리시켜 놓았네요.

p request.raw_post
# {\"intent\":{\"id\":\"h9zks0yo5yr~~~blahblah~~,\"action\":{\"data\":\"user_data\"}

그럼 결국 raw_post의 데이터를 꺼내서 파싱해서 사용한다면 action 이라는 이름의 값을 받을 수 있겠네요.

p params[:action]
# 1: create

action_data = JSON.parse(request.raw_post)[:action]
p action_data
# 2: user_input_data!

잘 됩니다!!

References