2

理想情况下,我想要看起来像这样的网址:

/用户/约翰-s

/用户/foo-b

/用户/布拉德-p

我有一个看起来像这样的用户模型:

class User < ActiveRecord::Base
  extend FriendlyId
  friendly_id :name, :use => :slugged

  validates :first_name, :presence => true
  validates :last_name, :presence => true

  # "John Smith" becomes "John S."
  def name
    "#{self.first_name.capitalize} #{self.last_name[0].capitalize}."
  end
end

使用此控制台输出可以最好地解释不良行为:

[15] pry(main)> User.new(first_name: nil, last_name: nil).save!
   (0.2ms)  BEGIN
   (0.1ms)  ROLLBACK
NoMethodError: undefined method `capitalize' for nil:NilClass

问题(终于!:))

似乎发生的事情是在我的验证之前调用 FriendlyId 并被first_name触发last_name。这会导致在name对 nil 值调用 capitalize 时方法大便。

我该怎么做才能在调用 FriendlyId 之前触发我的验证?实际上更进一步......为什么在建立任何有效性之前就涉及FriendlyId?

谢谢!!

4

3 回答 3

2

调用它是因为 slug 是在保存验证之前生成的:

https://github.com/FriendlyId/friendly_id/issues/280

我不太确定猴子补丁需要什么。

于 2012-06-22T03:35:26.953 回答
1

我最终修复我的方式是这样的:

  def name
    "#{self.first_name.capitalize} #{self.last_name[0].capitalize}." if first_name.present? && last_name[0].present?
  end
于 2013-09-06T14:12:52.700 回答
1

我认为要走的路是在创建的 before_validation 中设置用户名,该用户名已预先添加到friendly_id 自己的设置 slug 的 before_validation 回调中:

class User < ActiveRecord::Base
  extend FriendlyId
  friendly_id :name, :use => :slugged

  # 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_name, on: :create, prepend: true

  validates :first_name, :presence => true
  validates :last_name, :presence => true

  # To control when new slugs should be generated
  def should_generate_new_friendly_id?
    new_record? || first_name_changed? || last_name_changed?
  end

  private

  def set_name
    "#{self.first_name.capitalize} #{self.last_name[0].capitalize}."
  end
end

希望这可以帮助!

于 2014-02-06T15:11:18.253 回答