新手问题 这个 polymorphic 关系该如何实现?

kingwkb · 2013年06月07日 · 最后由 kingwkb 回复于 2013年06月07日 · 3681 次阅读
class topic

  has_many :pictures, as: :imageable
end

class picture
  belongs_to :imageable, polymorphic: true
  attr_accessible :image
  mount_uploader :image, ImageUpload
end

class PictureController 
  def create
    @picture = Picture.new params[:picture]
    @picture.save
  end
end

class TopicController
  def create
    @topic = Topic.new params[:topic]
    @topic.save
  end
end

结构就是这样的

topic 的 new 中通过 ajax 上传 picture,然后 topic.save 时候需要把 picture 和 topic 关联起来。

我把 topic 中增加一个 picture_ids 属性 然后把上传过的 picture id 提交上来,再用

topic.pictures << Picture.find(picture_id)

这样使用,不行,这个地方报错,不知道该怎么弄了

报了什么错,完整输出贴上来

undefined method `[]' for nil:NilClass Rails.root:

Application Trace | Framework Trace | Full Trace app/uploaders/image_uploader.rb:20:in store_dir' app/controllers/topics_controller.rb:23:increate' Request

Parameters:

{"utf8"=>"✓", "authenticity_token"=>"YzDZeUCANS1dsxpA5rXGn7I+/Xa2m5VhJvCNWtznmgI=", "topic"=>{"title"=>"asdfasdf", "body"=>" <图片 30> <图片 31> ", "picture_ids"=>["30", "31"]}, "commit"=>"提 交"}

app/uploaders/image_uploader.rb:20

贴这一段代码

#3 楼 @Rei

def store_dir
  "uploads/images/#{filename[0...2]}/#{filename[2...4]}/#{filename[4...6]}" # 20
end

我把 topic 中增加一个 picture_ids 属性

这里有写什么代码么?

topic.rb
before_save do
  if picture_ids.present?
    picture_ids.each do |picture_id|
      self.pictures << Picture.find(picture_id)
    end
  end
end

#5 楼 @Rei

#6 楼 @kingwkb ActvieRecord 里本来就提供了 xxx_ids 这个方法了,所以不用自己写。

错误的原因是 store_dir 里面的调用 filename[] 方法,但是 filename 是 nil。不知你的 pictures 表有没有增加 :image 这个字段,没有的话就保存不了 filename。

#7 楼 @Rei 是有 image 这个字段,而且是有内容的,内容就是上传过的文件名

那么 uploader 里面的 filnename 方法有没有改写过?

Loading development environment (Rails 3.2.12)
irb(main):001:0> Picture.first
  Picture Load (0.2ms)  SELECT `pictures`.* FROM `pictures` LIMIT 1
=> #<Picture id: 1, user_id: 1, imageable_id: nil, imageable_type: nil, image: "a7042087847e7544ab2a7942e851768b.jpg", with: 0, height: 0, file_size: 346053, file_name: "1904412le1rv3eoovs5v11.jpg", ip: "", created_at: "2013-06-06 09:28:54", updated_at: "2013-06-06 09:28:54">
irb(main):002:0> t = Topic.first
  Topic Load (0.2ms)  SELECT `topics`.* FROM `topics` LIMIT 1
=> #<Topic id: 1, user_id: 1, neighborhood_id: 1, title: "asdasf", body: "asdfsdf", views_count: 0, replies_count: 0, last_reply_id: nil, last_reply_user_id: nil, last_active_mark: 1370510810, locked: false, locked_at: nil, ip: "127.0.0.1", extendable_id: nil, extendable_type: nil, created_at: "2013-06-06 09:26:50", updated_at: "2013-06-06 09:26:50">
irb(main):003:0> t.pictures << Picture.first
  Picture Load (0.3ms)  SELECT `pictures`.* FROM `pictures` LIMIT 1
   (0.1ms)  BEGIN
   (0.1ms)  ROLLBACK
NoMethodError: undefined method `[]' for nil:NilClass
        from /app/uploaders/image_uploader.rb:20:in `store_dir'

def filename
  if original_filename
    @name ||= Digest::MD5.hexdigest(File.dirname(current_path))
    "#{@name}.#{file.extension}"
  end
end

#9 楼 @Rei 难道这里应该把 if 去掉?

#11 楼 @kingwkb 是的,有问题。你可以试试,我没这样改写过不确定。original_filename 从数据库读出来是拿不到的,只有刚上传的时候有效。

#12 楼 @Rei 不行,current_path 也是空的

需要 登录 后方可回复, 如果你还没有账号请 注册新账号