自定义关联错误消息

时间:2015-12-15 00:52:44

标签: ruby-on-rails

在进行关联验证时是否可以更改is invalid错误?

我的代码:

class Membership < ActiveRecord::Base
  belongs_to :user, inverse_of: :memberships
  belongs_to :team, inverse_of: :memberships

  validate :user_cannot_have_same_team_name

  protected

  def user_cannot_have_same_team_name
    if User.find(user.id).teams.map(&:name).include? team.name
      errors.add :base, "Duplicate team name"
    end
  end
end


class User < ActiveRecord::Base
  has_many :teams, through: :memberships
  has_many :memberships, dependent: :destroy
  # ...
end

class Team < ActiveRecord::Base
  has_many :memberships
  has_many :users, through: :memberships
  has_many :thanks

  validates :name, presence: true

  validate do |team|
    team.memberships.each do |membership|
      membership.errors.full_messages.each do |message|
        errors[:base] << message
      end
    end
  end
end

使用rails console:

[1] pry(main)> team = User.first.teams.new(name: "Wat")
  User Load (0.2ms)  SELECT  `users`.* FROM `users`  ORDER BY `users`.`id` ASC LIMIT 1
=> #<Team:0x007fc38b72dfe8 id: nil, name: "Wat", created_at: nil, updated_at: nil>
[2] pry(main)> team.save
   (0.2ms)  BEGIN
  User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
  Team Load (0.3ms)  SELECT `teams`.* FROM `teams` INNER JOIN `memberships` ON `teams`.`id` = `memberships`.`team_id` WHERE `memberships`.`user_id` = 1
   (0.2ms)  ROLLBACK
=> false
[3] pry(main)> team.errors
=> #<ActiveModel::Errors:0x007fc38b604c48
 @base=#<Team:0x007fc38b72dfe8 id: nil, name: "Wat", created_at: nil, updated_at: nil>,
 @messages={:memberships=>["is invalid"], :base=>["Duplicate team name"]}>

正如您所看到的,即使我设置了自定义消息,也总会出现is invalid错误。请指教。提前谢谢。

1 个答案:

答案 0 :(得分:0)

您最好使用ActiveRecord中的内置validations

class Membership < ActiveRecord::Base
  belongs_to :user, inverse_of: :memberships
  belongs_to :team, inverse_of: :memberships

  validate :user, uniqueness : { scope: :team, message: "Duplicate Team" }
end

对于此错误,您需要对team.name进行验证。为什么这样做可以处理Team id - 实际对象。团队的name应该归因于团队对象,因此您不希望用户拥有多个团队对象(因此使用:uniqueness验证)

-

对于您的Team模型,您实际上可以使用inverse_of -

通过模型提取关联的验证
class Team < ActiveRecord::Base
  has_many :memberships, inverse_of: :team
end

应包含您尝试通过memberships创建的所有新Team的所有验证:

#app/views/teams/new.html.erb
<%= form_for @team do |f| %>
   <%= f.errors... #-> this should have all the errors from membership %>
<% end %>