Cách lấy các giá trị của một cột vào một mảng


80

Ngay bây giờ tôi đang làm điều gì đó như thế này để chọn một cột dữ liệu:

points = Post.find_by_sql("select point from posts")

Sau đó, chuyển chúng cho một phương thức, tôi muốn phương thức của mình vẫn là bất khả tri và bây giờ phải gọi hash.point từ bên trong phương thức của tôi. Làm cách nào để tôi có thể nhanh chóng chuyển đổi dữ liệu này thành một mảng và chuyển tập dữ liệu vào phương thức của mình, hoặc có cách nào tốt hơn không?

Câu trả lời:


190

Trong Rails 3.2 có một phương pháp gảy cho việc này

Chỉ như thế này:

Person.pluck(:id) # SELECT people.id FROM people
Person.pluck(:role).uniq # unique roles from array of people
Person.distinct.pluck(:role) # SELECT DISTINCT role FROM people SQL
Person.where(:confirmed => true).limit(5).pluck(:id)

Sự khác biệt giữa uniq và riêng biệt


Làm cách nào để một mảng có thể kế thừa thứ tự của kết quả truy vấn với pluck?
Franklin stine

3
Post.order (: điểm) .pluck (: điểm) là giải pháp. Cảm ơn.
Franklin stine

6
Để nhổ id có một phương pháp đặc biệt: Person.ids.
shock_one

Ngoài ra nhìn vào viên ngọc Valium Ernie Miller github.com/ernie/valium đặc biệt là nếu bạn đang ở trên một Rails cũ hoặc muốn nhiều cột
James Daniels

Tính đến Rails 5.0, nó hiện đang khuyến khích sử dụng distinctthay vì uniq: như vậyPerson.distinct.pluck(:role)
David

15

Bạn nên sử dụng pluckphương pháp như @alony đã đề xuất. Nếu bạn gặp khó khăn trước Rails 3.2, bạn có thể sử dụng selectphương thức ActiveRecord cùng với Array#map:

Post.select(:point).map(&:point)
#=> ["foo", "bar", "baz"] 

trước Ruby 1.9, bạn phải làm như .map{|x| x.title}vậy, vì Symbol#to_proc(bí danh của toán &tử một ngôi) không được định nghĩa trong các phiên bản trước của Ruby.


Cảm ơn. Tôi thấy bạn nhận xét về phương pháp Pluck mới. Bạn có thể làm điều tương tự với điều đó?
Franklin stine

Có, nếu bạn đọc kỹ câu trả lời của @ alony, bạn sẽ nhận thấy rằng cô ấy đã bao gồm một ví dụ thực hiện điều này.
Patrick Oscity

5

Nếu bạn thấy định nghĩa của select_values, thì nó sử dụng 'map (&: field_name)'

  def select_values(arel, name = nil)
    result = select_rows(to_sql(arel), name)
    result.map { |v| v[0] }
  end

Cách Rails phổ biến và chung để thu thập tất cả các giá trị trường trong mảng như sau:

points = Post.all(:select => 'point').map(&:point)

Điểm tốt. Cảm ơn bạn. Điều này hoạt động tốt và cho phép tôi vẫn áp dụng thứ tự và những thứ khác cho truy vấn, không giống như ví dụ Post.select.
Franklin stine

Tôi không đồng ý với bạn, @franklinstine: Post.select(:point).limit(1)thực hiện SELECT point FROM "posts" LIMIT 1trong khi Post.all(:select => :point).limit(1)tăng a NoMethodError. Nêu tôi sai vui long chân chỉnh tôi.
Patrick Oscity

Tôi đồng ý với bình luận của cậu. Nhưng tôi không nhận được nơi đề cập đến trong bài viết để sử dụng: Post.all (: chọn =>: điểm) .limit (1) Ofcourse nó sẽ cho lỗi "Phương pháp xác định giới hạn ''"
Vik

@franklinstine nói ông thích phương pháp của bạn bởi vì anh ta có thể chuỗi báo cáo khác sau nó, tôi chỉ muốn làm cho rõ ràng rằng đây là không đúng sự thật
Patrick Oscity

Có @padde bạn đã suy luận sai. Tôi đã nói rằng bạn vẫn có thể áp dụng lệnh và các câu lệnh truy vấn khác như: Post.all (: select => 'score',: order => 'score ASC'). Map (&: score).
Franklin stine

2
points = Post.all.collect {|p| p.point}

2
Điều này hoạt động, nhưng bạn chọn tất cả các trường từ cơ sở dữ liệu và sau đó lọc kết quả trong Ruby trong khi selectcâu lệnh chỉ tìm nạp các cột được chỉ định.
Patrick Oscity
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.