简体   繁体   English

如何遍历Rails模型的嵌套属性?

[英]How to iterate through a Rails model's nested attributes?

I have a collection of models: Users, Cvs, Skills, Educations, & Experiences. 我收集了以下模型:用户,简历,技能,教育和经验。

# models/user.rb
class User < ApplicationRecord
  has_one :cv
  has_many :skills, through: :cv, inverse_of: :user
  has_many :educations, through: :cv, inverse_of: :user
  has_many :experiences, through: :cv, inverse_of: :user
  ...
end

# models/cv.rb
class Cv < ApplicationRecord
  belongs_to :user
  has_many :skills
  has_many :educations
  has_many :experiences
  ...
end

# models/skill.rb
class Skill < ApplicationRecord
  belongs_to :cv
  belongs_to :user, inverse_of: :skill
end

# models/education.rb
class Education < ApplicationRecord
  belongs_to :cv
  belongs_to :user, inverse_of: :education
end

# models/experience.rb
class Experience < ApplicationRecord
  belongs_to :cv
  belongs_to :user, inverse_of: :experience
end

So, basically, a user has 1 cv and many skills , educations , and experiences that are nested in that cv 因此,基本上,一个user拥有1个cv ,并且嵌套在该cv许多skillseducationsexperiences

A Cv has many attributes other than the nested skills , educations , and experiences . 简历除了嵌套的skillseducationsexperiences ,还具有许多属性。

How can I iterate through all of the attributes in a Cv, including the nested ones? 如何遍历Cv中的所有属性,包括嵌套属性? I tried this: 我尝试了这个:

@user = User.new

@user.build_cv
@user.cv.educations.build
@user.cv.experiences.build
@user.cv.skills.build

@user.cv.attributes.each_pair do |attr, value|
  puts "#{attr}: #{value}"
end

But this just lists the attributes that are directly in the Cv model and not the attributes for the Cv's education , skill , and experience . 但这只是列出了直接在Cv模型中的属性,而不是Cv的educationskillexperience的属性。 What I eventually need to do is iterate through the Cv attributes and it's nested attributes searching for blank values in order to make sure a Cv has been completed. 我最终需要做的是遍历Cv属性,并且嵌套属性搜索空白值,以确保Cv已完成。 I could do that with a simple .blank? 我可以用一个简单的.blank?来做到这一点.blank? on each attribute if I could just figure out how to iterate through them all. 关于每个属性,如果我能弄清楚如何遍历它们的话。

So far, this is the most concise way I came up with to do it, I was just hoping that there was a built-in helper method for something like this: 到目前为止,这是我想出的最简洁的方法,我只是希望有一个内置的帮助器方法来执行以下操作:

def is_complete?
  user = current_user
  user.cv.attributes.each do |attr|
    return false if attr.blank?
  end
  user.cv.skills.each do |skill|
    skill.attributes.each do |sa|
      return false if sa.blank?
    end
  end
  user.cv.educations.each do |edu|
    edu.attributes.each do |ea|
      return false if ea.blank?
    end
  end
  user.cv.experiences.each do |exp|
    exp.attributes.each do |exa|
      return false if edu.blank?
    end
  end
  true
end

You can use reflect_on_all_associations 您可以使用reflect_on_all_associations

Cv.reflect_on_all_associations(:has_many).map(&:name).each do |attr|
  if @user.cv.send(attr).blank?
    # do something
  end
end

If you want to check individual attribute elements... 如果要检查单个属性元素...

Cv.reflect_on_all_associations(:has_many).map(&:name).each do |attr|
  @user.cv.send(attr).each do |item|
    if item.blank?
      # do something
    end
  end
end

or if you're looking at checking each attribute of each item... 或者如果您要检查每个项目的每个属性...

If you want to check individual attribute elements... 如果要检查单个属性元素...

Cv.reflect_on_all_associations(:has_many).map(&:name).each do |attr|
  @user.cv.send(attr).each do |item|
    item.attributes.each_pair do |subattr, value|
      puts "#{item.class}.#{subattr}: #{value}"
    end
  end
end

But a more natural way to do this would be to put validations on the association models. 但是,更自然的方法是将验证放在关联模型上。

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

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