【问题标题】:rspec shoulda matchers with friendly id custom slug not working具有友好 id 自定义 slug 的 rspec shoulda 匹配器不起作用
【发布时间】:2015-03-20 01:20:37
【问题描述】:

我有一个带有友好 id 的自定义 slug 的模型:

# == Schema Information
#
# Table name: blogs
#
#  id               :integer          not null, primary key
#  title            :string           not null
#  content          :text             not null
#  is_published     :boolean          default("false"), not null
#  slug             :string
#  publishing_date  :datetime
#  tags             :text             default("{}"), not null, is an Array
#  meta_keywords    :text             default("{}"), not null, is an Array
#  meta_description :text
#  page_title       :string(70)
#  author_id        :integer          default("1")
#  blog_category_id :integer          default("1")
#  author_type      :integer          default("0"), not null
#  created_at       :datetime         not null
#  updated_at       :datetime         not null
#

class Blog < ActiveRecord::Base
  enum author_type: [:content_contributor]
  enum publishing_status: [:reviewing, :accepted, :rejected]
  include FriendlyId
  friendly_id :title_and_category, use: [:slugged, :history]
  has_attached_file :featured_image,  styles: { large: '600x600>', medium: '300x300>',  thumb: '100x100>' }, default_url: 'No_image.jpg.png'
  validates_attachment_content_type :featured_image,  content_type: /\Aimage\/.*\Z/
  belongs_to :author, class_name: 'ContentContributor', foreign_key: 'author_id', inverse_of: :blogs
  belongs_to :featured_product, class_name: 'Product', foreign_key: 'featured_product_id', inverse_of: :blogs
  belongs_to :blog_category, inverse_of: :blogs
  belongs_to :deleted_by, class_name: 'User', foreign_key: 'deleted_by_id'
  validates :author, presence: true
  validates :author_type, presence: true
  validates :title, presence: true
  validates :content, presence: true
  validates :tags, presence: true
  validates :meta_keywords, presence: true

  def title_and_category
    "#{blog_category.name} #{title}"
  end
end

我已经为这样的模型编写了规范:

it { should define_enum_for(:author_type) }
  it { should define_enum_for(:publishing_status) }
  it { should belong_to(:author).class_name("ContentContributor").with_foreign_key("author_id").inverse_of(:blogs) }
  it { should belong_to(:featured_product).class_name("Product").with_foreign_key("featured_product_id").inverse_of(:blogs) }
  it { should belong_to(:deleted_by).class_name("User").with_foreign_key("deleted_by_id") }
  it { should belong_to(:blog_category).inverse_of(:blogs) }
  it { should validate_presence_of(:author) }
  it { should validate_presence_of(:author_type) }
  it { should validate_presence_of(:title) }
  it { should validate_presence_of(:content) }
  it { should validate_presence_of(:tags) }
  it { should validate_presence_of(:meta_keywords) }

上述失败并出现以下错误:

失败:

  1) Blog should require author to be set
     Failure/Error: it { should validate_presence_of(:author) }
     NoMethodError:
       undefined method `name' for nil:NilClass
     # ./app/models/blog.rb:41:in `title_and_category'
     # ./spec/models/blog_spec.rb:33:in `block (2 levels) in <top (required)>'

  2) Blog should require author_type to be set
     Failure/Error: it { should validate_presence_of(:author_type) }
     NoMethodError:
       undefined method `name' for nil:NilClass
     # ./app/models/blog.rb:41:in `title_and_category'
     # ./spec/models/blog_spec.rb:34:in `block (2 levels) in <top (required)>'

  3) Blog should require title to be set
     Failure/Error: it { should validate_presence_of(:title) }
     NoMethodError:
       undefined method `name' for nil:NilClass
     # ./app/models/blog.rb:41:in `title_and_category'
     # ./spec/models/blog_spec.rb:35:in `block (2 levels) in <top (required)>'

  4) Blog should require content to be set
     Failure/Error: it { should validate_presence_of(:content) }
     NoMethodError:
       undefined method `name' for nil:NilClass
     # ./app/models/blog.rb:41:in `title_and_category'
     # ./spec/models/blog_spec.rb:36:in `block (2 levels) in <top (required)>'

  5) Blog should require tags to be set
     Failure/Error: it { should validate_presence_of(:tags) }
     NoMethodError:
       undefined method `name' for nil:NilClass
     # ./app/models/blog.rb:41:in `title_and_category'
     # ./spec/models/blog_spec.rb:37:in `block (2 levels) in <top (required)>'

  6) Blog should require meta_keywords to be set
     Failure/Error: it { should validate_presence_of(:meta_keywords) }
     NoMethodError:
       undefined method `name' for nil:NilClass
     # ./app/models/blog.rb:41:in `title_and_category'
     # ./spec/models/blog_spec.rb:38:in `block (2 levels) in <top (required)>'

我删除了自定义名称构建的代码,以上所有内容都通过了,但没有构建自定义 slug。应该改变什么?

【问题讨论】:

    标签: ruby-on-rails rspec shoulda friendly-id


    【解决方案1】:

    这是因为 FriendlyId 使用 before_validation callback 来设置 slug。在您在类中定义的任何 before_validation 回调之前调用此方法。

    title_and_category 方法在您的其他验证之前调用。

    要解决此问题,您可以在设置 before_validation 回调之后调用friendly_id,或者您可以在friendly_id 之前添加您的方法:

    解决方案 1

    假设您有一个 title_and_category 列而不是一个方法。

    # Make sure to prepend it so that it runs before Friendly_id's own callback
    # http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
    
    before_validation :set_title_and_category, prepend: true
    
    def set_title_and_category
       self.title_and_category = "#{blog_category.name} #{title}"
    end
    

    解决方案 2

    def title_and_category
        "#{blog_category.name} #{title}" if blog_category
    end
    

    解决方案 3

    我看到你正在使用shoulda-matchers,你可以使用shoulda callback matchers 并在你的测试中添加这个代码

    it { should callback(:generate_slug).before(:validation) } 
    

    【讨论】:

    • 答案中的解决方案二得到了解决。我最初尝试了 3,但没有成功。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-18
    • 2016-05-15
    • 2013-08-10
    • 2016-11-21
    • 2014-10-24
    • 2013-09-12
    • 2012-11-28
    相关资源
    最近更新 更多