Rails Как можно запросить определения ассоциаций - PullRequest
2 голосов
/ 01 сентября 2011

У меня много динамического кода, который сохраняет сложные отношения в строке. например:

 "product.country.continent.planet.galaxy.name"

Как я могу проверить, существуют ли эти отношения? Я хочу метод, подобный следующему:

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

Как я мог это реализовать?

Ответы [ 3 ]

2 голосов
/ 01 сентября 2011

Попробуйте это:

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
0 голосов
/ 01 сентября 2011

Если вы действительно храните ассоциации 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")
0 голосов
/ 01 сентября 2011

Если это активные ассоциации записей, вот как вы можете это сделать:

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

И это скажет вам, имеет ли этот конкретный путь все ассоциации.

...