Як отримати значення одного стовпця в масив


80

Зараз я роблю щось подібне, щоб вибрати один стовпець даних:

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

Потім передаючи їх методу, я хотів би, щоб мій метод залишався агностичним, і тепер мені потрібно викликати hash.point зсередини мого методу. Як я можу швидко перетворити це в масив і передати набір даних своєму методу, чи є кращий спосіб?

Відповіді:


190

У Rails 3.2 є метод тельбухи для цього

Просто так:

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)

Різниця між унікальним та різним


Як масив може успадкувати впорядкування результату запиту за допомогою pluck?
Franklin Stine

3
Post.order (: score) .pluck (: score) - це рішення. Дякую.
franklin stine

6
Для того, щоб зривати йду є спеціальний метод: Person.ids.
shock_one

Також вивчіть дорогоцінний камінь Ерні Міллера Valium github.com/ernie/valium, особливо якщо ви перебуваєте на старіших рейках або хочете кілька стовпців
James Daniels

Що стосується Rails 5.0, то зараз рекомендується використовувати distinctзамість uniq: soPerson.distinct.pluck(:role)
Девід

15

Ви повинні використовувати pluckметод, як @alony запропонував. Якщо ви застрягли перед Rails 3.2, ви можете використовувати selectметод ActiveRecord разом із Array#map:

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

до Ruby 1.9 вам все-таки потрібно було це зробити .map{|x| x.title}, оскільки Symbol#to_proc(псевдонім унарного &оператора) не визначений у попередніх версіях Ruby.


Дякую. Я бачив, як ви прокоментували новий метод Pluck. Чи можете ви зробити те саме з цим?
Франклін Стін

Так, якщо ви уважно прочитаєте відповідь @ alony, ви помітите, що вона вже включила приклад, який це робить.
Патрік Оссіті

5

Якщо ви бачите визначення select_values, тоді воно використовується за допомогою "map (&: field_name)"

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

Загальний і загальний спосіб Rails зібрати всі значення полів у масиві такий:

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

Влучне зауваження. Дякую. Це чудово працює, і дозволяє мені все ще застосовувати порядок та інші речі до запиту, на відміну від прикладу Post.select.
Franklin Stine

Я не згоден з тобою, @franklinstine: Post.select(:point).limit(1)виступає, SELECT point FROM "posts" LIMIT 1тоді як Post.all(:select => :point).limit(1)піднімає a NoMethodError. Будь ласка, виправте мене, якщо я помиляюся.
Патрік Оссіті

Я згоден з вашими коментарями. Але я не дійшов, де згадати у дописі, щоб використовувати: Post.all (: select =>: point) .limit (1) Звичайно, це дасть помилку "невизначений метод` limit '"
Вік

@franklinstine сказав, що віддає перевагу вашому методу, тому що він міг би ланцюг інших тверджень після нього, я просто хотів пояснити, що це неправда
Патрік Оссіті

Так @padde, ви неправильно вивели. Я говорив, що ви все ще можете застосувати замовлення та інші запити, такі як: Post.all (: select => 'score',: order => 'score ASC'). Map (&: score).
Франклін Стін

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

2
Це працює, але ви вибираєте всі поля з бази даних, а потім фільтруєте результат у Ruby, тоді як selectоператор отримує лише вказані стовпці.
Патрік Оссіті
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.