在扩展ActiveRecord :: Base的用户类中实现每个方法

时间:2015-02-18 13:15:46

标签: ruby-on-rails ruby

重新定义each中针对规范类ActiveRecord::Base

User方法

这就是我所知道的

class Rainbow
 include Enumerable
  def each
   yield "red"
   yield "orange"
   yield "yellow"
   yield "green"
   yield "blue"
   yield "indigo"
   yield "violet"
  end
end

r = Rainbow.new

r.select { |a| a.start_with?('r')} #=> ["red"]

确定!!

就像我在User Model

中想要的那样
 class User < ActiveRecord::Base 
  include Enumerable
   def user_ids
    User.all.map(&:id)   ## instead of this i want to write like User.map(&:id) 
   end 
  end

实际上News model中有大量数据,只需要id来自所有记录要写User.all.map(&:id)这样的查询需要花费大量时间。

1:为此,我需要重新定义each method但是如何?但我需要在每种方法中编写什么代码行。

2:以便所有可枚举方法都可以在该classe对象上调用

还有其他办法。

任何帮助都会非常感激。

1 个答案:

答案 0 :(得分:0)

这不是一个好主意。原因是因为ActiveRecord类(以及内部实例方法)既可以作为第一类对象(当您调用Model.foo时)或通过ActiveRecord::Relation对象和关联代理进行访问。

很有可能在某些时候会导致一些难以察觉的冲突。

尝试做你想做的事并没有什么好处。实际上,方法

class User < ActiveRecord::Base 
  include Enumerable

  def user_ids
    User.all.map(&:id)
  end 
end

已经可以改写为

def user_ids
  User.ids
end 

这是

的缩短版
def user_ids
  User.pluck(:id)
end 

请注意,pluckids都只选择必填字段,因此它们比在加载所有记录和映射字段时更有效(在Ruby级别和数据库级别)。“ / p>

没有提到你的代码可能是错误的。实际上,您正在定义一个应该被称为

的实例方法
User.new.user_ids

而您可能希望将其用作

User.user_ids

因此您可以将其定义为

class User < ActiveRecord::Base 

  def self.user_ids
    # User it's implicit, its the current scope
    ids
  end 
end

您可以定义each

class User < ActiveRecord::Base 
  include Enumerable

  def each(&block)
    # all returns a lazy-evaluated scope
    # that responds to each
    # Note that .each will trigger a query.
    # In this case, that's effectively equivalent to to_a.each
    all.each(&block)
  end 
end

但它不会给你带来任何好处。此外,这将始终在您调用方法时触发查询,跳过活动记录的非常方便的延迟加载功能。

事实上,ActiveRecord::Relation也可以作为性能改进来利用延迟加载。


最重要的是,如果您的目标是不键入User.all.map(&:id),那么请使用自定义方法,或有效使用Rails API。

User.all.map(&:id)

可以写成

User.pluck(:id)

相当于

User.ids
包含在方法中的

变为

class User
  def self.user_ids
    ids
  end
end

User.user_ids