shimoju / metabase-ruby

Ruby client library for Metabase API
MIT License
28 stars 27 forks source link

how to get card data (with solution) #79

Open igorkasyanchuk opened 1 year ago

igorkasyanchuk commented 1 year ago

Want to get card data. Found one solution. But want to ask if there is a proper way?

client = Metabase::Client.new(
  url: 'domain',
  token: "token"
)
client.current_user
# Sniffer.enable! for debugging gem
parameters = [{"type":"string/=","value":["SOME"],"target":["dimension",["template-tag","property"]]}.deep_stringify_keys]
client.query_card(4329, format: :json, parameters: parameters.to_json)

AND

in lib/metabase/connection.rb comment one line

    def connection
      @connection ||= Faraday.new(url: @url) do |c|
        c.response :logger, ::Logger.new(STDOUT), bodies: true
        # c.request :json, content_type: /\bjson$/
        c.response :json, content_type: /\bjson$/
        c.request :url_encoded, content_type: /x-www-form-urlencoded/
        c.adapter Faraday.default_adapter
        c.headers['User-Agent'] =
          "MetabaseRuby/#{VERSION} (#{RUBY_ENGINE}#{RUBY_VERSION})"
      end
    end
varg90 commented 1 year ago

This query_card method (and other methods with export_format) does not seem to work by its definition. Metabase API expects to receive data as a url encoded form and this gem sends this request body as a json.

The way to solve this would be (lib/metabase/connection.rb:33):

      encoded_body =  params.delete(:encoded_body)

      response = connection.public_send(method, path, params) do |request|
        request.headers['X-Metabase-Session'] = @token if @token
        headers&.each_pair { |k, v| request.headers[k] = v }
        request.body = encoded_body if encoded_body
      end

Now you can just do

encoded_params = URI.encode_www_form({ parameters: params.to_json }).gsub('+', '%20')
client.query_card(
  CARD_ID,
  format: :json,
  encoded_body: encoded_params,
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  }
)

and get the correct response.

I may do the PR later if I'll get a chance (just because it also requires to update specs and the readme)