0

I have a class I'm using build complex objects via method chaining. I'm new to ruby so I must be missing something obvious here. I expect a hash to be returned that looks like this: {"must"=>[{:match=>{"status_type" : "good"}}, {:match=>{"product_age" : "old"}}]}

But all I get is this: {"must"=>[{:match=>{}}]}

I invoke the following code for the above attempts:

builder = QueryBuilder.new
built = builder.must("status_type").equals("good").must("product_age").equals("old")
built.serialize_this

Here is my class. I'd appreciate any help as I'm pretty new to Ruby.

class QueryBuilder
    attr_accessor :query_hash, :context, :condition_hash

    def initialize
        @query_hash = {}
        @condition_hash = {}
    end

    def serialize_this
        return @query_hash
    end

    def must(search_field)
        @context = "must"
        @condition_hash[search_field] = "temp"
        return self
    end

    def should(search_field)
        @context = "should"
        @condition_hash[search_field] = "temp"
        return self
    end

    def equals(value_field)
        search_field = @condition_hash.keys[0].to_s
        @condition_hash[search_field] = value_field
        match_hash = {}
        match_hash[:match] = @condition_hash
        an_array =[]
        an_array << match_hash
        @query_hash[@context] = an_array
        @condition_hash.clear
    return self
    end
end

Thanks a ton in advance for any light you can shed on my code.

Horse Voice
  • 8,138
  • 15
  • 69
  • 120
  • It is more idiomatic to not explicitly return something at the end of methods. For e.g., in the last line of the `equals` method, just write `self` instead of `return self`. – yihangho Jul 22 '15 at 00:07
  • that shouldn't make a difference. – Horse Voice Jul 22 '15 at 00:08
  • It shouldn't. I was saying that it's more idiomatic, not it will solve the problem. – yihangho Jul 22 '15 at 00:09
  • That's true it is more idiomatic from what I've read. But return makes it easier to read. Some ruby industry experts are actually proponents to using return explicitly from what i have heard – Horse Voice Jul 22 '15 at 00:11
  • True that certain people think it's easier to read. Just thought you should know since you mentioned you're new to Ruby. – yihangho Jul 22 '15 at 00:12

1 Answers1

1

When you do this:

match_hash[:match] = @condition_hash

You don't put a copy of a Hash there, you put a reference to a hash. It's the very same hash that you clear later.

Is Ruby pass by reference or by value?

Community
  • 1
  • 1
wired9
  • 44
  • 1
  • great! that does fix the empty hash problem, but it missed out of status_type => good. It only shows the second hash which is: `{"must"=>[{:match=>{"product_age"=>"old"}}]}` – Horse Voice Jul 22 '15 at 00:53
  • Of course, you instantiate a new array each time and put a value to it. The old array is lost. – wired9 Jul 22 '15 at 01:04
  • got it. I see we have to do this: `(@query_hash[@context] ||= []) << match_hash ` – Horse Voice Jul 22 '15 at 01:19