CollectionProxy vs AssociationRelation

时间:2015-11-12 23:46:29

标签: ruby-on-rails ruby ruby-on-rails-4 activerecord

我想知道ActiveRecord::Associations::CollectionProxyActiveRecord::AssociationRelation之间的区别。

class Vehicle < ActiveRecord::Base
  has_many :wheels
end

class Wheel < ActiveRecord::Base
  belongs_to :vehicle
end

如果我这样做:

v = Vehicle.new

v.wheels # => #<ActiveRecord::Associations::CollectionProxy []>

v.wheels.all # => #<ActiveRecord::AssociationRelation []>

我不知道它们之间有什么区别以及为什么会这样实现?

2 个答案:

答案 0 :(得分:16)

ActiveRecord::Relation在转换为查询并执行之前是简单的查询对象,另一方面CollectionProxy稍微复杂一些。

首先,你得到了关联扩展,你可能看到了这样的东西,假设一个有很多书的书店模型

class Store < ActiveRecord::Base
  has_many :books do
    def used
      where(is_used: true)
    end
  end
end

这样您就可以使用类似于

的语法在商店中调用旧书
Store.first.books.used

但这是最基本的用途,您可以使用在集合代理中公开的属性,ownerreflectiontarget

所有者

owner提供对持有关联的父对象的引用

反射

reflection对象是ActiveRecord::Reflection::AssocciationReflection的实例,包含关联的所有配置选项。

目标

target是关联集合对象(或has_onebelongs_to时的单个对象。)

使用这些方法,您可以在关联扩展中做一些条件,例如,如果我们有博客,我们会将所有已删除帖子的访问权限授予管理员用户(我知道的蹩脚示例)

Class Publisher < ActiveRecord::Base
  has_many :posts do
    def deleted
      if owner.admin?
        Post.where(deleted: true)
      else
        where(deleted: true)
      end
    end
  end
end

您还可以访问另外两个resetreload方法,第一个方法(reset)清除缓存的关联对象,第二个方法(reload )更常见,用于reset,然后从数据库加载相关对象。

我希望这能解释如何让CollectionProxy课程如此有用

答案 1 :(得分:9)

确定。差异非常简单。

基于您的示例的说明:

// trainingData is an int array with size 600x34 // labels is an int array with size 600, they're the labels corresponding to the trainingData rows cv::Mat trainingDataMat(600, 34, CV_32FC1, trainingData); cv::Mat labelsMat(600, 1, CV_32SC1, labels); cv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create(); cv::Ptr<cv::ml::TrainData> tempData = cv::ml::TrainData::create(trainingDataMat, cv::ml::ROW_SAMPLE, labelsMat); svm->setType(cv::ml::SVM::C_SVC); svm->setKernel(cv::ml::SVM::RBF); svm->setTermCriteria(cv::TermCriteria(cv::TermCriteria::MAX_ITER, 100, 0.001)); // Assign the SVM parameters to the most accurate result svm->trainAuto(tempData); // Train the SVM svm->train(trainingDataMat, cv::ml::ROW_SAMPLE, labelsMat); // predictRow contains a row of data with 34 columns to predict against the SVM Model cv::Mat sampleMat(1, 34, CV_32FC1, predictRow); // Prediction float response = svm->predict(sampleMat); std::cout << response << std::endl; 中的关联代理具有:

  • v.wheels中的对象为@owner;
  • 其轮子的集合为@target;
  • 并且@reflection对象代表v宏。

来自docs

  

Active Record中的关联代理是@owner之间的中间人   和@target。   在需要之前不会加载@target对象。

:has_many

这意味着,只要你调用@target对象上的任何方法(在我们的例子中包含v = Vehicle.new v.wheels # we are not sending any methods to @target object (collection of wheels) # => #<ActiveRecord::Associations::CollectionProxy []> 的集合),就会加载@target,它变为wheels

ActiveRecord_AssociationRelation