Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails ".pluck" on joined tables with columns of the same name returns one value and then nil

Experiment has_many :features 
Feature belongs_to :experiment

Experiment.where("experiments.id=1")
    .joins(:features)
    .pluck("features.id", "experiments.id")

I expect this to return the id of each features and the id of the experiment.

[
    [1, 1],
    [2, 1],
    [3, 1],
    # ....
]

Instead this returns the id of the experiment and then nil

[
    [1, nil],
    [1, nil],
    [1, nil],
    # ....
]

This is strange in three regards:

  • even though it is an inner join and only an Experiment is returned I am able to pluck columns from features (features.name)
  • everything is fine until a column name is repeated.
  • the last plucked column is reported first, as if the first column is overwritten. Switching the order of pluck switches the returned value.

This seems like a bug but maybe I am doing something wrong. Any tips?

SQL output:

SELECT features.id, experiments.id FROM "experiments" INNER JOIN "features" ON "features"."experiment_id" = "experiments"."id" WHERE (experiments.id=1)

Note. This is a simplified question pertaining to a query looking like:

Experiment.where("experiments.id=1")
    .joins(feature: { child2: { :child3 } })
    .pluck("feature.id, child3.id")
like image 936
nate Avatar asked Sep 24 '14 16:09

nate


People also ask

What is the difference between joins and includes in rails?

What is the difference between includes and joins? The most important concept to understand when using includes and joins is they both have their optimal use cases. Includes uses eager loading whereas joins uses lazy loading, both of which are powerful but can easily be abused to reduce or overkill performance.

What does pluck do in Rails?

Rails has a great, expressive term called pluck that allows you to grab a subset of data from a record. You can use this on ActiveRecord models to return one (or a few) columns. But you can also use the same method on regular old Enumerables to pull out all values that respond to a given key.


1 Answers

This is a bit tricky. Since there's an INNER JOIN the query produces only one id in this instance. You can actually form query the other way around:

Feature.joins(:experiment)
       .where(features: { experiment_id: 1 })
       .pluck(:id, :experiment_id)

Or:

Feature.joins(:experiment)
       .where(experiments: { id: 1 })
       .pluck(:id, :experiment_id)
like image 143
Surya Avatar answered Nov 15 '22 12:11

Surya