了解Rails的 "ActionController::Parameters.to_h "

187 阅读1分钟

RailsActionController::Parameters 是一种将数据从请求传递到控制器动作的便捷方式。每一个带参数的请求到控制器动作,都应该被极其谨慎地处理。ActionController::Parameters 是一种便捷的方式。

在Rails 7中,我们现在可以使用.to_h 方法将ActionController::Parameters 对象转换为标准的Hash。这对于想要定制数据传递给控制器的方式的开发者来说是个好消息。 这也意味着我们可以改变参数的行为,而不必在客户端代码上做任何改变。

让我们假设我们已经为一个产品模型搭建了脚手架,将product_name,product_price, 和product_image 作为属性。

class ProductsController < ApplicationController
  def create
    @product = Product.new(product_params)
    respond_to do |format|
      # respond to HTML, JSON
    end
  end
  private

    # Only allow a list of trusted parameters through.
      def product_params
        params.require(:product).permit(:product_name, :product_price, :product_image)
      end
end

现在,如果前端应用程序发送了一个带有适当参数的适当请求,我们应该能够创建一个新的产品。

{
  "product": {
    "product_name": "Ruby Programming 101",
    "product_price": "15.00"
    "product_image": "http://link-to-image-url/image.jpg"
  }
}

但是,如果客户端的请求体有不同的键/值对呢?

{
  "product": {
    "name": "Ruby Programming 101",
    "price": "15.00"
    "image": "http://link-to-image-url/image.jpg"
  }
}

之前

在Rails 7之前,解决这个问题的方法是改变强大的params键,然后在控制器内一个一个地修改键。

class ProductsController < ApplicationController
  def create
    params = product_params
    @product = Product.new
    @product.product_name = params[:product][:name]
    @product.product_price = params[:product][:price]
    @product.product_image = params[:product][:image]

    respond_to do |format|
      # respond to HTML, JSON
    end
  end

  private

    # Only allow a list of trusted parameters through.
    def product_params
      params.require(:product).permit(:name, :price, :image)
    end
end

在这种情况下,需要大量的手动更新,这感觉并不是一个好的做法。

之后

相反,在Rails 7中,我们可以在参数对象上使用to_h 方法,将其转换为标准的Hash,然后在控制器中对键进行修改。 这使得我们可以更智能地处理参数,而不需要大量的手动更新。 to_h 方法根本没有改变参数对象的行为,所以不需要以任何方式修改它。

class ProductsController < ApplicationController
  def create
    @product = Product.new(product_params)

    respond_to do |format|
      # respond to HTML, JSON
    end
  end

  private

    # Only allow a list of trusted parameters through.
    def product_params
      params.require(:product)
            .permit(:name, :price, :image)
            .to_h { |key, value| [:"product_#{key}", value] }
    end
end

这个解决方案看起来和感觉都很像Rails的方式。 干净的代码,简单易懂的逻辑!

上面的例子只是使用ActionController::Parameters的.to_h 方法的一种方式,我们还可以修改params hash的值来。

params = ActionController::Parameters.new(language: "Ruby", framework: "Ruby on Rails", version: "7.0.1")

params.to_h { |key, value| [key, "#{value == "Ruby" ? "Best Programming language on Earth" : value}"] }

=> {"language"=>"Best Programming language on Earth", "framework"=>"Ruby on Rails", "version"=>"7.0.1"}