4

我正在使用带有 CarrierWave gem 的 Rails 4.0.0。为什么不在数据库中的属性总是等于nil?它仅在文件 PostUploader 中。最终,数据到达。如何确保这些属性在文件 PostUploader 中可用?

class PostUploader < CarrierWave::Uploader::Base
...
  version :thumb do
    process :crop
  end

  def crop
    model.image_crop # => nil
  end
...
end

模型:

validates :name, presence: true
mount_uploader :image, PostUploader
attr_accessor :crop_x, :crop_y, :crop_w, :crop_h

控制器:

def create
   @post = Post.new(post_params)
   ...
end

def post_params
  params.require(:post).permit(:name, :image, :crop_x, :crop_y, :crop_w, :crop_h)
end

post_params {"name"=>"trololo", "image"=>#, @original_filename="large (3).jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"post[image]\"; filename=\"large (3).jpg\"\r\nContent-Type: image/jpeg\r\n">, "crop_x"=>"0", "crop_y"=>"0", "crop_w"=>"100", "crop_h"=>"200"}

PostUploader 中的模型对象:

Post id: nil, name: "trololo", image: nil, created_at: nil, updated_at: nil

model.crop_x && model.crop_w always => nil

https://github.com/CandyDandy/Realty/tree/development这个项目。

4

1 回答 1

9

我认为原因(基于您的代码)是分配在轨道和载波内串联工作的方式要详细解释,请查看下面的示例

class A
  attr_accessor :abuse_word,:word
  
  def initialize(abuse_word,word)
    self.word = word
    self.abuse_word = abuse_word
  end
  
  def word=(word)
    puts "Abuse word isnt set yet ...."
    puts "This will be nil => #{self.abuse_word}"
    @word = word
  end
end  

程序的 O/p 是这样的

a1 = A.new("BAD","GOOD")
 => Abuse word isnt set yet ....
 => This will be nil => 
# But when you do this
a1.abuse_word
  => "BAD"

现在你可以想象这样的事情发生在这里我的意思

考虑到这是你的哈希

{"name"=>"trololo", "image"=>#, @original_filename="large (3).jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"post[image]\"; filename=\"large (3).jpg\"\r\nContent-Type: image/jpeg\r\n">, "crop_x"=>"0", "crop_y"=>"0", "crop_w"=>"100", "crop_h"=>"200"}

没关系image=(即您的uploader_column=设置器属性被Carrierwave内部调用您定义的处理器覆盖crop

现在,如果您检查 rails,rails 会assign_attributes根据传递给它的散列检查here

现在当 rails 这样做时(通过解析你的参数)

image=[Value obtain from hash]这调用由carrierave定义的方法,该方法在内部调用

处理器crop,因此您会得到所需的结果,因为crop_x&&crop_w总是设置为,nil因为 rails 尚未完成分配 image=并且尚未分配crop_x,并且crop_w因为在上面的哈希中它们在image密钥之后

所以

public_send("crop_x=",[desired_value]) public_send("crop_w=",[desired_value])

当您的代码达到处理图像时尚未processor评估,因此在处理器中评估时,crop您将获得价值nil

解决方案 :

我建议你在你的控制器中做这样的事情

p1 = Post.new(post_params.except("image"))
p1.image = post_params.delete("image")
p1.save

否则(我不建议这样做)确保以某种方式确保crop_x,在 post_params 散列中的键crop_w 之前,image因此您的散列看起来像这样

{"name"=>"trololo","crop_x"=>"0", "crop_y"=>"0", "crop_w"=>"100", "crop_h"=>"200", "image"=>#, @original_filename="large (3).jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"post[image]\"; filename=\"large (3).jpg\"\r\nContent-Type: image/jpeg\r\n">}

您可以清楚地识别两者之间的区别

希望这有帮助

于 2013-07-19T06:36:10.153 回答