Ruby on rails Rails如何查询关联定义

Ruby on rails Rails如何查询关联定义,ruby-on-rails,ruby,activerecord,metaprogramming,Ruby On Rails,Ruby,Activerecord,Metaprogramming,我有很多动态代码,它们将复杂的关系保存在一个字符串中。 例: 如何检查这些关系是否存在? 我想要一个如下所示的方法: raise "n00b" unless Product.has_associations?("product.country.planet.galaxy") 如何实现这一点?如果这些是活动记录关联,下面是您可以实现的方法: current_class = Product has_associations = true paths = "country.planet.gala

我有很多动态代码,它们将复杂的关系保存在一个字符串中。 例:

如何检查这些关系是否存在? 我想要一个如下所示的方法:

  raise "n00b" unless Product.has_associations?("product.country.planet.galaxy")

如何实现这一点?

如果这些是活动记录关联,下面是您可以实现的方法:

current_class = Product
has_associations = true
paths = "country.planet.galaxy".split('.')

paths.each |item|
  association = current_class.reflect_on_association( item )
  if association
    current_class = association.klass
  else
    has_associations = false
  end
end

puts has_association

这将告诉您该特定路径是否具有所有关联。

如果确实要将AR关联存储在这样的字符串中,则放置在初始值设定项中的代码应允许您执行所需操作。就我个人而言,我不太明白你为什么要这么做,但我相信你有你的理由

class ActiveRecord::Base
  def self.has_associations?(relation_string="")
    klass = self
    relation_string.split('.').each { |j|
      # check to see if this is an association for this model
      # and if so, save it so that we can get the class_name of
      # the associated model to repeat this step
      if assoc = klass.reflect_on_association(j.to_sym)
        klass = Kernel.const_get(assoc.class_name)
      # alternatively, check if this is a method on the model (e.g.: "name")
      elsif klass.instance_method_already_implemented?(j)
        true
      else
        raise "Association/Method #{klass.to_s}##{j} does not exist"
      end
    }
    return true
  end
end
使用此选项,您需要省去初始模型名称,因此对于您的示例,它将是:

Product.has_associations?("country.planet.galaxy")
试试这个:

def has_associations?(assoc_str)
  klass = self.class
  assoc_str.split(".").all? do |name| 
    (klass = klass.reflect_on_association(name.to_sym).try(:klass)).present?
  end
end

我想我们需要更多的代码,你在字符串中存储了什么样的关联?活动记录关联?刚刚将reflect_on_association(名称)替换为reflect_on_association(名称.to_sym),工作起来很有魅力!
def has_associations?(assoc_str)
  klass = self.class
  assoc_str.split(".").all? do |name| 
    (klass = klass.reflect_on_association(name.to_sym).try(:klass)).present?
  end
end