1
\$\begingroup\$

So my question is the cleanest way to do #product_panels_for below:

class ProductPanel < Struct.new(:product)
end

class ProductPresenter
  def product_panels_for(selected_products)
    selected_products.map do |product|
      product_panels.find { |panel| panel.product.to_s == product }
    end.
      compact
  end

  def product_panels
    [ProductPanel.new(:iphone), ProductPanel.new(:ipad), ProductPanel.new(:ibidet)]
  end
end

ProductPresenter.new.product_panels_for(['ipad', 'iphone']) # => [<ProductPanel product=:ipad>, <ProductPanel product=:iphone>]

This is obviously simplified, but the point is #product_panels_for should return values from product_panels but in the order given in selected_panels. Maybe this is fine is just feels a bit gangly for something that seems conceptually simpler than that.

To be clear the order is defined by the business, it won't be alphabetical or anything nice.

In case anyone's thinking it, yes, I know in Ruby 2.7 I could replace .map...compact with .filter_map, but I'm not on 2.7 yet.

My previous implementation was:

def product_panels_for(selected_products)
  product_panels.select { |pp| selected_products.include?(pp) }
end

which was nice and clean but didn't preserve the order of selected_products.

If the implementation at the top can't be improved on, is there a nice way to use this previous implementation but chain something after the select that sorts the result so the order matches selected_products? I'm just generally curious about a good way to cleanly sort A so its order matches B where B is a list of values for an attributes of A.

\$\endgroup\$
  • \$\begingroup\$ Did you notice that if you have duplicate products you only get one product panel? If you are assuming a 1-to-` relationship then that's probably fine... \$\endgroup\$ – Garrett Motzner Apr 3 at 1:29
1
\$\begingroup\$

Your solution looks good to me, I tried some alternatives but they end up being a little more verbose and not adding value that makes it worth.

Also, I don't think it is worth adding one more step to order it just to use select.

I would go with your first solution.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.