ruby-on-railsrubyspree

How can I reject or allow only certain keys in a Hash?


I have this method that tries to select out certain field from each hashie::mash object (each image is a hashie::mash object) but not all of them.

  def images
        images = object.story.get_spree_product.master.images
        images.map do |image|
          {
            position: image["position"],
            attachment_file_name: image["attachment_file_name"],
            attachment_content_type: image["attachment_content_type"],
            type: image["type"],
            attachment_width: image["attachment_width"],
            attachment_height: image["attachment_height"],
            attachment_updated_at: image["attachment_updated_at"],
            mini_url: image["mini_url"],
            small_url: image["small_url"],
            product_url: image["product_url"],
            large_url: image["large_url"],
            xlarge_url: image["xlarge_url"]
          }
        end
      end

Is there an easier way to do this?

images is an array of hashie::mash objects.

object.story.get_spree_product.master.images.first.class
Hashie::Mash < Hashie::Hash
[15] pry(#<Api::V20150315::RecipeToolSerializer>)> object.story.get_spree_product.master.images.count
2

Solution

  • You're after Hash#slice:

    def images
      images = object.story.get_spree_product.master.images
      images.map do |image|
        image.slice("position", "attachment_file_name", "...")
      end
    end
    

    This lets you "whitelist" the keys to include in the returned hash. If there are more values to approve than to reject, then you can do the opposite and list only the keys to reject using Hash#except.

    In either case, you might find it easier to store the list of allowable keys as a separate array, and splat it in with *:

    ALLOWED_KEYS = %w(position attachment_file_name attachment_content_type ...)
    
    def images
      object.story.get_spree_product.master.images.map do |image|
        image.slice(*ALLOWED_KEYS)
      end
    end