Question

I have the following code:

table([
          ["UnitID", "First Name", "NPS Score", "Comments"],
          *[invite_unitid_arr, invite_name_arr, nps_score_integers_final, comment_arr]
          .transpose.reject{ |x| x[3].empty? }
      ], :position => :center, :column_widths => {0 => 50, 1 => 60, 2 => 60, 3 => 40, 4 => 150}) do
  row(0).style :background_color => 'C0C0C0'
end

I am calling transpose on an array of arrays. I am refactoring this code and I now have an array of model objects:

array = Model.all

How can I rewrite the above, saying "Loop through each model (Model1, Model2, etc.) and create a row with the attributes unit_id,first_name,nps_score,comment like so: Model1[:unit_id],Model1[:first_name],Model1[:nps_score],Model1[:comment]"

Était-ce utile?

La solution

If I understand correctly, you have an array of objects like this:

my_models = [ <MyModel id: 1, unit_id: 123, first_name: "Xxx", nps_score: 100, ...>,
              <MyModel id: 2, unit_id: 456, first_name: "Yyy", nps_score: 200, ...>,
              ...
            ]

And you want an array like this:

[ [ "UnitID", "First Name", "NPS Score", "Comments" ],
  [ 123,      "Xxx",        100,         "..."      ],
  [ 456,      "Yyy",        200,         "..."      ],
  ...
]

All you really need to do is this:

headers = [ "UnitID", "First Name", "NPS Score", "Comments" ]

data = my_models.map do |model|
  [ model.unit_id, model.first_name, model.nps_score, model.comments ]
end

rows = [ headers, *data ]

Or...

data = my_models.map do |model|
         model.attributes.values_at(:unit_id, :first_name, :nps_score, :comments)
       end

(Either way you could make this a one-liner, but mind your code's readability.)

Of course, it's always best to select only the columns you're going to use, so you could just do this (adding whatever where, order etc. calls you need):

my_models = MyModel.select([ :unit_id, :first_name, :nps_score, :comments ]).where(...)
data = my_models.map(&:attributes)
# => [ [ 123, "Xxx", 100, "..." ],
#      [ 456, "Yyy", 200, "..." ],
#      ...
#    ]

In Rails 4 the pluck method takes multiple arguments, making this even easier:

data = MyModel.where(...).pluck(:unit_id, :first_name, :nps_score, :comments)
# => [ [ 123, "Xxx", 100, "..." ],
#      [ 456, "Yyy", 200, "..." ],
#      ...
#    ]

Autres conseils

I am not entirely sure what are you trying to achieve here, but it seems that you are looking for pluck method. Since rails 4 it allows you to pluck multiple columns at once (and by default will pluck all columns). So it seems that:

Model.pluck(:unit_id, :first_name, :nps_score, :comment)

Is what you are looking for - and is actually much better as it is not instantiating new objects and makes just one call to db. . It will return 2d array, one row for each model. If you rather prefer have different values of same column, add transpose on the above.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top