I have here a model helper named GmailGcalendar
I have multiple actions in 2 models namely gmail.rb and pivotaltracker.rb
They do the same functions, but the only difference is the connection url.
In my lib helper:
def connection_url
if API::Pivotaltracker
'https://www.pivotaltracker.com'
else
'https://accounts.google.com'
end
end
def my_connections
connection_name ||= Faraday.new(:url => "#{connection_url}" , ssl: {verify: false}) do |faraday|
faraday.request :url_encoded # form-encode POST params
faraday.response :logger # log requests to STDOUT
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
end
puts "####"
puts connection_url
end
And in my gmail.rb
def connection
my_connections
end
As well as my pivotaltracker.rb
def connection
my_connections
end
Now they have different connection url.
Pivotal goes to https://www.pivotaltracker.com
Gmail goes to https://accounts.google.com
But I seem to can't make the condition work in connection_url action.
Any workarounds will be appreciated.
EDIT:
I am using the connection_url here: ( in the Faraday block )
def my_connections
connection_name ||= Faraday.new(:url => "#{connection_url}" , ssl: {verify: false}) do |faraday|
faraday.request :url_encoded # form-encode POST params
faraday.response :logger # log requests to STDOUT
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
end
puts "####"
puts connection_url
end
Your can rewrite your lib helper as class:
class Connection
def initialize(url)
#url = url
end
def setup
connection_name ||= Faraday.new(:url => "#url" , ssl: {verify: false}) do |faraday|
faraday.request :url_encoded # form-encode POST params
faraday.response :logger # log requests to STDOUT
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
end
end
end
Now in the model you can initialize this class with the url you want, for example:
def connection
Connection.new("https://accounts.google.com").setup
end
I didn't test this code, but it should work.
Related
In my Rails 7 app third party API require to send the PDF file created by my application. I've got sample curl from the API docs:
curl -X POST --header 'Content-Type: multipart/form-data' --header 'Accept: application/json' {"type":"formData"} 'https://some_path.com'
I'm using Faraday gem with below implementation of client and resource:
# app/clients/test_api/client.rb
module TestApi
class Client
include ::Errors
API_ENDPOINT = 'https://some_path.com'
ACCESS_TOKEN = Rails.application.credentials.api_token
def initialize
#access_token = ACCESS_TOKEN
end
def post(path, options = {})
handle_response(client.public_send(:post, path.to_s, options.to_json))
end
attr_reader :access_token
private
def client
#client =
Faraday.new(API_ENDPOINT) do |client|
client.request :url_encoded
client.response :json, content_type: /\bjson$/
client.adapter Faraday.default_adapter
client.headers['Accept'] = 'application/json'
client.headers['Content-Type'] = 'application/json'
client.headers['apiToken'] = access_token.to_s if access_token.present?
end
end
def handle_response(response)
return response_body(response) if response.success?
raise error_class(response.status)
end
def response_body(response)
response&.body
end
end
end
# app/clients/test_api/resources.rb
module TestApi
class Resources
def upload_document(file)
client.post('/sspfile/uploadtemporary', body: file)
end
private
def client
#client ||= Client.new
end
end
end
But how to send the file as a body params? I've got the API error with my implementation so seems like it's not that simple.
You have to use Faraday::UploadIO class to first create an UploadIO object and pass that into the request.
Make changes in these lines of your code:
# app/clients/test_api/client.rb
module TestApi
class Client
...
def post(path, options = {})
handle_response(client.public_send(:post, path.to_s, options.to_json))
end
...
end
end
# app/clients/test_api/resources.rb
module TestApi
class Resources
def upload_document(file)
uploaded = Faraday::UploadIO.new(file, 'application/pdf')
client.post('/sspfile/uploadtemporary', file: uploaded)
end
...
end
end
Can read here for more info on UploadIO class: https://rubydoc.info/gems/multipart-post/1.1.0/UploadIO
There is outdated tutorial in Ruby - https://dev.outlook.com/restapi/tutorial/ruby
( search for get_email_from_id_token in the .\o365-tutorial\app\helpers\auth_helper.rb file )
First of all - I tried it and it does not work.
I tried to make request for profile:
conn = Faraday.new(url: 'https://outlook.office.com') do |faraday|
# Outputs to the console
faraday.response :logger
# Uses the default Net::HTTP adapter
faraday.adapter Faraday.default_adapter
end
response = conn.get do |request|
# Get events from the calendar
request.url '/api/v2.0/Me'
request.headers['Authorization'] = "Bearer #{token}"
request.headers['Accept'] = 'application/json'
end
JSON.parse(response.body)
It returns user profile data, but email field is blank. It is strange.
Did anyone face/solve this problem ?
My Resque Job can't connect to localhost to POST request...
When I try UserCreatorJob.perform_now(options) it runs ok.
When I use UserCreatorJob.perform_later(options) it goes to the resque queue and than, when performing, it fails with Connection refused - connect(2) for "fe80::1%lo0" port 3000
user_creator_job.rb
class UserCreatorJob < Jobs::ApplicationJob
queue_as :user
def perform(*args)
conn :post, 'api/v1/users', args
end
def conn
Faraday.new(url: 'http://localhost:3000') do |faraday|
faraday.request :url_encoded # form-encode POST params
faraday.response :logger # log requests to STDOUT
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
faraday.token_auth('')
end
end
end
If I perform the post with CURL everything goes as expected.
I think resque may not like posting to localhost.
Try adding this line to your /etc/hosts file:
127.0.0.1 my.api.dev
Then, in your code, replace http://localhost:3000 with http://my.api.dev:3000
I'm trying to use Faraday with Rails 4 for Google API Oauth in below code:
class GoogleApisController < ApplicationController
def oauth2callback
require 'faraday'
render layout: false
conn = Faraday.new(:url => 'https://accounts.google.com',:ssl => {:verify => false}) do |faraday|
faraday.request :url_encoded
faraday.response :logger
faraday.adapter Faraday.default_adapter
end
#result = conn.post '/o/oauth2/token', {'code' => params[:code],
'client_id' => "some_id",
'client_secret' => "some_secret",
'redirect_uri' => "some_redirect_uri",
'grant_type' => 'authorization_code'}
end
end
But when I do #result.body.inspect it doesn't return anything.
So #result return nil and doesn't seem to process at all.
However when I try the above codes in liveshell it seems to work.
Is there a reason why this is happening?
If you try to render before you instantiate the object you are trying to render, the template won't actually have anything in it. Moving the render statement to the bottom of the method will take care of the issue.
Is it possible for me to call a controllers action programatically and get the HTML output?
Here's a rails2 example that might get you a bit closer
lib/render_url_to_string.rb
if !defined?(ActionController::Integration::Session)
require "action_controller/integration"
end
class Rack::Lint
def call(*args)
#app.call(*args)
end
end
module RenderURLToString
def self.included(base)
base.send(:include, RenderURLToString::InstanceMethods)
base.extend( RenderURLToString::ClassMethods)
end
module ClassMethods
# This method sets the default hostname to render templates
# with. Use this to ensure the output urls in your templates
# are getting the right host.
#
def set_default_render_hostname(host)
RenderURLToString::Settings.hostname = host
end
end
module InstanceMethods
# This method renders a given URL within your site to a string.
# Invoke the method with the form
# render_url_to_string("/path/to/resource.ext")
# The method supports the following optional parameters, passed in
# as a symbol hash.
#
# :headers => A hash of HTTP headers
# Defaults to nil
# :params => A hash of URL parameters, or a string of URL
# parameters "?foo=bar&baz=bo"
# Defaults to nil
# :method => A symbol or string representing which HTTP method
# to use. Must be :get, :post, :put or :delete
# Defaults to :get
# :environment => A request environment to pass to the Dispatcher.
# You will rarely need to use this option; if you
# are calling the method inside of a Rails template
# or controller, the method will use the
# current request, extracting the relevant parts
# for its own use.
# :host => The host name to use for resolving URL creation
# Defaults to www.example.com
#
#
# The method returns an array with two elements. The first
# element is the integer status code (200, 404, 500) of the
# attempt to process the URL, and the second element is the
# string result of the body processed. An example return value of
# a successful request would be:
# [200, "<html><head><title>Foo!</title></head><body></body></html>"]
#
# whereas an example of a failed request would be:
# [500, "<html><head><title>The request failed</title><body></body></html>"]
#
# Examples:
#
# Renders the url /foo/bar.baz
# render_url_to_string("/foo/bar.baz")
#
# Renders the url /foo/bar.baz?wocca=wocca!
# render_url_to_string("/foo/bar.baz", :params => { :wocca => "wocca!" }
#
# Renders the url /foo/bar.baz with form parameter wocca = whoopiepie
# render_url_to_string("/foo/bar.baz",
# :params => { :wocca => "whoopiepie" }
# :method => :post)
#
# Renders the url /foo/bar.baz with form parameter wocca =
# whoopiepie and host set to "www.yahoo.com"
# render_url_to_string("/foo/bar.baz",
# :host => "www.yahoo.com",
# :params => { :wocca => "whoopiepie" }
# :method => :post)
#
def render_url_to_string(url, *args)
options = args.extract_options!
method = (options.delete(:method) || :get)
if method.is_a?(String)
method = method.downcase.to_sym
end
headers = options.delete(:headers)
params = options.delete(:params)
environment =
raise "Invalid method, must be GET, POST, PUT or DELETE" unless [ :get, :post, :put, :delete ].include?(method)
app = RenderURLToString::Settings.app
reset_host = app.host
if host = (options.delete(:host) || RenderURLToString::Settings.hostname)
app.host = host
end
if e = options.delete(:environment)
RenderURLToString::Settings.set_current_app_environment(e)
elsif self.respond_to?(:request) && request.env
RenderURLToString::Settings.set_current_app_environment(request.env)
else
RenderURLToString::Settings.set_current_app_environment(ENV)
end
status = app.send(method.to_sym, url, params, headers)
app.host = reset_host
return [status, RenderURLToString::Settings.app.body]
end
end
private
class Settings
IGNORED_ENVIRONMENT_KEYS = ["REQUEST_PATH", "action_controller.request.request_parameters", "PATH_INFO", "rack.request", "rack.routing_args", "rack.multithread","rack.request.query_hash","REQUEST_METHOD", "action_controller.request.query_parameters", "action_controller.rescue.request", "rack.request.query_string", "action_controller.rescue.response","rack.input", "QUERY_STRING", "rack.errors", "REQUEST_URI", "SCRIPT_NAME"]
def self.app=(app)
#app = app
end
def self.app
unless #app
# We don't want to deadlock the server when trying
# to process this internal request
# THIS IS MUCKING WITH INTERNAL RAILS REQUEST DISPATCHING LOGIC
# AND AS SUCH SHOULD NOT BE MESSED WITH UNLESS YOU
# PLAN ON FIXING BUGS IN THE FUTURE
dispatcher = ActionController::Dispatcher.new(self.stringio)
dispatcher.instance_eval do |instance|
def set_my_env(e)
#my_env = {}
e.each do |k, v|
#my_env[k] = v unless IGNORED_ENVIRONMENT_KEYS.include?(k)
end
end
def call(e)
#env = e.merge(#my_env)
self.dispatch
end
end
#app = ActionController::Integration::Session.new(dispatcher)
end
#app
end
def self.set_current_app_environment(env)
self.app.application.set_my_env(env)
end
def self.hostname=(host)
#host = host
end
def self.hostname
#host
end
def self.stringio
StringIO.new
end
end
end