【问题标题】:Rails 4.2.x - use params hash data in modelRails 4.2.x - 在模型中使用参数哈希数据
【发布时间】:2016-02-11 07:49:04
【问题描述】:

问题 - 有没有办法将params 哈希数据传递/使用到关联模型?

我的应用的要点:

  1. Image 模型 belongs_to User 模型,User 模型 has_many Image 实例。
  2. Image 架构:

    create_table "images", force: :cascade do |t| t.string "文件名" t.string "mime_type" t.binary “内容” t.integer "user_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false 结束

    add_index "images", ["user_id"], name: "index_images_on_user_id"

  3. 在 root_url(即StaticPagesController#home)我有图片上传表单:

  4. Image 我做的模型中:

    def uploaded_file=(initial_data)
      self.filename = initial_data.original_filename
      self.mime_type = initial_data.content_type
      self.content = initial_data.read
      initial_data.rewind
    end
    
  5. 也是自定义验证:

    validate :mime_type
    

def mime_type
    correct_mime = ["image/jpeg", "image/png", "image/gif"]
    unless correct_mime.include? params[:image][:uploaded_file].content_type.chomp
        errors.add(:base, 'must be .jpeg, .png or .gif')
    end
end
  1. 众所周知,来自上传表单的所有查询都会转到 params[:image][:uploaded_file]

6.是否可以将 params[:image][:uploaded_file] 作为具有原始哈希结构的哈希传递给 Image 模型?

我已经尝试过,但没有一个有效:

  • Image 模型中传递显式参数哈希 - 不可行
  • create 操作中定义实例@params_hash = params[:image][:uploaded_file](单独或从自定义类方法内部) - 不行
  • controller#action 中定义常量 - 不行

什么有效? 全局变量 - $variable

这是一种轨道方式吗? -> 查询数据到模型

【问题讨论】:

  • 为什么不能使用mime_type 而不是params[:image][:uploaded_file].content_type?除非我遗漏了一些明显的东西?
  • 次要问题(本例)是如何从模型中的 params hash 中提取上传的文件 content_type,主要问题是 - 如何在适当的模型中为未来的应用正确使用 params hash。
  • @japed - 您能否将它作为您所建议的答案提出来。谢谢!

标签: ruby-on-rails model params


【解决方案1】:

在一个好的 MVC 应用程序中,您的模型不应该知道参数、请求或任何直接用户输入。该模型只是从控制器获取数据并执行业务逻辑并持久化数据。

class Image < ActiveRecord::Base
  belongs_to :user
  validates_inclusion_of :mime_type,
      in: ["image/jpeg", "image/png", "image/gif"],
      message: 'must be .jpeg, .png or .gif'
end

class ImagesController < ApplicationController

  def new
    @image = Image.new
  end

  def create
    @image = Image.new(
      filename: image_params.original_filename
      mime_type: image_params.content_type,
      content: image_params.read
    )
    if @image.save
      redirect_to root_path
    else
      render :new
    end
  end

  private
    def image_params
      params.require(:image).require(:uploaded_image)
    end
end

【讨论】:

  • 所有答案都很好,但我选择接受 max 的解释,因为它最接近对我有用的内容 + 简短的解释,一般来说好的 MVC 应用程序应该做什么
  • 当然,如果您正在为附件开发一个专门的模型,那么将文件对象作为输入并提取内容类型是完全有效的。
【解决方案2】:

模型代码似乎是正确的,这只是您尝试将图像数据获取到模型的方式违反约定。通常你会在控制器中创建一个新的Image 实例,然后设置图像数据,如下所示:

image = user.images.new # If "user" is set to the correct user for the image
image.uploaded_file = params[:image][:uploaded_image]
# ...whatever else you need to do with the image here
image.save

这是一个准系统控制器操作,因此您需要确保 Image 验证并处理验证错误等,但希望这可以帮助您入门。

【讨论】:

    【解决方案3】:

    如果你有

    def uploaded_file=(initial_data)
      self.filename = initial_data.original_filename
      self.mime_type = initial_data.content_type
      self.content = initial_data.read
      initial_data.rewind
    end
    

    所以你将 mime_type 设置为文件的 content_type。

    你为什么不能这样做

    def mime_type
      correct_mime = ["image/jpeg", "image/png", "image/gif"]
      unless correct_mime.include? mime_type.chomp
        errors.add(:base, 'must be .jpeg, .png or .gif')
      end
    end
    

    【讨论】:

    • 看起来合乎逻辑,但我得到的只是浏览器的忙碌状态和:...app/models/image.rb:17:in `mime_type'app/models/image.rb:17:in `mime_type'app/controllers/images_controller.rb:11:in `create'
    • 而我的 ImagesController 第 11 行是:if @image.save
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-12
    • 2017-08-08
    • 1970-01-01
    • 1970-01-01
    • 2019-06-30
    相关资源
    最近更新 更多