I am new to both Rails and AJAX.
I want to consume an API which is hosted on a different website. I ran into problems with cross origin HTTP request. So I tried doing this by using HTTParty.
In the code below, I am setting the text of $(".result") as JSON.parse(HTTParty()) request, so that it can query the website and give me the result.
Rails code:
<%= form_for(#profile) do |f| %>
<%= f.label :content %>
<%= f.text_field :content, class: 'ajax-control' %>
<%= f.submit "Save changes", class: "btn btn-primary" %>
<% end %>
<p class="result"></p>
Javascript code:
<script>
$(document).ready(function(){
$('.ajax-control').on('keyup',function(){
var charCount = $(this).val().length;
if(charCount===3){
var str1='<%=JSON.parse(HTTParty.get("http://example.com/api.php?param='+$(this).val()+'"))%>'
$(".result").text(str1);
}
});
});
</script>
Now comes the weird problem. The code above does send the GET request to example.com (placeholder), but gets a response saying that it is not a valid query.
However, if I pass the str1 as follows -
var str1='<%=JSON.parse(HTTParty.get("http://example.com/api.php?param=xyz"))%>'
$(".result").text(str1);
I get the expected response. If the $(".ajax-control") text field is "xyz", I get a response saying not a valid query.
Does string concatenation in javascript introduces new characters because of which it is throwing an error?
That javascript (which in turn has ruby code via erb) is not going to execute after its been rendered the first time by Rails.
That is, its not going to be invoked each time that keypress callback is called, which means that when Rails is rendering that Javascript it obviously has no knowledge of the client-side DOM so the URL is affectively:
JSON.parse(HTTParty.get("http://example.com/api.php?param="))
And the remote server has an empty param which it doesnt like...
If you really need to invoke that API for every keypress you have two options:
Get it to work via Ajax using CORS
Invoke an endpoint in your Rails app,
which in turn uses Ruby-side HTTParty to invoke the API and relay
the response back to the client.
Related
I am using the FileStack API and the file picker gem (https://github.com/Ink/filepicker-rails). I have an Attachment model that has a :title as a string. When a file is uploaded, the URL from the FilePicker API is stored as the :title. But the gem has a onchange method that returns an event variable as a JSON object that contains attributes of the file. I use JavaScript to access those attributes but I want to find a way in Rails to store those attributes, accessed via JavaScript, in a Model so that I can access it through the rest of the Rails app.
<%= filepicker_js_include_tag %>
<%= simple_form_for(#attachment) do |f| %>
<%= f.filepicker_field :title, onchange: 'onUpload(event)' %>
<%= f.submit %>
<% end %>
<script>
function onUpload(event) {
console.log(event);
var name = event.fpfile.filename;
console.log(name);
}
</script>
Update:
So after looking into your solution and googling around I am using ajax to send the data via routes to the controller. Below is my updated Javascript as well as the route and controller. When I render and inspect the #foo instance variable it is nil. So my data isn't getting passed properly. Furthermore, this whole process from the firing of the Javascript function to displaying the index view is now very very slow. I think I have the right idea after viewing your solution and doing more digging but I'm missing something and/or overcomplicating this. Any advice would be much appreciated.
<script>
function onUpload(event) {
var name = event.fpfile.filename;
jQuery.ajax({
data : { data_value: event },
type: 'post',
url: "/attachment/index"
});
}
</script>
Route
post 'attachments/' => 'attachment#index'
Controller
def index
#attachments = Attachment.all
#foo = params[:data_value]
end
View (returns nil)
<%= raise #foo.inspect %>
If you're using Postgres 9.3 or above you should consider using the hstore module and creating a JSON column. In a migration you can do:
add_column :your_model, :your_attribute, :json
And then you can just update YourModel.your_attribute => {'your': 'JSON here'}
Docs here: http://edgeguides.rubyonrails.org/active_record_postgresql.html#json
If you're using MySQL it's tricky, but doable. You have to create a text column and save the JSON as a string, and parse it every time you interact with it. Postgres is definitely better at handling JSON. I realize that this answer relies on an assumption, so if you're not using one of the two data stores mentioned, let me know and I'll pull it down.
In my RoR project I got html page, where I changing div's background image with javascript. Javascript function send me index, and I want to use this index for getting element of ruby array.
Look into my code
function drawNewProject (index){
console.log(<%= 'index' %>)
<% index = 'index' %>
<% #existProjects = Admin::Project.order('weight') %>
<% #existProject = #existProjects[index] %>
var image = document.getElementById('block_one')
image.style.backgroundImage="url('<%= #existProject.image(:large) %>')";
}
But this line
<% #existProject = #existProjects[index] %>
Gives me error
no implicit conversion of String into Integer
Do you know how to do it correct? Thnx.
You have to think that the <%= erb %> block is executed in the server before being sent to the browser, and once there, the javascript is run.
Your browser has no idea about ruby or php or whatever... it just receives the html and the js (regardless is a static file, or a dynamically generated bunch of js) and runs it.
That means that all the data must be known at rendering time. If your application depends on dynamic data, or on your user interaction, then you have to do an ajax request and deliver back a call with the right js to be run by the browser.
I want to start using websockets. I read all the docs and understand everything, but it leaves out something I need: How to pass information from view to JS?
I need to pass data from javascript to my controller. What I do not understand is, how do I get dynamically generated data in my view to the javascript to be sent?
Right now my view receives an instance variable on every HTTP request, it loops over every instance variable and makes a button which submits a hash with information extracted from that instance variable. I do not understand how to do the same thing with Javascript because Javascript will not understand Ruby classes.
This is what my code looks like now:
View/dashboards/_other_characters.html.erb
<% other_characters.each do |other_character| %>
<p><%= other_character.name %> is standing here (<%= other_character.power_level %>)</p>
<%= button_to "punch #{other_character.name}",
attacks_path(
target_type: other_character.class,
attack_type: :punch,
target_id: other_character,
target_name: other_character.name
) %>
<% end %>
This is what I would like to be able to do using JS
var task = {
name: 'Start taking advantage of WebSockets',
completed: false
}
var dispatcher = new WebSocketRails('localhost:3000/websocket');
dispatcher.trigger('tasks.create', task);
Try
<%= button_to "punch #{other_character.name}",
attacks_path(
target_type: other_character.class,
attack_type: :punch,
target_id: other_character,
target_name: other_character.name
), {id: '***', data: {name: '***', other_key: 'other_value'} } %>
Then you can access the data via jQuery data api.
When you need get dynamic data from view by client js, add data-attrs in your view dom then read it from dom API or other 3rd party js API.
In order to pass information from ruby to javascript you can use this gem: Gon, basically it transforms ruby variables and make them available to javascript on each view, take a look:
http://railscasts.com/episodes/324-passing-data-to-javascript
for any other alternative to achieve your purpose visit: https://www.ruby-toolbox.com/categories/javascript_tools#paloma
I have a controller with multiple actions/views, only one of which will take advantage of the ActionController::Live module. However, once included, AJAX actions (on unrelated pages) no longer render on the client at all.
The following code works without a problem:
my_controller.rb:
class MyController < ApplicationController
def index
// renders vanilla HTML/JS from index.html.erb
end
def update_index
// renders JavaScript from index.js.erb
end
end
index.html.erb:
<%= button_to({ controller: :my_controller, action: :update_index},
remote: true,
method: 'post') do %>
Update the text
<% end %>
<div id='content'>Some content</div>
update_index.js.erb:
$('#content').html('You clicked the button.');
The Problem:
As soon as I add include ActionController::Live to the controller, before even creating any JavaScript or Rails handles for Server Side Events (which work great), my existing code stops working. The following occurs:
Server sees the incoming AJAX request
All appropriate Controller functions are called
The JavaScript is not executed on the client side.
If you've included ActionController::Live in your controller, it seems to change the default header situation on returns to the client. Adding the following line to my non-SSE actions seemed to solve the problem:
response.headers["Content-Type"] = 'text/javascript'
But would love to hear if there's a better solution, or if I should just do this on all appropriate actions.
This is my first time trying AJAX request on Ruby on Rails. I followed the RoR guide to come up with this script. My code is as follows.
course_controller
def index
#course = Course.all
respond_to do |format|
format.html{}
format.js {}
end
end
views/courses/index.js.erb
$('#dummy_div').hide();
views/courses/trial.html.erb (view from where I am calling the AJAX / index controller)
<body>
<%= form_for(Course.new, :method => :get, remote: true) do |f| %>
<%= submit_tag "Search", :name => 'course_list' %>
<%end%>
<div id = "dummy_div" style = "width:100px; height: 100px;background-color:black;"></div>
</body>
My expected result is that the div should disappear once I have submitted the Search function. However, this does not happen. I have not put in embedded ruby because I am just testing whether plain JS works in the first place. My intention is to put in erb later (just to be clear that I am testing this for AJAX). Why does the JS in the index.js.erb file not get executed?
Additionally, how do I debug AJAX requests in Ruby on Rails?
What I have done above was absolutely correct and should be the correct way to route to the js file. This was actually an issue with initializing the model object course and had nothing to do with the code above (I had a small typo mismatch with the model name - Course).
A better way to test the ajax than making the div disappear is using the console.log("i'm at: views/courses/index.js.erb"); or alert("i'm at: views/courses/index.js.erb"); as mentioned by John in the comment above.