如何访问参数中通过 JSON 发送的蛇对象的数据?

How can I access the data for the snake object sent through JSON in my params?

使用 javascript,我进行了一次提取 post。

const game = {name: this.player, snake: this.snake, score: this.score, apple: this.apple, skull: this.skull, completed: this.completed}
        return fetch("http://localhost:3000/games", {
        method: "POST",
        headers: {
            "Content-Type": "application/json"},
            body: JSON.stringify(game)
        })
        .then(resp => resp.json())
        .then(json => Game.appendHighScores(json));

我在 Rails 端通过 Ruby 上的参数访问数据。 params[:snake][:body] 的数据应该看起来像 "body"=>[{"x"=>16, "y"=>15}, {"x"=>16, "y"=>14}, {"x"=>16, "y"=>15}]},但是当我将它们输入命令行时,它们看起来像这样:

[<ActionController::Parameters {"x"=>16, "y"=>15} permitted: false>, <ActionController::Parameters {"x"=>16, "y"=>14} permitted: false>, <ActionController::Parameters {"x"=>16, "y"=>15} permitted: false>]

它可以通过索引访问,但我得到了所有东西以及我正在寻找的数据。

我希望它在我输入时看起来像原始参数

<ActionController::Parameters {"name"=>"Don", "snake"=>{"x"=>16, "y"=>15, "direction"=>"down", "speed"=>0, "directions"=>{"left"=>{"x"=>-1, "y"=>0}, "up"=>{"x"=>0, "y"=>-1}, "right"=>{"x"=>1, "y"=>0}, "down"=>{"x"=>0, "y"=>1}}, "image"=>{}, "body"=>[{"x"=>16, "y"=>15}, {"x"=>16, "y"=>14}, {"x"=>16, "y"=>15}]}, "score"=>0, "apple"=>{"image"=>{}, "x"=>2, "y"=>10}, "skull"=>{"image"=>{}, "x"=>12, "y"=>12}, "completed"=>true, "controller"=>"games", "action"=>"create", "game"=>{"score"=>0, "skull"=>{"image"=>{}, "x"=>12, "y"=>12}, "apple"=>{"image"=>{}, "x"=>2, "y"=>10}, "completed"=>true}} permitted: false>

无论如何要将参数作为数组获取,而不用在元素内部 ActionController::Parameters 看起来那么混乱?

因为 Rails 利用 "strong parameters" 你必须列出并允许你想要使用的控制器中的参数。

因为你有一个带有动态键的参数列表,最简单的方法是在开发模式下允许它们像这样:

# in your controller

def game_params
  params.require(:game).tap do |permitted|
    permitted[:name] = params[:name].permit!
    permitted[:snake] = params[:snake].permit!
    permitted[:apple] = params[:apple].permit!
    permitted[:skull] = params[:skull].permit!
    permitted[:completed] = params[:completed].permit!
  end
end

然后您将能够访问您的参数:

game_params[:snake][:body]

在生产中,我会鼓励您将所有密钥列入白名单,例如 this

之所以将所有内容都包裹在 ActionController::Parameters 中是为了您的安全(尤其是批量分配)。您永远不应该相信从互联网发送的数据。这 class 允许您 permit/whitelist 您信任的属性并过滤掉您不信任的所有内容。

snake_params = params.require(:snake).permit(body: [:x, :y])

然后您可以通过简单的 to_h 调用将其转换为散列,这将深入到所有其他也允许的嵌套参数。

snake_data = snake_params.to_h
#=> { "body" => [{"x"=>16, "y"=>15}, {"x"=>16, "y"=>14}, {"x"=>16, "y"=>15}] }

如果您还想包含其他属性,可以将它们添加到 permit 列表中。

.permit(:direction, :speed, directions: {left: [:x, :y], up: [:x, :y], ...}, body: [:x, :y])

有关 permit 的更多信息,我建议查看指南 Action Controller Overview - 4.5 Strong Parameters

如果您不关心是否允许某些参数,您可以使用 permit!.

允许所有参数

请注意,如果直接提取值,则不必允许参数。下面的代码可以在没有任何允许的情况下完美运行。

body = params[:snake][:body]
body.each |body_part|
  x = body_part[:x]
  y = body_part[:y]
  // do stuff with x and y
end