2012-06-22 16 views
2

理想我希望網址看起來像:FriendlyId觸發BEFORE模型驗證。我如何解決這個問題?

/用戶/約翰-S

/用戶/富-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_namelast_name觸發。這導致name方法pooping大寫時調用一個零值。

我該怎麼做才能讓我的驗證在FriendlyId被調用之前觸發?並且實際上進一步......爲什麼在建立任何有效性之前,FriendlyId都參與其中?

謝謝!

回答

1

會調用它,因爲塞之前驗證上保存生成:

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

我不太清楚怎樣才能給猴補丁吧。

+0

謝謝你的回覆。 –

+0

任何可能不需要monkeypatching的替代方法的建議? –

+1

我可能會重新定義'name',並且只有在設置了第一個和最後一個時才返回一個有效的名稱。由於驗證,這應該只發生在需要有效的slu before之前。 –

1

我結束了固定礦的方法是這樣的:

def name 
    "#{self.first_name.capitalize} #{self.last_name[0].capitalize}." if first_name.present? && last_name[0].present? 
    end 
+0

兄弟...這只是救了我。謝謝! – marcamillion

1

我覺得要走的路是在before_validation設置的用戶名上創建具有前置到的friendly_id自己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 

希望這有助於!

+0

如果有人使用:歷史,我認爲最好省略'on::create'。因此,讀取'before_validation:set_name,on :: create,prepend:true'的行應該是:'before_validation:set_name,prepend:true'。 – rvg