calling ruby method in rails controller raises error - ruby-on-rails

I have a rails app and I'm trying to call the methods below from the controller, but I get this error:
undefined local variable or method "service" for #<EventsController:0x007fb6d27da1c8>` for this line: `api_method: service.freebusy.query
What's the problem here? Why can't the get_busy_events see the service var if it's defined above it?
controller
include GoogleCalendarApi
.....
#user = current_user
#google = #user.socials.where(provider: "google_oauth2").first
unless #google.blank?
#client = init_google_api_calendar_client(#google)
#result = open_gcal_connection(get_busy_events, #client, #google)
lib/google_api_calendar.rb
def init_google_api_calendar_client(google_account)
#method only called if google_oauth2 social exists
client = Google::APIClient.new
client.authorization.access_token = google_account.token
client.authorization.client_id = ENV['GOOGLE_API_KEY']
client.authorization.client_secret = ENV['GOOGLE_API_SECRET']
client.authorization.refresh_token = google_account.refresh_token
return client
end
def open_gcal_connection(options, initialized_client, social_object)
client = initialized_client
old_token = client.authorization.access_token
service = client.discovered_api('calendar', 'v3')
result = client.execute(options) #after execution you may get new token
# update token if the token that was sent back is expired
new_token = client.authorization.access_token
if old_token != new_token
social_object.update_attribute(token: new_token)
end
return result
end
def get_busy_events
result = open_gcal_connection(
api_method: service.freebusy.query,
body: JSON.dump({ timeMin: '2015-12-24T17:06:02.000Z',
timeMax: '2013-12-31T17:06:02.000Z',
items: social_object.email }),
headers: {'Content-Type' => 'application/json'})
#handling results
end

To answer your question(as I did in the comments):
To fix your method, you have to define the service variable in the action where you are calling it.
As for your posted link: if you look at the get_busy_events method there is a line where service = client.discovered_api('calendar', 'v3')
and it is fine, because it is in the method. The same goes for client that the service declaration depends on- you have to declare them inside the method where you use them.
You should follow the article and make the code as it is there so you would have:
def init_client
client = Google::APIClient.new
# Fill client with all needed data
client.authorization.access_token = #token #token is taken from auth table
client.authorization.client_id = #oauth2_key
client.authorization.client_secret = #oauth2_secret
client.authorization.refresh_token = #refresh_token
return client
end
which you can use to define client variable in all your other actions and then use the service method:
def get_busy_times
client = init_client
service = client.discovered_api('calendar', 'v3')
#result = client.execute(
:api_method => service.freebusy.query,
:body_object => { :timeMin => start_time, #example: DateTime.now - 1.month
:timeMax => end_time, #example: DateTime.now + 1.month
:items => items
},
:headers => {'Content-Type' => 'application/json'}})
end
EDIT No2:
Since you have a controller, where client is initialized I suggest passing it down as an argument:
include GoogleCalendarApi
.....
#user = current_user
#google = #user.socials.where(provider: "google_oauth2").first
unless #google.blank?
#client = init_google_api_calendar_client(#google)
#result = open_gcal_connection(get_busy_events(#client), #client, #google)
and changing your get_busy_events method:
def get_busy_events(client)
service = client.discovered_api('calendar', 'v3')
result = open_gcal_connection(
api_method: service.freebusy.query,
body: JSON.dump({ timeMin: '2015-12-24T17:06:02.000Z',
timeMax: '2013-12-31T17:06:02.000Z',
items: social_object.email }),
headers: {'Content-Type' => 'application/json'})
#handling results
end
Although this is a bit weird for me(nesting arguments like this) so you should look at refactoring this.

Related

Quickbook Create invoice error in rails

i am getting this error when i am creating invoice using Quickbook rails gem (quickbooks-ruby)
Quickbooks::IntuitRequestException (Required param missing, need to supply the required value for the API:
Required parameter Line.DetailType is missing in the request):
app/controllers/users_controller.rb:42:in `oauth_callback'
My Controller
class UsersController < ApplicationController
def index
upload_service = Quickbooks::Service::Upload.new
# result = upload_service.upload("tmp/monkey.jpg", "image/jpeg", attachable_metadata)
end
def authenticate
callback = users_oauth_callback_url
token = QB_OAUTH_CONSUMER.get_request_token(:oauth_callback => callback)
session[:qb_request_token] = Marshal.dump(token)
redirect_to("https://appcenter.intuit.com/Connect/Begin?oauth_token=#{token.token}") and return
end
def oauth_callback
at = Marshal.load(session[:qb_request_token]).get_access_token(:oauth_verifier => params[:oauth_verifier])
session[:token] = at.token
session[:secret] = at.secret
session[:realm_id] = params['realmId']
end
def create_invoice
access_token = OAuth::AccessToken.new(QB_OAUTH_CONSUMER, session[:token], session[:secret] )
invoice = Quickbooks::Model::Invoice.new
invoice.customer_id = 123
invoice.txn_date = Date.civil(2013, 11, 20)
invoice.doc_number = "1001" # my custom Invoice # - can leave blank to have Intuit auto-generate it
line_item = Quickbooks::Model::InvoiceLineItem.new
line_item.amount = 50
line_item.description = "Plush Baby Doll"
line_item.sales_item! do |detail|
detail.unit_price = 50
detail.quantity = 1
detail.item_id = 500 # Item ID here
end
invoice.line_items << line_item
service = Quickbooks::Service::Invoice.new
service.company_id = session[:realm_id]
service.access_token = access_token
created_invoice = service.create(invoice)
puts created_invoice.id
redirect_to root_url
end
end
config/initializers/quickeebooks.rb
OAUTH_CONSUMER_KEY = "xxxxxxxxxxxxxxxxxxxxxxx"
OAUTH_CONSUMER_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
::QB_OAUTH_CONSUMER = OAuth::Consumer.new(OAUTH_CONSUMER_KEY, OAUTH_CONSUMER_SECRET, {
:site => "https://oauth.intuit.com",
:request_token_path => "/oauth/v1/get_request_token",
:authorize_url => "https://appcenter.intuit.com/Connect/Begin",
:access_token_path => "/oauth/v1/get_access_token"
})
The error is:
Required parameter Line.DetailType is missing in the reques
Did you specify DetailType in your request. It doesn't look like it:
line_item = Quickbooks::Model::InvoiceLineItem.new
line_item.amount = 50
line_item.description = "Plush Baby Doll"
Refer to the documentation:
https://developer.intuit.com/docs/api/accounting/invoice
Which indicates:
DetailType:
*required*
LineDetailTypeEnum
Set to SalesItemLineDetail for this type of line.

undefined method `get_access_token'

My twitter controller code is this
class TwitterController < ApplicationController
before_filter :authenticate_user!
def index
unless TwitterOauthSetting.find_by_user_id(current_user.id).nil?
redirect_to "/twitter_profile"
end
end
def generate_twitter_oauth_url
oauth_callback = "http://#{request.host}:#{request.port}/oauth_account"
#consumer = OAuth::Consumer.new("n3yfOi9iEHwnyz5uEsyNotW6t","kqHFm5dRRX00dIQSwBcTEJKZNAzrWcuK0BOAyDVWY8liRI1cPc", :site => "https://api.twitter.com")
#request_token = #consumer.get_request_token(:oauth_callback => oauth_callback)
session[:request_token] = #request_token
redirect_to #request_token.authorize_url(:oauth_callback => oauth_callback)
end
def oauth_account
if TwitterOauthSetting.find_by_user_id(current_user.id).nil?
#request_token = session[:request_token]
#access_token = #request_token.get_access_token(:oauth_verifier => params["oauth_verifier"])
TwitterOauthSetting.create(atoken: #access_token.token, asecret: #access_token.secret, user_id: current_user.id)
update_user_account()
end
redirect_to "/twitter_profile"
end
def twitter_profile
#user_timeline = get_client.user_timeline
#home_timeline = get_client.home_timeline
end
private
def get_client
Twitter.configure do |config|
config.consumer_key = "n3yfOi9iEHwnyz5uEsyNotW6t"
config.consumer_secret = "kqHFm5dRRX00dIQSwBcTEJKZNAzrWcuK0BOAyDVWY8liRI1cPc"
end
Twitter::Client.new(
:oauth_token => TwitterOauthSetting.find_by_user_id(current_user.id).atoken,
:oauth_token_secret => TwitterOauthSetting.find_by_user_id(current_user.id).asecret
)
end
def update_user_account
user_twitter_profile = get_client.user
current_user.update_attributes({
name: user_twitter_profile.name,
screen_name: user_twitter_profile.screen_name,
url: user_twitter_profile.url,
profile_image_url: user_twitter_profile.profile_image_url,
location: user_twitter_profile.location,
description: user_twitter_profile.description
})
end
end
On index page add your twitter account option is there. After clicking on that it will authorize app & After authorizaion process i am facing an error "undefined method `get_access_token' .i am facing error in this line " #access_token = #request_token.get_access_token(:oauth_verifier => params["oauth_verifier"])"
The solution of my problem:
What i did is I added a new method to prepare access token & in get client method used Twitter::REST::Client.new do |config| and also provided access_token & access_token_secret_key and now it is working properly.
class TwitterController < ApplicationController
before_filter :authenticate_user!
def index
unless TwitterOauthSetting.find_by_user_id(current_user.id).nil?
redirect_to "/twitter_profile"
end
end
def generate_twitter_oauth_url
oauth_callback = "http://#{request.host}:#{request.port}/oauth_account"
#consumer = OAuth::Consumer.new("2K763Dgw9y6oAOOLsegegkHW7","pwXauJeR628SL8DhgwikStNYykGCKoabISHI4ZUnKIxt2eSmNY", :site => "https://api.twitter.com")
#request_token = #consumer.get_request_token(:oauth_callback => oauth_callback)
session[:request_token] = #request_token
redirect_to #request_token.authorize_url(:oauth_callback => oauth_callback)
end
def oauth_account
if TwitterOauthSetting.find_by_user_id(current_user.id).nil?
#request_token = session[:request_token]
prepare_access_token(params[:oauth_token],params[:oauth_token_secret])
#consumer = OAuth::Consumer.new(params[:oauth_token],params[:oauth_token_secret], :site => "https://api.twitter.com")
#access_token = prepare_access_token(params[:oauth_token],params[:oauth_token_secret])
TwitterOauthSetting.create(atoken: #access_token.token, asecret: #access_token.secret, user_id: current_user.id)
update_user_account()
end
redirect_to "/twitter_profile"
end
def twitter_profile
#user_timeline = get_client.user_timeline
#home_timeline = get_client.home_timeline
end
private
def get_client
Twitter::REST::Client.new do |config|
config.consumer_key = "n3yfOi9iEHwnyz5uEsyNotW6t"
config.consumer_secret = "kqHFm5dRRX00dIQSwBcTEJKZNAzrWcuK0BOAyDVWY8liRI1cPc"
config.access_token = "access_token key"
config.access_token_secret = "access_token_secret key"
end
end
def update_user_account
user_twitter_profile = get_client.user
current_user.update_attributes({
name: user_twitter_profile.name,
screen_name: user_twitter_profile.screen_name,
url: user_twitter_profile.url,
profile_image_url: user_twitter_profile.profile_image_url,
location: user_twitter_profile.location,
description: user_twitter_profile.description
})
end
def prepare_access_token(oauth_token, oauth_token_secret)
#consumer = OAuth::Consumer.new("APIKey", "APISecret", { :site => "https://api.twitter.com", :scheme => :header })
#consumer = OAuth::Consumer.new("2K763Dgw9y6oAOOLsegegkHW7","pwXauJeR628SL8DhgwikStNYykGCKoabISHI4ZUnKIxt2eSmNY", { :site => "https://api.twitter.com", :scheme => :header })
# now create the access token object from passed values
token_hash = { :oauth_token => oauth_token, :oauth_token_secret => oauth_token_secret }
access_token = OAuth::AccessToken.from_hash(#consumer, token_hash )
return access_token
end
end
Your #request_token is apparently a string, which is why the get_access_token method is undefined.
Replace the oauth_account method with the one below to recreate the #request_token because #request_token = session[:request_token] will create a string instead and the get_access_token method is hence undefined.
def oauth_account
if TwitterOauthSetting.find_by_user_id(current_user.id).nil?
# Re-create the request token
#consumer = OAuth::Consumer.new(ENV["consumer_key"], ENV["consumer_secret"], :site => "https://api.twitter.com")
#request_token = OAuth::RequestToken.new(#consumer, session[:request_token], session[:request_secret])
#access_token = #request_token.get_access_token(:oauth_verifier => params["oauth_verifier"])
TwitterOauthSetting.create(atoken: #access_token.token, asecret: #access_token.secret, user_id: current_user.id)
update_user_account()
end
redirect_to "/twitter_profile"
end
Replace the get_client method with the one below to access the user's token and its access which are stored in the session.
def get_client
Twitter::REST::Client.new do |config|
config.consumer_key = ENV["consumer_key"]
config.consumer_secret = ENV["consumer_secret"]
unless TwitterOauthSetting.find_by_user_id(current_user.id).nil?
config.oauth_token = TwitterOauthSetting.find_by_user_id(current_user.id).atoken
config.oauth_token_secret = TwitterOauthSetting.find_by_user_id(current_user.id).asecret
end
end
end
Check using logger the value of #acces_token. Maybe it is not getting the required value or datatype.

Rails redirecing with session variables

I have a landing page controller that looks like this ;
class LandingController < ApplicationController
def index
#user = current_user
#name = #user.name.titleize
#balance = "#{#user.currency} #{#user.balance}"
#last_login = #user.last_sign_in_at
api_key = ApiKey.find_by_user_id( #user.id)
#access_token = api_key.access_token
end
def check_mail
end
end
However, in a controller method shown below, when i make the redirect i get an error.
Controller method;
def success
transaction = Transaction.find_by_token(params[:token])
transaction.payer_id = params[:payer_id]
transaction.save
#current_user = user = User.find(transaction.user_id)
username = "xxxxxxxxxxxxxxxxxxxx"
password = "7xxxxxxxxxxxxxxx"
signature = "xxxxxxxxxxxxxxx"
version = 98
#amount = Currency.convert(user.currency, "USD", transaction.amount.to_f).to_f.round(2)
url = "https://api-3t.paypal.com/nvp?USER=#{username}&PWD=#{password}&SIGNATURE=#{signature}&VERSION=#{version}&METHOD=DoExpressCheckoutPayment&TOKEN=#{transaction.token}&PAYERID=#{transaction.payer_id}&PAYMENTREQUEST_0_PAYMENTACTION=SALE&PAYMENTREQUEST_0_AMT=#{#amount}&PAYMENTREQUEST_0_CURRENCYCODE=USD"
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(uri.request_uri)
res = http.request(request)
response = res.body
transaction.save
user.balance = (user.balance+transaction.amount)
user.save()
transaction.status ="Completed"
transaction.save()
flash[:notice] = 'Payment Transaction Completed. Thank you for using skyline SMS'
redirect_to user_home_path(#current_user)
end
i get the error below;
undefined method `name' for nil:NilClass
with the trace;
app/controllers/landing_controller.rb:4:in `index'
How can i go about it?
The problem is that the #user variable in LandingController don't have a value (it's nil), that's why you're getting undefined method name for nil:class, try this: put the redirect like this
#stuff...
redirect_to user_home_path(:current_user => #current_user)
end
and in LandingController index put this
def index
#user = params[:current_user]
#name = #user.name.titleize
#...rest of the method...

Google Calendar API 'start-min' parameter not doing anything

This is my code:
oauth_yaml = YAML.load_file('google-api.yaml')
client = Google::APIClient.new
client.authorization.client_id = oauth_yaml["client_id"]
client.authorization.client_secret = oauth_yaml["client_secret"]
client.authorization.scope = oauth_yaml["scope"]
client.authorization.refresh_token = #rtoken
client.authorization.access_token = #token
if client.authorization.refresh_token && client.authorization.expired?
client.authorization.fetch_access_token!
end
service = client.discovered_api('calendar', 'v3')
result = client.execute(
:api_method => service.events.list,
:parameters => {'calendarId' => #calendar, 'start-min' => Time.now.xmlschema},
:headers => {'Content-Type' => 'application/json'}
)
#parsed = JSON.parse(result.data.to_json)
I'm getting all events regardless of if the 'start-min' parameter is included or not. Am I doing something wrong here?
Thanks.
The correct parameter is actually timeMin, not start-min.

401 Unauthorized for foursquare OAuth

OK, I am pulling my hair after trying this out too many times to debug.
So please help me out here. I keep getting 401 Unauthorized error after I am redirected back.
Here is my code. What am I doing wrong here?
require 'rubygems'
require 'OAuth'
require 'json'
class SessionController < ApplicationController
before_filter :load_oauth
def index
if session[:request_token] && params[:oauth_token]
#request_token = OAuth::RequestToken.new(#consumer,
session[:request_token], session[:request_secret])
#access_token =
#request_token.get_access_token(:oauth_verifier =>
params[:oauth_verifier])
puts #access_token
#info = #access_token.get("http://api.foursquare.com/v1/
test")
flash[:notice] = "Foursquare! Yay!"
else
redirect_to(#foursqrurl)
end
end
private
def load_oauth
#oauth_key = 'key'
#oauth_secret = 'secret'
#consumer = OAuth::Consumer.new(#oauth_key,#oauth_secret,{
:site => "http://foursquare.com",
:scheme => :header,
:http_method => :post,
:request_token_path => "/oauth/request_token",
:access_token_path => "/oauth/access_token",
:authorize_path => "/oauth/authorize"
})
#request_token = #consumer.get_request_token(:oauth_callback =>
"http://localhost:3001/session")
session[:request_token] = #request_token.token
session[:request_secret] = #request_token.secret
puts #request_token.token
puts #request_token.secret
# redirecting user to foursquare to authorize
#foursqrurl = #request_token.authorize_url
puts #foursqrurl
end
end
I know absolutely nothing about Oauth and this may be completely wrong, but, if http://foursquare.com is not your local machine and oauth_callback is a URL that http://foursquare.com will call when it has completed then it will be calling back to itself as its definition of localhost will be its own 127.0.0.1 i.e itself.
If I have guessed correctly here then change the :oauth_callback to your public IP Address/name.
I think #request_token = OAuth::RequestToken.new(#consumer,
session[:request_token], session[:request_secret]) is wrong.
If you already have the token and the secret, you don't really need to do the verifier thing.
You should construct it like this:
OAuth::RequestToken.from_hash(consumer, { :oauth_token => params[:oauth_token] })
access_token = request_token.get_access_token(:oauth_verifier => params[:oauth_verifier])
Or if you already have the token and the secret, you should do:
access_token = OAuth::AccessToken.from_hash(consumer, {
:oauth_token => "YOUR_TOKEN",
:oauth_token_secret => "YOUR_SECRET"
})

Resources