Jwan622
Jwan622

Reputation: 11639

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

Upvotes: 3

Views: 2316

Answers (2)

Peter H. Boling
Peter H. Boling

Reputation: 584

You can also use Hashie's StrictKeyAccess. It makes a Ruby Hash behave like Python's Dictionary, raising an error when missing keys are accessed.

    #     class StrictKeyAccessHash < Hash
    #       include Hashie::Extensions::StrictKeyAccess
    #     end
    #
    #     >> hash = StrictKeyAccessHash[foo: "bar"]
    #     => {:foo=>"bar"}
    #     >> hash[:foo]
    #     => "bar"
    #     >> hash[:cow]
    #       KeyError: key not found: :cow

Upvotes: 1

user229044
user229044

Reputation: 239220

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

Upvotes: 11

Related Questions