Hi I am working on rails app. In the function makeRequestToAPI1 of ArticlesHelper module, I am calling the API1 class's (this class is present in lib/) method "createRequest(request). But it is giving me "NoMethodError".
articles_helper.rb
require '././lib/ThirdPartyLibs/api1'
require '././lib/ThirdPartyLibs/api2'
module ArticlesHelper
include EnumsHelper
def makeRequestToAPI1(request)
# here as request to API is same as the original request
# so I am directly passing the request to the API
response = API1.createRequest(request)
Rails.logger.debug "makeRequestToAPI1: #{response}"
end
def makeRequestToAPI2(request)
requestToAPI2 = {}
requestToAPI2.merge!({:items => request[:items]})
requestToAPI2.merge!({:pickup => request[:pickup]})
requestToAPI2.merge!({:drop => request[:drop]})
#response = API2.createRequest(requestToAPI2)
#Rails.logger.debug "makeRequestToAPI2: #{response}"
end
end
api1.rb
class API1
#class << self
def self.createRequest(request)
#response = {:etd => 10, :eta => 20}
end
end
What am I missing here?
Can you please try adding following line to applicaion.rb
config.autoload_paths += %W(#{config.root}/lib)
Related
I have got a AccountController class, this controller class is in the application kernel. I dont want to make changes into kernel, therefore Im going to Monkey Patch it.
Controller has method named successful_authentication, which I've rewritten. Inside the new method (in my module) this code calls new method named load_favourite_or_index.
I've read that alias_method_chain is deprecated now and should not be used. I'm trying to prepend my module before AccountController. But nothing happens, I guess my prepending code is not correct, please could you help me? Here's my code.
# frozen_string_literal: true
module RedmineKapDesign
module Patches
module AccountControllerPatch
def self.prepended(base) # :nodoc:
class << base
prepend InstanceMethods
end
end
module InstanceMethods
def successful_authentication(user)
logger.info "Successful authentication for '#{user.login}' from #{request.remote_ip} at #{Time.now.utc}"
# Valid user
self.logged_user = user
logger.info "Setting.autologin? = #{Setting.autologin?}, params[:autologin] = #{params[:autologin]}"
# generate a key and set cookie if autologin
if params[:autologin] && Setting.autologin?
set_autologin_cookie(user)
end
call_hook(:controller_account_success_authentication_after, {:user => user})
load_favourite_page_or_index
#redirect_back_or_default my_page_path
end
def load_favourite_page_or_index
user = User.current
favourite_page_field = CustomField.where(name: ["Favourite page", "favourite page", "favorite page", "Favourite page", "Любимая страница", "любимая страница", "Избранная страница", "избранная страница"]).first
page_url = user.custom_values.where(custom_field_id: favourite_page_field.id).first.value
if page_url.empty?
redirect_back_or_default my_page_path
else
redirect_to(page_url)
end
end
def self.hello
puts "Hello"
end
end
end
end
end
#unless AccountController.included_modules.include?(RedmineKapDesign::Patches::AccountControllerPatch)
# AccountController.send(:prepend, RedmineKapDesign::Patches::AccountControllerPatch)
#end
AccountController.singleton_class.prepend(RedmineKapDesign::Patches::AccountControllerPatch)
You don't need to separate out the instance methods into a seperate module. You can just place them in AccountControllerPatch and prepend whatever class you are monkeypatching with it.
module RedmineKapDesign
module Patches
module AccountControllerPatch
def successful_authentication(user)
logger.info "Successful authentication for '#{user.login}' from #{request.remote_ip} at #{Time.now.utc}"
# Valid user
self.logged_user = user
logger.info "Setting.autologin? = #{Setting.autologin?}, params[:autologin] = #{params[:autologin]}"
# generate a key and set cookie if autologin
if params[:autologin] && Setting.autologin?
set_autologin_cookie(user)
end
call_hook(:controller_account_success_authentication_after, {:user => user})
load_favourite_page_or_index
#redirect_back_or_default my_page_path
end
def load_favourite_page_or_index
user = User.current
favourite_page_field = CustomField.where(name: ["Favourite page", "favourite page", "favorite page", "Favourite page", "Любимая страница", "любимая страница", "Избранная страница", "избранная страница"]).first
page_url = user.custom_values.where(custom_field_id: favourite_page_field.id).first.value
if page_url.empty?
redirect_back_or_default my_page_path
else
redirect_to(page_url)
end
end
def self.hello
puts "Hello"
end
end
end
end
Using a seperate module is only really needed for class methods when using the module mixin pattern. In framework code using a seperate InstanceMethods module can be used for organizational purposes. But in a simple monkeypatch it just makes more of a mess.
# config/initializers/my_monkey_patch.rb
# You should explicity require classes in initializers
require Rails.root.join('path', 'to', 'monkeypatch')
require Rails.root.join('path', 'to', 'target')
::AccountController.prepend RedmineKapDesign::Patches::AccountControllerPatch
I am trying to open a file on rails user model with ruby and call it from user controller but it kept throwing me back wrong number of arguments (given 0, expected 1..3).
This is my file directory 'app' ,'assets', 'files', 'test_list.txt'
'app' ,'controllers', 'users controller'
can you help?thanks
class User < ApplicationRecord
def self.my_method
my_array = []
file = File.join(Rails.root, 'app' 'models','assets', 'files', 'test_list.txt')
File.open.each do |line|
my_array << line.gsub!(/\n?/, "")
end
return my_array.to_s
end
end
class UsersController < ApplicationController
require 'open-uri'
require 'net/http'
def show
# uri = URI('https://gist.githubusercontent.com/Kalagan/3b26be21cbf65b62cf05ab549433314e/raw')
# data = Net::HTTP.get(uri)
# anagrams = data.split(/\n/)
#vari = User.my_method
#query = params[:query]
#results = anagrams.select { |word| #query.split('').sort.join == word.split('').sort.join }
end
end
You're passing nothing to the open method. Pass the filename
Change
File.open
to
File.open(file)
open method needs to know at least the filename it has to open
I think you missed a comma.You can write the below code.
file = File.join(Rails.root, 'app', 'models','assets', 'files', 'test_list.txt')
and for reading the content
File.read(file) do |file|
file.each do |line|
p line
end
end
I'm working with a team on checking a user's email input when they sign up for a web app. The user will not be allowed to sign up if their email is not found with the following API call using HTTParty. We are getting method_errors for whatever syntax is first within the function. For, example, in the method below, "include" comes up as an undefined method error.
def email_checker
include HTTParty
default_params :output => 'json'
format :json
base_uri 'app.close.io'
basic_auth 'insert_api_code_here', ' '
response = HTTParty.get('/api/v1/contact/')
#email_database = []
response['data'].each do |x|
x['emails'].each do |contact_info|
#email_database << contact_info['email']
end
end
unless #email_database.include? :email
errors.add :email, 'According to our records, your email has not been found!'
end
end
UPDATE: So we went with the inline version of using HTTParty and our registrations controller (working with devise) looks like this:
class RegistrationsController < Devise::RegistrationsController
def email_checker(email)
YAML.load(File.read('config/environments/local_env.yml')).each {|k, v| ENV[k.to_s] = v}
api_options = {
query: => {:output => 'json'},
format: :json,
base_uri: 'app.close.io',
basic_auth: ENV["API_KEY"], ' '
}
response = HTTParty.get('/api/v1/contact/', api_options)
#email_database = []
response['data'].each do |x|
x['emails'].each do |contact_info|
#email_database << contact_info['email']
end
end
unless #email_database.include? email
return false
else
return true
end
end
def create
super
if email_checker == false
direct_to 'users/sign_up'
#and return to signup with errors
else
User.save!
end
end
end
We're getting syntax error: "syntax error, unexpected =>" Did we screw up the format?
There are two different ways to use HTTParty, and you're trying to use both. Pick one :).
The class-based method would look something like this:
class CloseIo
include HTTParty
default_params :output => 'json'
format :json
base_uri 'app.close.io'
basic_auth 'insert_api_code_here', ' '
end
class UserController
def email_checker
response = CloseIo.get('/api/v1/contact/')
# ... the rest of your stuff
end
end
An inline version would look something like this
class UserController
def email_checker
api_options = {
query: :output => 'json',
format: :json,
base_uri: 'app.close.io',
basic_auth: 'insert_api_code_here'
}
response = HTTParty.get('/api/v1/contact/', api_options)
# ... do stuff
end
end
This method works OK, but if I add delayed_job's handle_asychronously, I get can't convert nil into String:
def onixtwo
s = render_to_string(:template=>"isbns/onix.xml.builder")
send_data(s, :type=>"text/xml",:filename => "onix2.1.xml")
end
handle_asynchronously :onixtwo
So rendering with delayed job is clearly having a problem with params being passed. I've tried putting this job in a rake task but render_to_string is a controller action - and I'm using a current_user variable which needs to be referenced in the controller or view only. So... what's the best way to delay a rendering job?
/////////update////////
Given that I'm currently pair-programming with a toddler, I don't have the free hands to investigate additional class methods as wisely recommended in the comments - so as a quick and dirty I tried this:
def onixtwo
system " s = render_to_string(:template=>'isbns/onix.xml.builder') ; send_data(s, :type=>'text/xml',:filename => 'onix2.1.xml') & "
redirect_to isbns_path, :target => "_blank", :flash => { :success => "ONIX message being generated in the background." }
end
Why doesn't it work? No error message just no file produced - which is the case when I remove system ... &
For what it's worth, this is what I did, bypassing render_to_stream entirely. This is in /lib or app/classes (adding config.autoload_paths += %W(#{config.root}/classes into config/application.rb):
#classes/bookreport.rb
# -*- encoding : utf-8 -*-
require 'delayed_job'
require 'delayed/tasks'
class Bookreport
# This method takes args from the book report controller. First it sets the current period. Then it sorts out which report wants calling. Then it sends on the arguments to the correct class.
def initialize(method_name, client, user, books)
current_period = Period.where(["currentperiod = ? and client_id = ?", true, client]).first
get_class = method_name.capitalize.constantize.new
get_class.send(method_name.to_sym, client, user, books.to_a, current_period.enddate)
end
end
#app/classes/onixtwo.rb
require 'builder'
class Onixtwo
def onixtwo(client_id, user_id, books, enddate)
report_name = "#{Client.find_by_id(client_id).client_name}-#{Time.now}-onix-21"
filename = "#{Rails.root}/public/#{report_name}.xml"
current_company = Company.where(:client_id => client_id).first
File.open(filename, "w") do |file|
xml = ::Builder::XmlMarkup.new(:target => file, :indent => 2)
xml.instruct!(:xml, :version => "1.0", :encoding => "utf-8")
xml.declare! :DOCTYPE, :ONIXMessage, :SYSTEM, "http://www.editeur.org/onix/2.1/03/reference/onix-international.dtd"
xml.ONIXMessage do
xml.Header do
#masses of Builder code goes here...
end
end #of file
xmlfile = File.open(filename, "r")
onx = Onixarchive.new(:client_id => client_id, :user_id => user_id)
onx.xml = xmlfile
onx.save!
end #of method
handle_asynchronously :onixtwo
end #of class
Called from the view like this:
= link_to("Export to ONIX 2.1", params.merge({:controller=>"bookreports" , :action=>:new, :method_name => "onixtwo"}))
Via a controller like this:
class Books::BookreportsController < ApplicationController
#uses Ransack for search, hence the #q variable
def new
#q = Book.search(params[:q])
#books = #q.result.order('pub_date DESC')
method_name = params[:method_name]
Bookreport.new(method_name, #client, #user, #books)
redirect_to books_path, :flash => {:success => t("#{method_name.to_sym}").html_safe}
end
end
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