Reputation: 2512
I have a working Ruby on Rails form that currently posts my results and redirects the user to another view and posts the results. The flow is:
views/tools/index.html.erb -> views/tools/ping.html.erb
Since I have it working now, I'd like to convert it to AJAX and keep the user on the views/tools/index.html.erb
view, getting rid of the redirect to enhance the user experience. However, I'm unsure of how to proceed based on the way that my Tools
controller is currently setup, and my incredibly lacking knowledge of AJAX.
So, here's what I currently have:
views/tools/index.html.erb (added 'remote: true' to form)
<h1> Tools </h1>
<h3> Ping </h3>
<%= form_tag ping_tool_path(1), method: "post", remote: true do %>
<%= text_field_tag :ip, params[:ip] %>
<%= submit_tag "Ping", name: nil %>
<% end %>
<!-- this is where I'd like to put the results via AJAX -->
<div id="output"></div>
controllers/tools_controller.rb
class ToolsController < ApplicationController
def index
end
def ping
ping_host(params[:ip])
save_host(params[:ip])
# Adds based on recommendations
respond_to do |format|
format.html { redirect_to tools_path }
format.js
end
end
protected
def ping_host(host)
f = IO.popen("ping -c 3 #{host}")
@output = f.readlines
tool_type = "ping"
tool = Tool.find_by(tool_type: tool_type)
tool.increment(:tool_hit_count, by = 1)
tool.save
@results = "<pre>#{@output.join}</pre>".html_safe
end
def save_host(host)
host = Host.find_or_create_by(host_ip: host)
host.increment(:host_hitcount, by = 1)
host.save
end
end
views/tools/ping.html.erb
<%= @results %>
views/tools/ping.js.erb (New file based on suggestion)
$("#output").html("<%= @results %>");
routes.rb
Rails.application.routes.draw do
root 'tools#index'
resources :tools do
member do
post 'ping'
end
end
end
This is what I see on the Network tab in Google Chrome after submitting the form:
So, what I know at this point is that I'll need to add remote: true
to my form in views/tools/index.html.erb
, and this is where I get lost.
It seems that I have an issue ATM with the fact that I've abstracted the form to use my ping
method in the Tools
controller, whereas all of the tutorials (and railscasts) I've gone through are doing AJAX on CRUD methods and a given model, not something like what I've build here so far. Please help me understand AJAX!
Upvotes: 1
Views: 280
Reputation: 907
You're on the right track, now you need to modify the def ping
action with a respond_to
block.
def ping
ping_host(params[:ip])
save_host(params[:ip])
respond_to do |format|
format.html { redirect_to tools_path } ## if you still want to have html
format.js
end
end
and create a file called view/tools/ping.js.erb
where you have javascript that will be run and returned asynchronously
$("#output").html("<%= j @results %>");
The <%= %> block will be evaluated first and replaced with the output of that ruby code. Then this will be inserted into the #output div.
Upvotes: 2