Rails는 요청의 매개 변수에서 빈 배열을 nil로 변환합니다.
내 앱에는 일반적인 플랫 개체가 아닌 백본 모델이 있으며, 큰 중첩 개체이며 중첩 된 부분을 MySQL 데이터베이스의 TEXT 열에 저장합니다.
Rails API에서 JSON 인코딩 / 디코딩을 처리하여 일부가 문자열 화 된 JSON 텍스트로 저장되어 있어도 외부에서이 하나의 큰 중첩 JSON 객체를 POST / GET 할 수있는 것처럼 보이도록하고 싶었습니다.
그러나 Rails가 마술처럼 빈 배열을 nil
값으로 변환하는 문제가 발생했습니다 . 예를 들어 다음을 게시하면 :
{
name: "foo",
surname: "bar",
nested_json: {
complicated: []
}
}
내 Rails 컨트롤러에는 다음이 표시됩니다.
{
:name => "foo",
:surname => "bar",
:nested_json => {
:complicated => nil
}
}
그래서 내 JSON 데이터가 변경되었습니다 ..
전에이 문제를 겪은 사람이 있습니까? Rails가 내 POST 데이터를 수정하는 이유는 무엇입니까?
최신 정보
그들이하는 곳은 다음과 같습니다.
https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/http/request.rb#L288
그리고 여기에 ~ 왜 그들이 그것을 하는가 :
https://github.com/rails/rails/pull/8862
이제 문제는 중첩 된 JSON API 상황에서이를 가장 잘 처리하는 방법입니다.
많은 검색 끝에 Rails 4.1에서 시작하여 deep_munge "기능"을 완전히 건너 뛸 수 있음을 발견했습니다.
config.action_dispatch.perform_deep_munge = false
문서를 찾을 수 없지만 여기에서이 옵션의 소개를 볼 수 있습니다 : https://github.com/rails/rails/commit/e8572cf2f94872d81e7145da31d55c6e1b074247
이렇게하면 보안 위험이 발생할 수 있습니다 ( https://groups.google.com/forum/#!topic/rubyonrails-security/t1WFuuQyavI).
최근에 알려진 알려진 문제인 것 같습니다 : https://github.com/rails/rails/issues/8832
빈 배열이 어디에 있는지 알고 있다면 항상 params[:...][:...] ||= []
이전 필터에 있을 수 있습니다 .
또는 BackBone 모델을 JSON 메서드로 수정하여 JSON.stringify()
게시되기 전에 nested_json 값을 명시 적으로 문자열 화하고 JSON.parse
before_filter에서 사용하여 수동으로 다시 파싱 할 수 있습니다.
못 생겼지 만 작동합니다.
다음과 같이 직접 매개 변수를 다시 구문 분석 할 수 있습니다.
class ApiController
before_filter :fix_json_params # Rails 4 or earlier
# before_action :fix_json_params # Rails 5
[...]
protected
def fix_json_params
if request.content_type == "application/json"
@reparsed_params = JSON.parse(request.body.string).with_indifferent_access
end
end
private
def params
@reparsed_params || super
end
end
이는 JSON 콘텐츠 유형의 요청을 찾고 요청 본문을 다시 구문 분석 한 다음 params
메서드를 가로 채서 다시 구문 분석 된 매개 변수가있는 경우이를 반환하는 방식으로 작동합니다.
비슷한 문제가 발생했습니다.
빈 문자열을 배열의 일부로 전송하여 수정했습니다.
그래서 이상적으로 당신의 매개 변수는
{
name: "foo",
surname: "bar",
nested_json: {
complicated: [""]
}
}
따라서 빈 배열을 보내는 대신 깊은 뭉침 프로세스를 우회하라는 요청에 항상 ( "")을 전달합니다.
Here's (I believe) a reasonable solution that does not involve re-parsing the raw request body. This might not work if your client is POSTing form data but in my case I'm POSTing JSON.
in application_controller.rb
:
# replace nil child params with empty list so updates occur correctly
def fix_empty_child_params resource, attrs
attrs.each do |attr|
params[resource][attr] = [] if params[resource].include? attr and params[resource][attr].nil?
end
end
Then in your controller....
before_action :fix_empty_child_params, only: [:update]
def fix_empty_child_params
super :user, [:child_ids, :foobar_ids]
end
I ran into this and in my situation, if a POSTed resource contains either child_ids: []
or child_ids: nil
I want that update to mean "remove all children." If the client intends not to update the child_ids
list then it should not be sent in the POST body, in which case params[:resource].include? attr
will be false
and the request params will be unaltered.
I ran into a similar issue and found out that passing an array with an empty string would be processed correctly by Rails, as mentioned above. If you encounter this while submitting a form, you might want to include an empty hidden field that matches the array param :
<input type="hidden" name="model[attribute_ids][]"/>
When the actual param is empty the controller will always see an array with an empty string, thus keeping the submission stateless.
'code' 카테고리의 다른 글
Android의 서비스를 통해 GPS 위치 가져 오기 (0) | 2020.12.09 |
---|---|
Chrome Dev Tools / Firebug의 Less / Sass 디버깅 (0) | 2020.12.09 |
일반 JavaScript를 asm.js로 변환 할 수 있습니까? 아니면 정적으로 유형이 지정된 저수준 언어의 속도를 높이기위한 것입니까? (0) | 2020.12.09 |
GCC의 스택 보호 기능은 언제 어떻게 사용합니까? (0) | 2020.12.09 |
'Alternative'유형 클래스의 의미와 다른 유형 클래스와의 관계로 인해 혼동 됨 (0) | 2020.12.08 |