簡體   English   中英

Rails - 給定一組用戶 - 如何獲得電子郵件的輸出?

[英]Rails - given an array of Users - how to get a output of just emails?

我有以下內容:

@users = User.all

用戶有幾個字段,包括電子郵件

我希望能夠獲得所有@users電子郵件的列表。

我試過了:

@users.email.all but that errors w undefined

想法? 謝謝

(按流行需求,發布作為真實答案)

我不喜歡fl00r的解決方案是它在數據庫中為每條記錄實例化一個新的User對象; 這只是不規模。 這對於一個只有10封電子郵件的表來說非常棒,但是一旦你開始涉及成千上萬,你就會遇到問題,主要是Ruby的內存消耗。

通過在模型上使用connection.select_values以及一點ARel優點,可以解決這個小問題:

User.connection.select_values(User.select("email").to_sql)

這將為您提供數據庫中電子郵件地址的直接字符串。 沒有對用戶對象User.select("email")並且比直接的User.select("email")查詢更好地擴展,但我不會說它是“最佳規模”。 可能有更好的方法來做到這一點,我還沒有意識到。

問題的關鍵是:一個String對象將使用的方式較少的內存比User對象,這樣你可以有更多的人。 它也是一個更快的查詢,並沒有很長的路要走(運行查詢,然后映射值)。 哦, map也需要更長的時間。

如果您使用的是Rails 2.3 ...

然后你必須手動構建SQL,我很遺憾地說。

User.connection.select_values("SELECT email FROM users")

只是提供了Rails 3提供的幫助程序的另一個示例。

我仍然發現connection.select_values是一個有效的方法來解決這個問題,但我最近發現了一個內置在Rails中的默認AR方法,可以為你做這個: pluck

在您的示例中,您需要執行的所有操作都是:

User.pluck(:email)

select_values方法在極大的數據集上可以更快,但那是因為它沒有對返回的值進行類型轉換。 例如,布爾值將返回它們如何存儲在數據庫中(如1和0)並且不是真的| 假。

pluck方法適用於ARel,因此您可以菊花鏈式連接:

User.order('created_at desc').limit(5).pluck(:email)
User.select(:email).map(&:email)

雖然我經常訪問SO,但我今天才注冊。 不幸的是,這意味着我沒有足夠的聲譽來評論其他人的答案。

回顧上面Ryan的回答,你可以擴展ActiveRecord :: Base來創建一個方法,允許你以更干凈的方式在整個代碼中使用它。

在config / initializers中創建一個文件(例如,config / initializers / active_record.rb):

class ActiveRecord::Base
  def self.selected_to_array
    connection.select_values(self.scoped)
  end
end

然后,您可以在ARel聲明的末尾鏈接此方法:

User.select('email').selected_to_array
User.select('email').where('id > ?', 5).limit(4).selected_to_array

只需使用:

User.select("email")

使用它來獲取所有電子郵件的數組:

@users.collect { |user| user.email }
# => ["test@example.com", "test2@example.com", ...]

或簡寫版本:

@users.collect(&:email)

您應該避免使用User.all.map(&:email)因為它會創建大量消耗大量內存的ActiveRecord對象,其中很大一部分將不會被Ruby的垃圾收集器收集。 它也是CPU密集型的。

如果您只想從數據庫中只收集一些屬性而不犧牲性能,高內存使用率和CPU周期,請考慮使用Valium。

https://github.com/ernie/valium

以下是從數據庫中的所有用戶獲取所有電子郵件的示例。

User.all[:email]

或僅適用於訂閱或其他任何用戶。

User.where(:subscribed => true)[:email].each do |email|
  puts "Do something with #{email}"
end

出於上述原因,使用User.all.map(&:email)被認為是不好的做法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM