18

I am trying to pass a parameter to a login method and I want to switch the base uri based on that parameter.

Like so:

class Managementdb
  include HTTParty

  def self.login(game_name)
        case game_name
        when "game1"
            self.base_uri = "http://game1"
        when "game2"
            self.base_uri = "http://game2"
        when "game3"
            self.base_uri = "http://game3"
        end

    response = self.get("/login")

        if response.success?
      @authToken = response["authToken"]
    else
      # this just raises the net/http response that was raised
      raise response.response    
    end
  end

  ...

Base uri does not set when I call it from a method, how do I get that to work?

Joseph Le Brech
  • 6,541
  • 11
  • 49
  • 84

3 Answers3

19

In HTTParty, base_uri is a class method which sets an internal options hash. To dynamically change it from within your custom class method login you can just call it as a method (not assigning it as if it was a variable).

For example, changing your code above, this should set base_uri as you expect:

...
case game_name
  when "game1"
    # call it as a method
    self.base_uri "http://game1"
...

Hope it helps.

  • If you need to call a class method of a Mixin in your initialize() method, you need to call `YourClassName.mixin_class_method`. – spier Sep 01 '12 at 08:55
  • 24
    In my `initialize` method I had to call `self.class.base_uri "http://example.com"` for it to work. – hamstar May 19 '13 at 09:24
  • 2
    @hamstar but that will change the base_uri for all instances? so, all instances will behave like the last one, right ? – MhdSyrwan Aug 28 '16 at 20:26
  • 1
    Remember to change `base_uri` back to whatever it originally was at the end of the method call if you want to use the instance again with the original value. – Simon L. Brazell Oct 18 '18 at 23:22
10

I can’t comment yet, so here’s an extension to Estanislau Trepat’s answer.

To set the base_uri for all your calls, call the according class method:

self.base_uri "http://api.yourdomain.com"

If you want to have a way of sending only a few calls to a different URI and avoid state errors (forgetting to switch back to the original URI) you could use the following helper:

def self.for_uri(uri)
  current_uri = self.base_uri
  self.base_uri uri
  yield
  self.base_uri current_uri
end

With the above helper, you can make specific calls to other URIs like the following:

for_uri('https://api.anotheruri.com') do
  # your httparty calls to another URI
end
j4zz
  • 272
  • 4
  • 9
  • 1
    I like this approach a lot. However, it's important to not that this will return the `base_uri` as it's return value. That will not help if you need to do something with the return value. To improve this, `response = yield` and then have `response` as the last line to return the response value from the httparty call – jsookiki Apr 25 '17 at 22:17
  • 1
    I like this approach too, and used it... and then realized one more thing. If your `yield` results in an exception, then your `base_uri` will get "stuck" with what should've been a temporary `base_uri`! So using a `begin/rescue/ensure` block to make sure that your `self.base_uri` will be restored even in the case of an exception is a good idea. – nicedawg Jul 28 '17 at 18:47
7

I'm not certain it was implemented when this question was first asked, but if you want to set or override :base_uri on a per-request or per-instance basis, HTTParty request methods (:get, :post, etc) accept options to override class options.

So for OP's example, it could look something like this:

class Managementdb
  include HTTParty

  # If you wanted a default, class-level base_uri, set it here:
  base_uri "http://games"

  def self.login(game_name)
    base_uri =
      case game_name
      when "game1" then "http://game1"
      when "game2" then "http://game2"
      when "game3" then "http://game3"
      end

    # To override base_uri for an individual request, pass
    # it as an option:
    response = get "/login", base_uri: base_uri

    # ...
  end
end

Calling the class method dynamically, as suggested in some of the other answers, changes the base_uri for all requests, which is probably not what you want. It's certainly not thread-safe.

Steve
  • 6,618
  • 3
  • 44
  • 42