Using "helper" method in view - ruby

I made a helper in my rails project that makes a request in an external api and get a certain value from it.
def show_CoinPrice coin
begin
coinTicker = JSON.parse(HTTParty.get("https://www.mercadobitcoin.net/api/#{coin}/ticker/").body)
"R$ #{coinTicker["ticker"]["last"].to_number.round}"
rescue
"---"
end
end
However I have doubts if this was a good practice to do (this code caused slowness in my view), there is something I can do better, whether with a controller or something ?!
Thanks.

I think u should request to external API using client-side (JS). Cs fetching API with rails helper it's will run while your server is rendering view.

Related

Validation & External APIs - Rescue in Controller or Fatten Model validations?

I am using Restforce to query records from a remote salesforce instance. The user simply has to put in a valid UID for the record they want to query.
Restforce uses Faraday middleware to deal with http requests - and raises a Faraday::ResourceNotFound error if I request something that cannot be located in the remote salesforce database.
Question
Where should I validate user input?
I have two ideas but i'm not sure of the consequences to each... and I'm trying to work out how to stick best to the fat model - skinny controller best practice.
Check for successful query at the application controller level
Requests save the UID to a simple ActiveRecord model #record_request. My create method can fire a query, check for an error and flash/redirect the user if needed.
# app/controllers/record_requests_controller
def create
#record_request = current_user.record_requests.new(record_request_params)
# Check to see if CHAIN number exists
if #record_request.restforce.find("Contact", #record_request.chain_number, 'ClientID__c')
# If it gets past that do standard validation checks
if #record_request.save
flash[:success] = 'Record request was successfully created.'
redirect_to record_requests_path
else
render :new
end
end
end
Then over in the ApplicationController I've got a rescue method setup
# app/controllers/application_controller
rescue_from Faraday::ResourceNotFound, with: :resource_not_found
private
def resource_not_found
flash[:alert] = 'Cannot find resource on Salesforce'
redirect_to(:back)
end
This works! And seems fine... but...
Model level validation?
My gut tells me this is a validation and should be validated on the model level, what if there's a bug and something sneaks into my database? Should this all just be checked at the if #record_request.save moment?
If so... how would i get model level code to handle validation AND be able to fire off an external (OAuth authenticated) API request without breaking the MVC.
What are the implications to either, and how might I do better?
I think the best way to use model level validation something like this:
validate :something
def something
errors.add(:field, 'error message') unless RestClient.check_something
end
Where RestClient is singleton object in /lib folder. This will allow to keep controller clean.

Render a view's output later via a delayed_job

If I render html I get html to the browser which works great. However, how can I get a route's response (the html) when being called in a module or class.
I need to do this because I'm sending documents to DocRaptor and rather than store the markup/html in a db column I would like to instead store record IDs and create the markup when the job executes.
A possible solution is using Ruby's HTTP library, Httparty or wget or something and open up the route and use the response.body. Before doing so I thought I'd ask around.
Thanks!
-- Update --
Here's something like what I ended up going with:
Quick tip - in case anyone does this and need their helper methods you need to extend AV with ApplicationHelper:
Here's something like what I ended up doing:
av = ActionView::Base.new()
av.view_paths = ActionController::Base.view_paths
av.extend ApplicationHelper #or any other helpers your template may need
body = av.render(:template => "orders/receipt.html.erb",:locals => {:order => order})
Link:
http://www.rigelgroupllc.com/blog/2011/09/22/render-rails3-views-outside-of-your-controllers/
check this question out, it contains the code probably want in an answer:
Rails 3 > Rendering views in rake task

rails persist objects over requests in development mode

I am trying to interact with Matlab.Application.Single win32ole objects in my rails application. The problem I am running into is that while I am developing my application, each separate request reloads my win32ole objects so I loose the connection to my matlab orignal instances and new instances are made. Is there a way to persist live objects between requests in rails? or is there a way to reconnect to my Matlab.Application.Single instances?
In production mode I use module variables to store my connection between requests, but in development mode Module variables are reloaded every request.
here is a snippet of my code
require 'win32ole'
module Calculator
#engine2 = nil
#engine3 = nil
def self.engine2
if #engine2.nil?
#engine2 = WIN32OLE.new("Matlab.Application.Single")
#engine2.execute("run('setup_path.m')")
end
#engine2
end
def self.engine3
if #engine3.nil?
#engine3 = WIN32OLE.new("Matlab.Application.Single")
#engine3.execute("run('setup_path.m')")
end
#engine3
end
def self.load_CT_image(file)
Calculator.engine2.execute("spm_image('Init','#{file}')")
end
def self.load_MR_image(file)
Calculator.engine3.execute("spm_image('Init','#{file}')")
end
end
I am then able to use my code in my controllers like this:
Calculator.load_CT_image('Post_Incident_CT.hdr')
Calculator.load_MR_image('Post_Incident_MRI.hdr')
You can keep an app-wide object in a constant that won't be reset for every request. Add this to a new file in config/initializers/:
ENGINE_2 = WIN32OLE.new("Matlab.Application.Single")
You might also need to include the .execute("run('setup_path.m')") line here as well (I'm not familiar with WIN32OLE). You can then assign that object to your instance variables in your Calculator module (just replace the WIN32OLE.new("Matlab.Application.Single") call with ENGINE_2, or simply refer to them directly.
I know this is beyond the scope of your question, but you have a lot of duplicated code here, and you might want to think about creating a class or module to manage your Matlab instances -- spinning up new ones as needed, and shutting down old ones that are no longer in use.

ChemDoodle Ajax Incompatibility with Pollen.js

I'm trying to use iChemLabs cloud services from a html5 web worker. Normally the cloudservices requires jQuery but I can't import that into a web worker so I'm using Pollen instead with a ChemDoodle Web Components library with which I have stripped out the document-related things.
jQuery.Hive.Pollen provides a nice ajax function very similar to jQuery, but I can't seem to get it to work at all. I know this problem will be tricky to solve considering that Access-control-headers need to be set to allow any of you to actually find the solution. However, I'm a beginning javascript programmer and I was wondering if my two weeks of frustration is actually a small difference. I am trying to invoke the following function:
var cloudmolecule;
ChemDoodle.iChemLabs.readSMILES('N1(C)C(=O)N(C)C(C(=C1N1)N(C=1)C)=O', function(mol){
cloudmolecule = mol;
});
Here is a link to the library code I am using, see the 'q.ajax' call and substitute jQuery = q for p = q (p is for pollen) in that block of code.
Right now I'm just trying to get the ajax call to work in an ordinary block of javascript with the plan to migrate to a web worker later.
If anybody could point out the problem to me I would be extremely grateful.
solved! turns out iChemLabs rejects these two extra headers that pollen creates:
_xhr.setRequestHeader("X-Requested-With", "Worker-XMLHttpRequest");
_xhr.setRequestHeader("X-Worker-Hive", "Pollen-JS" );
Simply comment them out
Also, Pollen ajax seems to return a JSON object containing the data in JSON format AND as a string, so do
o = JSON.parse(data.string)//data is the parameter to the callback function
The reduced ChemDoodle library (without document-related methods) will work like a charm with pollen ajax.

Get absolute (base) url in sinatra

Right now, I do a
get '/' do
set :base_url, "#{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}"
# ...
haml :index
end
to be able to use options.base_url in the HAML index.haml.
But I am sure there is a far better, DRY, way of doing this. Yet I cannot see, nor find it. (I am new to Sinatra :))
Somehow, outside of get, I don't have request.env available, or so it seems. So putting it in an include did not work.
How do you get your base url?
You can get it using request.base_url too =D (take a look at rack/request.rb)
A couple things.
set is a class level method, which means you are modifying the whole app's state with each request
The above is a problem because potentially, the base url could be different on different requests eg http://foo.com and https://foo.com or if you have multiple domains pointed at the same app server using DNS
A better tactic might be to define a helper
helpers do
def base_url
#base_url ||= "#{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}"
end
end
If you need the base url outside of responding to queries(not in a get/post/put/delete block or a view), it would be better to set it manually somewhere.

Resources