【问题标题】:Why does delete not work on full_messages function?为什么 delete 对 full_messages 函数不起作用?
【发布时间】:2015-08-05 13:48:18
【问题描述】:

我有以下代码:

def register_learner
  @event = Event.find(params[:event_id])
  @registation = EventRegistration.new first_name: params[:first_name], last_name: params[:last_name], email: params[:email], event_id: params[:event_id]

  if !@registation.valid?
    @registation.errors.full_messages.delete("Event has already been taken"
    flash[:notice] = @registation.errors.full_messages.to_sentence
    redirect_to(event_path(@event))
  else
    @registation.save
  end
end

注意 @registation.errors.full_messages.delete("Event has already been taken") 行,我试图从 full_messages 数组中删除此特定消息,但它不起作用。下一行是flash消息,还在显示“Event has been taken”的消息。

这是通过控制台进行的健全性检查...

2.1.5 :001 > errors = ["Event has already been taken", "Last name can't be blank"]
 => ["Event has already been taken", "Last name can't be blank"]
2.1.5 :002 > errors.delete "Event has already been taken"
 => "Event has already been taken"
2.1.5 :003 > errors
 => ["Last name can't be blank"]

我错过了什么?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 validation


    【解决方案1】:

    这是因为full_messages 是一个方法,每次调用它都会生成一个新数组。做你想做的事:

    errors = @registation.errors.full_messages
    errors.delete("Event has already been taken")
    flash[:notice] = errors.to_sentence
    

    这回答了问题,现在有一个问题 - 为什么需要这样做?可能有更好的方法。

    一般来说,依赖字符串通常是个坏主意,想象一下半年后您将需要更改此验证的错误消息。你能 100% 确定你会记得在这里更改它吗?如果没有,你有一个错误。

    【讨论】:

    • 谢谢兄弟。是的,我同意它的不稳定。它是一个特定的请求,我们希望验证保持数据库清洁,但我们不想抛出错误消息。
    【解决方案2】:

    好吧,因为 Rails 每次调用该方法时都会使用 errors 重新创建 #full_messages

    def full_messages(options = {})
      @errors.values.inject([]) do |full_messages, errors|
        full_messages + errors.map { |error| error.full_message }
      end
    end
    

    Source

    您可以使用#select 跳过该消息:

    @registation.errors.full_messages.select{|x| x != "Event has already been taken"}.to_sentence
    

    此外,您可以在 #errors.messages(而不是 full_messages)上使用 #delete,因为它们是底层对象的公开属性(不是副本,与 full_messages 一样):

    @registration.errors.messages[:event].delete('has already been taken')
    

    【讨论】:

      猜你喜欢
      • 2020-03-11
      • 1970-01-01
      • 2013-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-06
      相关资源
      最近更新 更多