简体   繁体   English

如何在验证中访问关联的表属性,然后将它们保存在 Rails 上的 Ruby 中

[英]How to access associated table attributes in validation before they are saved in Ruby on Rails

I want to be able to skip validation if a certain attribute is set to false, say status, problem is this model has many nested attributes to them, and they need to skip validation too if status is false.如果某个属性设置为假,我希望能够跳过验证,比如状态,问题是这个 model 有许多嵌套属性,如果状态为假,他们也需要跳过验证。

The purpose of such implantation is that if one wanted to save a draft of there form entry, for whatever reason, having it going through validation could halt them saving it, which is not desirable behavior, and only need to validate entries that are going public by setting status to true.这种植入的目的是,如果有人想保存表单条目的草稿,无论出于何种原因,让它通过验证可能会阻止他们保存它,这是不可取的行为,只需要验证公开的条目通过将状态设置为真。

Example below下面的例子

attribute status located in Article位于文章中的属性状态

model Article
  has_many :sub_articles
  accepts_nested_attributes_for :sub_articles, :allow_destroy => true

  validate_presence_of :body, :unless => Proc.new{|article| !article.status }

model SubArticle
  belongs_to :article
  has_many :foos
  accepts_nested_attributes_for :foos, :allow_destroy => true    

  validate_presence_of :body, :unless => Proc.new{|sub_article| !sub_article.article.status }

model Foo
  belongs_to :sub_article

  validate_presence_of :body, :unless => Proc.new{|foo| !foo.sub_article.article.status }

validation skipping for Article will work, but will not for SubArticle or Foo since they have not been saved an there ids are not set, not making them able to traverse up the associations like in the example. Article 的验证跳过将起作用,但对于 SubArticle 或 Foo 无效,因为它们尚未保存并且未设置 ID,因此无法像示例中那样遍历关联。

Is it possible to access associated table attributes at the point of validation?是否可以在验证时访问关联的表属性?

Any help would be greatly appreciated.任何帮助将不胜感激。

------Updated------ - - - 更新 - - -

The reason validation for SubArticle and Foo fail is because of a SubArticle 和 Foo 验证失败的原因是因为

undefined method `status' for nil:NilClass nil:NilClass 的未定义方法“状态”

This is expected because of the time of validation the article_id or sub_article_id is still nil, I've comfirmed this by doing这是预期的,因为在验证时 article_id 或 sub_article_id 仍然为零,我已经通过这样做确认了这一点

model SubArticle
  belongs_to :article
  has_many :foos

  validate_presence_of :body, :unless => Proc.new{|sub_article| !sub_article.article.check_attributes }

def check_attributes
  pp self
end

witch gives女巫给

#<SubArticle id: nil, body: "", article_id: nil, created_at: nil, updated_at: nil >

-----updated 2---------- ------更新2----------

I forgot and important detail, all of the data for the models are entered at once using a nested form, so at the moment of create, all of the entries on all of the models are only in memory, fixing example code so that would be more obvious.我忘记了重要的细节,模型的所有数据都是使用嵌套形式一次输入的,所以在创建时,所有模型上的所有条目都只在 memory 中,修复示例代码以便更明显。

It is possible but you need to use => instead of = .这是可能的,但您需要使用=>而不是= Like this:像这样:

validate_presence_of :body, :unless => Proc.new{|article| !article.status }

Please look at: http://guides.rubyonrails.org/active_record_validations_callbacks.html#conditional-validation for more information about conditional validations.有关条件验证的更多信息,请查看: http://guides.rubyonrails.org/active_record_validations_callbacks.html#conditional-validation

What about conditionally validating on the ID?有条件地验证 ID 怎么样?

model Article
  has_many :sub_articles

  validate_presence_of :body, :unless => Proc.new{|article| !article.status }

    model SubArticle
      belongs_to :article
      has_many :foos

      validate_presence_of :body, :unless => Proc.new{|sub_article| !sub_article.article_id}

model Foo
  belongs_to :sub_article

  validate_presence_of :body, :unless => Proc.new{|foo| !foo.sub_article_id }

Not sure if this will work but you're essentially only running validation if the parent model has saved and therefore has an ID.不确定这是否可行,但您实际上只是在父 model 已保存并因此具有 ID 时才运行验证。 Won't work for updates though.虽然不适用于更新。 Perhaps a mix between this and your original code would do for update?也许这与您的原始代码之间的混合可以进行更新?

I've got it working, although hack-ish, solved the can't traverse associations since ids are nil by using the:inverse_of我已经让它工作了,虽然 hack-ish,解决了不能遍历关联的问题,因为 id 是 nil 通过使用:inverse_of

model Article
  has_many :sub_articles, :inverse_of => :article

  validate_presence_of :body, :unless => Proc.new{|article| !article.status }

model SubArticle
  belongs_to :article, :inverse_of => :sub_articles
  has_many :foos, :inverse_of => :foo

  validate_presence_of :body, :unless => Proc.new{|sub_article| !sub_article.article.status }

model Foo
  belongs_to :sub_article, :inverse_of => :foos

  validate_presence_of :body, :unless => Proc.new{|foo| !foo.sub_article.article.status }

Which will make the instance being examined in all layers have access to the status attribute.这将使所有层中正在检查的实例都可以访问状态属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM