【问题标题】:Ruby on Rails - Seed undefined method errorRuby on Rails - 种子未定义方法错误
【发布时间】:2017-07-05 19:52:35
【问题描述】:

在我的应用程序中,我有 PostSlide 模型。 post has many slides & slide belongs_to post.

所有我的幻灯片每张都有一张图片(我使用carrierwave gem 进行上传),但目前我的一些帖子没有图片。

我正在尝试抓取每个帖子的第一张幻灯片,并在seed 的帮助下将其图片上传到帖子。

这是我在seeds.rb中尝试过的:

posts = Post.all.where(image: nil)

posts.each do |post|
  slide = Slide.where(post_id: post).order('created_at DESC').first
  post.update(remote_image_url: slide.image_url(:thumb_huge))
end

posts = Post.all.where(image: nil)

posts.each do |post|
  slide = Slide.where(post_id: post).order('created_at DESC').first
  post.update(remote_image_url: "http://mywebsite.com/uploads/slide/image/#{slide}/#{slide.image}")
end

当我运行它时,我得到:NoMethodError: undefined method image' for nil:NilClass

为什么image 会得到NoMethodError,我该如何解决?

【问题讨论】:

  • 你需要显示代码,但我猜由于post没有图像,你需要先创建关联的模型实例。
  • posts = Post.all.where(image: nil)更改为posts = Post.where(image: nil)

标签: ruby ruby-on-rails-4 seed seeding


【解决方案1】:

您只需在代码中添加一个条件。

 posts.each do |post|
   if post.slides.count > 0
     slide = Slide.where(post_id: post).order('created_at DESC').first
     post.update(remote_image_url: slide.image_url(:thumb_huge))
   end
 end

我希望它对你有用。

【讨论】:

  • 谢谢@Divyang。当我运行您的解决方案时,它只运行select 而不是update这是在我的终端中: Slide Load (0.3ms) SELECT "slides".* FROM "slides" WHERE "slides"."post_id" = 7257 ORDER BY created_at DESC LIMIT 1 01 (0.1ms) BEGIN 01 (0.1ms) 回滚
  • 可以添加完整的查询日志吗?
  • 如前所述,它只是 幻灯片加载 (0.3ms) SELECT "slides".* FROM "slides" WHERE "slides"."post_id" = 7257 ORDER BY created_at DESC LIMIT 1 01 ( 0.1ms) BEGIN 01 (0.1ms) ROLLBACK 唯一改变的是post_id
  • 当我选择 slide 时,它只运行Slide Load 而不是post update。我通过从posts.each do 中删除slide = post.slides.first 进行了测试,然后运行了后期更新。但是如果我把它放在posts.each do之外,我怎么能选择slide
【解决方案2】:

听起来您的post 没有任何幻灯片,所以

Slide.where(post_id: post).order('created_at DESC').first

正在返回nil

只需检查slide 是否存在即可修复它。

posts.each do |post|
  slide = Slide.where(post_id: post).order('created_at DESC').first

  if slide.present? 
     post.update(remote_image_url: "http://mywebsite.com/uploads/slide/image/#{slide}/#{slide.image}")
  end
end

但是,如果您的 belongs_tohas_many 关系设置正确,则可以稍微简化一下:

posts.each do |post|
  if post.slides.any?
     slide = post.slides.first
     post.update(remote_image_url: "http://mywebsite.com/uploads/slide/image/#{slide}/#{slide.image}")
  end
end

或者您可以更进一步,只选择首先包含至少一张幻灯片的帖子:

posts = Post.joins(:slides).uniq

posts.each do |post|
  slide = post.slides.first
  post.update(remote_image_url: "http://mywebsite.com/uploads/slide/image/#{slide}/#{slide.image}")
end

【讨论】:

  • 谢谢@nburkley。当我运行任一解决方案时,它只运行select 而不是update这是在我的终端中: Slide Load (0.3ms) SELECT "slides".* FROM "slides" WHERE "slides"."post_id" = 7257 ORDER BY created_at DESC LIMIT 1 01 (0.1ms) BEGIN 01 (0.1ms) 回滚`
  • 看起来当我选择 slide 时它只运行Slide Load 而不是post update。我通过从posts.each do 中删除slide = post.slides.first 进行测试,然后运行更新后。但是如果我在posts.each do之外有slide,我该如何选择它
  • 如果您在日志中看到ROLLBACK,那是因为update 失败了。可能有一些验证逻辑阻止模型保存。尝试添加一些日志记录或断点以找出无法保存的原因 - 这是如何添加点 binding.pry unless post.update(..your changes here..)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-19
  • 2012-07-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多