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...
Related
so im trying to do web scraping with rails and kimurai, the problem i ran in to was that for some reason i get a single big object instead of one for each of the products im scraping, here is my code:
class ProductsSpider < Kimurai::Base
#name = "products_spider"
#engine = :mechanize
def self.process(url)
#start_urls = [url]
self.crawl!
end
def parse(response, url:, data: {})
response.xpath("//div[#class='andes-card andes-card--flat andes-card--default ui-search-result ui-search-result--core andes-card--padding-default andes-card--animated']").each do |product|
item = {}
item[:product_name] = product.xpath("//h2[#class='ui-search-item__title ui-search-item__group__element']")&.text&.squish
item[:price] = product.xpath("//span[#class='price-tag-fraction']")&.text&.squish&.delete('^0-9')to_i
item[:shipping] = product.xpath("//p[#class='ui-search-item__shipping ui-search-item__shipping--free']")&.text&.squish
Product.where(item).first_or_create
end
end
end
and here is the function on the controller:
def scrape
url = "https://computacion.mercadolibre.com.ar/componentes-pc-placas-video/msi/cordoba/placa-de-video_NoIndex_True#applied_filter_id%3Dstate%26applied_filter_name%3DUbicaci%C3%B3n%26applied_filter_order%3D13%26applied_value_id%3DTUxBUENPUmFkZGIw%26applied_value_name%3DC%C3%B3rdoba%26applied_value_order%3D11%26applied_value_results%3D120%26is_custom%3Dfalse%26view_more_flag%3Dtrue"
response = ProductsSpider.process(url)
if response[:status] == :completed && response[:error].nil?
flash.now[:notice] = "Successfully scraped url"
else
flash.now[:alert] = response[:error]
end
rescue StandardError => e
flash.now[:alert] = "Error: #{e}"
end
I have a mutual friendship model, where one user requests a friendship and creates a model with user_id of current_user and friend_id of the friend.
Then the friend accepts it and creates another model of the inverse.
Now I am trying to send notification upon both cases. The problem is that #friend (current_user as well) in my code seems to be nil or otherwise just not working.
def notify_friend_request
#friend = params[:friend]
#url = 'http://localhost:3000'
#first_name = #friend.first_name
#last_name = #friend.last_name
#email = #friend.email
#sent_user = current_user
#sent_user_first_name = #sent_user.first_name
#sent_user_last_name = #sent_user.last_name
mail(to: #email,
subject: 'You have a new friend request!')
What could be wrong? I'd really appreciate help.
My friendship controller, create method is below. Upon request or acceptance the appropriate mailer method seems to be called (notify_friend_request vs. accept)
def create
#inviting_user = User.find(current_user.id)
#friend = User.find(params[:friend_id])
#friendship = current_user.friendships.build(:friend_id => params[:friend_id])
if #friendship.save
if #friend.friends.include? current_user
UserMailer.with(friendship: #friendship).notify_friend_accept.deliver_later
else
UserMailer.with(friendship: #friendship).notify_friend_request.deliver_later
end
I solved it with this code. Posting a question really cleared up my head:
def notify_friend_request
#friendship = params[:friendship]
#url = 'http://localhost:3000'
#first_name = User.find(#friendship.user_id).first_name
#last_name = User.find(#friendship.user_id).last_name
#sent_user = User.find(#friendship.friend_id)
#sent_user_first_name = #sent_user.first_name
#sent_user_last_name = #sent_user.last_name
#email = #sent_user.email
mail(to: #email,
subject: 'You have a new friend request!')
end
I am receiving a json response (response.body) from the api call I am making with my model and in my controller I would like to parse it to store its id key's value in my session[:user_id].
I've tried to implement it in the following way
parsed_body = JSON.parse(User.new.get_credentials, :symbolize_names => true)
puts "The parsed_body is: #{parsed_body}"
session[:user_id] = parsed_body[0][:id]
puts "The session id is: #{session[:user_id]} "
The response.body is:
{"result":[{"id":"3","username":"Sam","password":"111"},{"id":"4","username":"Harshal","password":"1234"},{"id":"5","username":"Dev","password":"112"},{"id":"6","username":"Lam","password":"113"},{"id":"7","username":"Tim","password":"114"},{"id":"8","username":"Harry","password":"222"}]}
The parsed_body is:
{:result=>[{:id=>"3", :username=>"Sam", :password=>"111"}, {:id=>"4", :username=>"Harshal", :password=>"1234"}, {:id=>"5", :username=>"Dev", :password=>"112"}, {:id=>"6", :username=>"Lam", :password=>"113"}, {:id=>"7", :username=>"Tim", :password=>"114"}, {:id=>"8", :username=>"Harry", :password=>"222"}]}
Here is my code for users controller, user model and sessions controller:
Users Controller
class UsersController < ApplicationController
def create
#users = User.new(token: user_params).credentials
parsed_body = JSON.parse(User.new.get_credentials, :symbolize_names => true)
puts "The parsed_body is: #{parsed_body}"
session[:user_id] = parsed_body[0][:id]
puts "The session id is: #{session[:user_id]} "
redirect_to '/dashboard'
end
private
def user_params
params.require(:user).permit(:id, :username, :password).to_hash
end
end
User Model
class User
def initialize(attributes={})
#token ||= attributes[:token]
end
def credentials
my_connection = Net::HTTP.new('localhost', 8080)
request = my_connection.post('/restapitrial/index.php/Users/insert/', #token.to_json, "Content-Type" => "application/json")
end
def get_credentials
my_connection = Net::HTTP.new('localhost', 8080)
request = my_connection.get('/restapitrial/index.php/Users/displayinfo/', "Content-Type" => "application/json")
puts "The req body is #{request.body}"
return request.body
end
end
Sessions Controller
class SessionsController < ApplicationController
def create
user = User.find_by(id: login_params[:id])
if user && user.authenticate(login_params[:password])
session[:user_id] = user.id
redirect_to '/dashboard'
else
flash[:login_errors] = ['invalid credentials']
redirect_to '/'
end
end
private
def login_params
params.require(:login).permit(:id, :username, :password)
end
end
If you want to get the last id in the array that is returned then use the
parsed_body[:result][-1][:id]
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.
I'm getting what seems to be a successful response from Twitter:
/auth/twitter/callback?oauth_token=somelongtoken&oauth_verifier=someverifier
But there's no oauth_token_secret there. Where do I get it?
DETAIL
routes.rb
get '/auth/:provider', to: 'authorisations#authorise', :as => :new_auth
get '/auth/:provider/callback', to: 'authorisations#callback'
authorisations_controller.rb
def authorise
session[:user_id] = current_user.id
#authorisation = Authorisation.new
#authorisation.user_id = current_user.id
if auth_hash.provider == "facebook"
#authorisation.provider = auth_hash.provider
#authorisation.oauth_token = auth_hash.credentials.token
#authorisation.oauth_expires_at = Time.at(auth_hash.credentials.expires_at)
elsif params[:provider] == "twitter"
#authorisation.provider = params[:provider]
#authorisation.oauth_token = params[:oauth_token]
#authorisation.oauth_token_secret = params[:oauth_token_secret]
#authorisation.access_token = params[:oauth_verifier]
end
#authorisation.save!
end
def callback
session[:user_id] = current_user.id
#authorisation = Authorisation.new
#authorisation.user_id = current_user.id
if auth_hash.provider == "facebook"
#authorisation.provider = auth_hash.provider
#authorisation.oauth_token = auth_hash.credentials.token
#authorisation.oauth_expires_at = Time.at(auth_hash.credentials.expires_at)
elsif params[:provider] == "twitter"
#authorisation.provider = params[:provider]
#authorisation.oauth_token = params[:oauth_token]
#authorisation.oauth_token_secret = params[:oauth_token_secret]
#authorisation.access_token = params[:oauth_verifier]
end
#authorisation.save!
redirect_to root_url, notice: "#{current_user.name} and #{params[:provider].titlecase} have been linked."
end
def auth_hash
request.env['omniauth.auth']
end
documents_controller.rb
def twitter
session[:return_to] = request.referer
#document = Document.find(params[:id])
if #document.template.name == "Image"
#document.process_social_media
twitter_user.update_with_media("#{#document.remove_html(#document.components.first.body[0..100])}...", "#{root_url}temporary#{#document.temp_file_name}.jpg")
else
twitter_user.update("#{#document.remove_html(#document.components.first.body[0..100])}... #{root_url.gsub(/\/$/, '')}#{share_path(#document.user.ftp, #document)}")
end
redirect_to session[:return_to], notice: "#{#document.title} has been posted to Twitter."
end
def twitter_user
user = Twitter.configure do |config|
config.consumer_key = ENV['TWITTER_CONSUMER_KEY']
config.consumer_secret = ENV['TWITTER_CONSUMER_SECRET']
config.oauth_token = current_user.single_authorisation("twitter").oauth_token
config.oauth_token_secret = current_user.single_authorisation("twitter").oauth_token_secret
end
end
It has been a while since I did this, so maybe it has changed, but these are the parameters I pass in the authorization request:
oauth_consumer_key
oauth_nonce
oauth_signature
oauth_signature_method
oauth_timestamp
oauth_version
It's here for anyone hunting around:
def create
#authorisation.oauth_token_secret = auth_hash.credentials.secret
end
def auth_hash
request.env['omniauth.auth']
end
Cheers.