【问题标题】:Why do I get this "undefined method" error in a Rails model callback, passing the method as a symbol?为什么我在 Rails 模型回调中得到这个“未定义的方法”错误,将方法作为符号传递?
【发布时间】:2014-06-03 13:16:17
【问题描述】:

我有一个名为“Post”的类,当它更改或尚未转换时,它应该将它的降价内容转换为 HTML。我正在尝试将 before_save 回调与 if: 参数一起使用,但是当我尝试运行测试时,无论我传递给 if 时都会出现此错误:

测试于 1:55 开始... rake 中止!
未定义的方法“markdown_changed_or_html_nil?”对于#<Post:0x000000053603d0> C:/Users/user/Documents/GitHub/jw/app/models/post.rb:7:in<class:Post> C:/Users/user/Documents/GitHub/jw/app/models/post.rb:1:in<top (required)> C:/Users/user/Documents/GitHub/jw/test/test_helper.rb:12:in<class:TestCase> C:/Users/user/Documents/GitHub/jw/test/test_helper.rb:5:in<top (required)> C:/Users/user/Documents/GitHub/jw/test/models/post_test.rb:1:in <top (required)>
-e:1:in '加载'
-e:1:in '' 任务:TOP => test:run => test:units(通过使用 --trace 运行任务查看完整跟踪)运行选项:--seed 13458

# 运行测试:

在 0.002000 秒、0.0000 测试/秒、0.0000 断言/秒内完成测试。

0 次测试、0 次断言、0 次失败、0 次错误、0 次跳过

进程以退出代码 1 结束

这是有问题的模型:

class Post < ActiveRecord::Base
  include ActiveModel::Dirty

  before_save :convert_markdown, if: :markdown_changed_or_html_nil?

  belongs_to :user
  validates :user, :title, :content_markdown, { presence: true, on: create }
  validates_associated :user

  protected
    def convert_markdown
      markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, space_after_headers: true, underline: true)
      self.content_html = markdown.render(content_markdown)
    end

    def markdown_changed_or_html_nil?
      content_markdown.changed? || content_markdown.nil?
    end
end

我正在使用 Ruby 2.0.0 和 Rails 4.0.2。

我很可能犯了一个非常基本的错误——我还在学习 Rails。


编辑:这是 post_test.rb

require 'test_helper'

class PostTest < ActiveSupport::TestCase
  test 'saving an empty object fails' do
    new_post = Post.new

    assert_not new_post.save
  end

  test 'validates that given user id corresponds to user' do
    # This will create a user with a given id so we can use the next one up
    test_user = User.create({ name: 'Johnny Test', email: 'johnny.test@example.com',
                            password: 'password', password_confirmation: 'password' })

    # Use next id up - there's no reason it should be taken at this point
    given_user_id = test_user.id + 1

    post_with_invalid_user = Post.new({ title: 'Look at my glorious title', content_markdown: 'Sick content',
                                      user_id: given_user_id })

    assert_not post_with_invalid_user.save
  end

  test 'converts markdown into html' do
    # This is a really really basic test just to make sure a conversion happens
    new_post = Post.new({ title: 'Check out this markdown, baby', content_markdown: 'I got some *sick* markdown',
                        user_id: users(:paul).id })

    assert_equal '<p>I got some <em>sick</em> markdown</p>', new_post.content_html
  end
end

【问题讨论】:

  • 我认为这些方法不需要保护,它们可能不应该是:这可能是你的问题 - 将它们置于受保护意味着它们只能从该类的实例中调用.如果你删除protected,你会遇到同样的问题吗?
  • @MaxWilliams 如果在实际回调中使用,回调将从类的实例中触发。所以这应该不是问题。我认为这更有可能是测试的问题
  • 哦,是的,我之前尝试过 - 我仍然遇到同样的错误。
  • @Baloo,如果我发布测试会有帮助吗?它似乎没有运行,但我猜它可能有一些用处。
  • 我认为这里的错误可能非常具有误导性。请注意错误显示在第 7 行。如果您为 Post 类发布的代码是您的源代码中的真正内容(您没有删除 cmets 或额外的换行符)。然后我会尝试删除您的验证,看看是否适合您。然后从那里去。

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


【解决方案1】:

这可能不是您的主要问题(因为您的错误消息似乎与它无关),但您没有正确使用changed?。 changed? 需要在您的模型对象上调用,可选地以您的属性名称作为前缀。所以你的条件方法应该是这样的:

def markdown_changed_or_html_nil?
  # based on your method name, shouldn't this be:
  # content_markdown_changed? || content_html.nil?
  content_markdown_changed? || content_markdown.nil?
end

在http://api.rubyonrails.org/classes/ActiveModel/Dirty.html 上查找有关Dirty 方法的更多信息。

也

我很确定 Rails 4 没有将 Dirty 移出 ActiveRecord::Base,因此您无需在模型中手动 include ActiveModel::Dirty。

也

这一行:

validates :user, :title, :content_markdown, { presence: true, on: create }

应该是:

validates :user, :title, :content_markdown, { presence: true, on: :create }

【讨论】:

  • 你对那行确实是正确的 - 改变了它。谢谢:)
  • 是的,Benjamin 的评论也为我指明了 :create 符号的方向。谢谢!
【解决方案2】:

validates :user, :title, :content_markdown, { presence: true, on: create }

应该是

validates :user, :title, :content_markdown, presence: true, on: :create

我认为 ruby​​ 只是将 validates :user, :title, :content_markdown 之后的所有内容解释为 validates 函数的一部分。为什么会这样,我对解释器知之甚少,但 ruby​​ 有很多这些“奇怪”的错误。遇到 CaptChrisD 所说的,查看行号总是一个好的开始。

【讨论】:

  • 轰隆隆!知道了!那条线应该是validates :user, :title, :content_markdown, presence: true, on: :create - create 应该是一个符号。谢谢你:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-06
  • 2015-07-06
  • 1970-01-01
  • 1970-01-01
  • 2015-04-23
  • 1970-01-01
相关资源
最近更新 更多