calling ruby methods with arguments inside ERB? - javascript

I am storing a response in javascript variable. This is inside a .html.erb file.
var file = response.data.files[0];
I first made a call using
var f = "<%=link_onedrive%>"
This successfully calls a method link_onedrive
Then I made this call
var f = "<%=link_onedrive(%>file<%=)%>"
It throws an error
wrong number of arguments (0 for 1)
My question is how to make a ruby method call with argument from a erb.
edited
here's my link_onedrive
def link_onedrive(file)
uri = URI.parse("https://api.onedrive.com/v1.0")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new("https://api.onedrive.com/v1.0/drive/items/file.link/action.createLink)
req.content_type = "application/json"
req.body = '{"type" : "view"}'
response = http.request(req)
arr = JSON.parse(response.body)
arr["link"]["webUrl"]
end

ok... first you need to realise how erb works.
At the end of a controller action: Rails parses the erb and runs all the ruby first and uses it to generate some html+js code... at this point, the bit that says <%= link_onedrive %> gets completely overwritten by the result of calling the link_onedrive method... it's not there in the html anymore.
This html+js then gets sent to the browser and the browser (on the client's machine) runs the js that has already been created at this point.
You can't call the ruby from the javascript, because by that stage, there is no ruby left... just javascript.
If you want to call ruby methods from your javascript - you probably need to set up an ajax-post that posts to a controller that runs the ruby, and then returns a result that the javascript does something with.
or we need to help you rewrite the two bits of code... to get what you actually want some other way (but to do that we probably need to see what link_onedrive actually does)

Related

my jQuery parameter is not recognized by the C# method in which is accessed in script area

I tried to access the my C# method in my JavaScript, but this method is not accepting the local parameters and saying, the parameter does not exist in the current context.
var typeofServiceNumber = $("#serviceType").val();
#MyStaticClass.StringEncoding(Convert.ToString(typeofServiceNumber));
The above typeofServiceNumber is not recognized by the method
Razor code is executed server side before the HTML is returned in the response stream.
Javascript is executed client side within the resultant HTML.
Therefore you cannot pass a Javascript variable through to a Razor method, and you receive the message that typeOfServiceNumber is not recognized.
To be recognized, it would either need to be handled server side via data being passed to the View (ViewBag, Model etc), or it would need to be declared and assigned to within Razor tags on the page itself.
EDIT: to clarify the last point:
var typeofServiceNumber = $("#serviceType").val();
#MyStaticClass.StringEncoding(Convert.ToString(typeofServiceNumber))
The first line you have here is all happening in the browser of the end user.
The second line is all happening on the server. You see the error message because you are trying to pass "typeofServiceNumber" to your method, and the variable isn't even declared at that point.
Without knowing exactly what you're trying to achieve it's hard for me to give a precise answer as to how to solve your problem. But here are two possibilities:
1) You know what $("#serviceType").val() is going to be before you serve the web page to the end user because that value is being set server side.
Controller:
public ActionResult MysteryController()
{
...your code here to work out what the service type is...
ViewBag.serviceType = serviceType;
return View();
}
View:
...lots of lovely html and such...
<script>
#MyStaticClass.StringEncoding(Convert.ToString(ViewBag["serviceType"]));
</script>
I can't see what the output of #MyStaticClass.StringEncoding() is but I have to assume at this point that it is doing whatever it is supposed to do.
Although the logic is split between the controller and the view, all of this is happening server side.
The second half of my point "or it would need to be declared and assigned to within Razor tags on the page itself." refers to the fact that one variation of this method could involve manipulating data in the View itself by enclosing it in a Razor code block like this:
#{
var typeofServiceNumber = #MyStaticClass.StringEncoding(Convert.ToString(ViewBag["serviceType"]));
}
The alternative, which I did not really address originally is:
2) You don't know what the value of $("#serviceType").val() is going to be before the page is loaded because it is being set by the end user and your function needs to be used before the data is submitted to the server:
If that's the case then #MyStaticClass.StringEncoding(Convert.ToString(typeofServiceNumber)) is no good to you, you will have to replicate the function in JavaScript and include it in the webpage itself.

How to pass a json object from a Python function to Javascript with Eel where you can use and manipulate the json

This question may be a bit confusing, so let me give you some background. Eel is a Python module where you can take functions made in Python and use them in Javascript, and vice versa. What I want to do is take a json made from a Python function, put it in Javascript, and make a table based on the json that was taken from the Python side. Here's an example.
python.py
def json_example():
json = [
{
"key": "value1"
},
{
"key": "value2"
}
]
return json
js.html
<body>
<div></div>
</body>
<script>
function js_example() {
# This is where the function from Python is called
var json_obj = eel.json_example();
var tbl = $("<table/>").attr("id", "example_table");
$("div").append(tbl);
for(var i=0; i<json_obj.length; i++){
var tr="<tr>";
var td="<td>"+obj[i]["key"]+"</td></tr>";
$('#example_table').append(tr+td);
}
}
I tested both of these functions out separately with a few changes and they both work. However, here's where the problem starts. For some reason, the Javascript part is not getting anything from the function it calls from the Python code. the variable "json_obj" should be equal to the json I made in the Python function, but for some reason the return value of the function isn't creating tangible data that can be manipulated in the Javascript, basically returning nothing. And the eel transfer itself works as well. If you replace "return" with "print", it will print the json in the console.
Also, please don't tell me to just put the json itself in the Javascript. I have a reason for needing the json to come from the Python side.
So basically, here's my question: how do you get a Python function to create a value that can be manipulated in Javascript?
The problem is that when eel exposes a function what it actually does is it creates a new function that will return a promise containing the return value of your python function.
So you should have something like this instead:
let json_obj = '';
eel.json_example()(x => json_obj = x);
If you need more help on callbacks, refer to https://github.com/ChrisKnott/Eel.
Convert to json within Python if you're calling Python to begin with and send json to JS in the return value.
See: https://github.com/ChrisKnott/Eel/tree/master/examples/03%20-%20sync_callbacks
To do a synchronous operation that will take time to complete in Python and then return a value into JS, use;
let n = await eel.py_random()();
which is really
let mySlowReturnValueFromPython = await eel.myExposedPythonFunction()();
In fact I tried to code in my own promises and I was getting back garbage that looked like eel promises. The browser maintains a thread while you call this way, so the user can kick off a long Python operation and still interact with the GUI.
I'd note that you can still call things that update the GUI asynchronously. If you have a bunch of Python functions which return ready-made HTML as I do, then you can kick them all off in a row without waiting and they will update the divs whenever they return. I use this;
eel.expose(updateDiv);
function updateDiv(newData, divToUpdate)
{
var fieldToUpdate = document.getElementById(divToUpdate)
fieldToUpdate.innerHTML = newData
}
Then I call my Python function which gets the data synchronously, packs it up into a ready-made HTML chunk for the GUI, and then calls updateDiv from Python. I'm actually really enjoying the power that this "ping pong" interaction between a synchronous codebase and an asynchronous one give me when working with a GUI. Worlds better than arfing about with TK.
I hope this helps you and you can struggle less with it than I did. Once you understand how this works, Eel is really great. It apparently handles sync for you, just hand it a blank callback (or whatever black magic that is). What a great lib! Eel is just perfect for locally hosted GUI's. I'd like to see a better GUI framework than HTML/CSS/JS - the truth is that there really isn't one, those things are so well tested and stable, with so many available examples for whatever you could want to create.
I'd really like to see this become the native Python GUI solution. Browsers are extremely cross-platform and the only problem to solve when porting becomes interfacing the browser to Python.

First class functions- how are even they possible?

I'm struggling with this. I'm reading a book and the example code works really well but I can't get my head around how. The first class functions seem to twist and turn, turn themselves inside out and feed in and out of each other like magic. It goes something like this:
var data = {};
data["value1"] = fancyMethod.Value1 ;
data["value2"] = fancyMethod.Value2 ;
data["value3"] = fancyMethod.Value3 ;
getGoing( complexFunction , data);
function getGoing( complexFunction , data){
function setUpComplexFunction(param1, param2){
var param3 = param1.someValue ;
complexFunction(param1, param2, param3, data);
}
importantFunction(GetGoing);
}
The thing is the importantFunction() is the one that sets up all the processes that are used to retrieve all the parameters for the functions that feed it.
So all the params are only obtained after the importantFunction() is called. How is it possible that all the other code inside getGoing() runs OK when when it is unable to obtain its params until importantFunction() is called?
Above is a simplification of the code to just show the concepts I'm struggling with.
Actual code:
importantFunction() is actually http.createServer(onRequest).listen(8888);
and getGoing() is a function that runs the router and request handlers for the server. Coming from PHP I'm finding it strange that it seems all the requests and urls and request handlers are interpreted before the server even starts.
Source:
https://github.com/manuelkiessling/nodebeginner.org/tree/master/code/application
I guess all this will be obvious to me one day but I wonder if anyone has a simple way of explaining it for now.
importantFunction (which you haven't included the definition of) will, presumably, call GetGoing. At that point it can pass it whatever arguments it likes.
Additionally, the first time GetGoing is called, it is called by this line:
getGoing( complexFunction , data);
… which doesn't depend on importantFunction at all.

How to assign and access a javascript variable in Rails using ajax

I'm using the gon gem for rails, which allows you to save variables defined in a controller action and use them in your JavaScript. It works fine when I use it in non-Ajax settings, however, I'm having an issue with using it successfully when doing Ajax requests.
The problem: Ruby variables I assign to gon variables in the controller action when making Ajax requests come out as 'undefined' in the JavaScript.
The objective: I want to trigger an Ajax request on my page, which:
1) hits an action in the controller, and assigns a Ruby variable to a gon variable.
2) it then renders a js.erb file which executes JavaScript, part of which needs to take the Ruby variable defined in step 1, and treat it as a js variable.
here's the example action in step 1:
def some_action
gon.my_ajax_var = {some: 'info'}
end
here's the example js.erb file it renders:
/some_action.js.erb
console.log('gon.my_ajax_var equals ' + gon.my_ajax_var) //this doesn't work! comes out as 'undefined' when I expected {some: 'info'}
Any thoughts on how I fix this? I took a look at the gon.watch page, but I was confused as to whether that relates to this problem I'm having and how to implement the correct solution. Additionally, if there's a better way to do this without gon, I'm open to that as well.
Thanks!
I ended up solving this by doing the following:
In my controller:
def some_action
#my_ajax_var = {some: 'info'}.to_json
end
In my corresponding view:
/some_action.js.erb
var my_ajax_var = <%= #my_ajax_var.html_safe %>
Would've been nice to have piggybacked off the gon gem, but this got the job done.
It's some time ago that I used erb templates, but I think you need to add tags in your erb-file.
/some_action.js.erb
console.log('gon.my_ajax_var equals ' + <%= gon.my_ajax_var %>)

Passing data from javascript into .erb

I want to know if this is possible. I have a bit of javascript code that renders a page based on information from my Rails 2.3.17 application. This code is inherited and not my own. The problem is that I am trying to get data from the server about an object that I do not know about during run time. Basically I am trying to do this:
var record_id = 73;
if(<%= DataTable.find(record_id).value_of_record.nil? %>{
...
}else{
...
where the record_id is what I want to pass into the .erb selection at run time with javascript. Is this possible. And if not, is there any way I can call the information from javascript to get the id of the record passed inside the .erb file? The id is currently being stored in the html document.
As MrYoshiji said, you can use ruby instead so do something like this:
var record_id = <%= record_id = 5 %>;
if(<%= DataTable.find(record_id).value_of_record.nil? %>{
...
}else{
...
Initialising a variable in ruby returns the value so it will become just var record_id = 73; and the ruby variable is now available to the find method.

Categories