Simulate redirect_to with remote option - ruby-on-rails

I have the following scheme:
lessons_controller -> show.html.erb, which contains *form_tag* with remote: true -> test_controller -> show.js -> _test.html.erb
So I receive the content of _test.html.erb when submit the form_tag on lesson/show page.
But I want to skip the lesson/show page in some cases.
So I want to go to the lesson/show page and receive the content of _test.html.erb without submitting anything, under the ground. Something like redirect_to in lessons_controller with remote option to simulate the form_tag submitting.
Is it possible?

Not sure your purpose, if you only want to show the form directly, it's as simple as putting following in js assets
$ ->
$(form#show_lesson).submit()
If you want to control it in controller level. You can do the following.
# Lessons controller
def show
#lesson = Lesson.find params[:id]
template = params[:show_directly].present? ? 'show' : 'show_with_test'
render template
end
# views/show.html.erb
render partial: 'show_form'
# views/show_with_test.erb
render partial: 'test', locals: {lesson: #lesson}
Use
Browse lessons/1 will show original form
Browse lessons/1?show_directly=1 will show all directly.

I think you can just invoke javascript submit when lessons#show is loaded, and use the callback data from _test.html.erb.
I don't think it's possible and good way to make a redirect request with a 'script' type.

Related

Rails + ajax, my "edit.js.erb" is not being run

I'm trying to setup ajax within rails, but I am having trouble getting my "edit.js.erb" to be ran
My edit.html.haml
= f.check_box :foo, {checked: eligibility_data.foo, class: "foo", remote: true}
controller
def edit
#survey = Foo.find_by_id(params[:id])
respond_to do |format|
format.html
format.js
end
end
edit.js.erb
alert("Testing");
How can I get edit.js.erb to run? Once it's working I want to append html to my view, will I be able to place that html right into my js.erb, or will I have to make a partial of some sort?
You can't append remote: true to a checkbox and expect it to fire off.
It needs to either be attached to the parent form tag of said checkbox, or you need to write some js that watches that checkbox.
If you go the watcher route, the JS will send an ajax call when the box gets clicked on.
Here is a link on how to do AJAX with jQuery (which is built into rails)

Add a "Thank you for your order" page that is not directly visitable

When the user purchases an item we want to display a thank you page.
Then again we want this page not to be directly visitable.
In other words, if the page was to be /orders/thankyou, the user could directly navigate to it which would be rather ugly and fail aas it would have nothing to show.
how can we show this page only when in context and forbid direct navigation to it?
You can create a partial form and append it to the DOM after the purchase event is fired. In the partial view, be sure to add a redirect action if it was accessed without the purchase event firing.
For just displaying short text (and not also e.g. the order data) you could just use a flash notice. For example:
redirect_to #page, notice: "Thank you for your order!"
Ajax
Sounds like you'll be best using ajax:
#app/views/cart/index.html.erb
<%= form_tag cart_order_path, remote: true do |f| %>
... (cart form)
<%= f.submit %>
<% end %>
This (obviously very simple) form will send a "remote" (Ajax) form submission to your controller. The reason why this is important is because you will then handle the response directly in that page you just sent the request from:
#app/assets/javascripts/application.js
$(document).on("ajax:success", "#your_form_id", function(status, data, xhr) {
$("your_page_div").html(data);
});
The trick here will be to render your thank you view without a layout -
#app/controllers/cart_controller.rb
class CartController < ApplicationController
respond_to :js, only: :create
def create
... business logic here
render "thank_you", layout: false
end
end
This will render the view you want without any of the supporting "layout" HTML - giving you the chance to append that to your current view. This means that if you wanted to show the "Thank You" view without letting the user browse to it directly - that's what you'll do
How It Works
Ajax (Asynchronous Javascript and XML) is a javascript technology which basically allows you to send "pseudo requests" to your Rails backend:
Basically the same as a standard HTTP request, except handled with Javascript, Ajax gives you the ability to create the appearance of "no refresh" functionality in your app. It does this by sending requests on your behalf, through Javascript.
Ajax is typically used for small pieces of functionality on web interfaces - whereby you'll have the ability to send simple requests to the server, gaining a comparable response that you can then work into the DOM.
This is the functionality I have been proposing - whereby you'll be able to send a request to your controller (albeit using the Rails UJS engine), to which you'll then receive a response. This response can then be worked into your page, thus providing you with the ability to show the "Thank You" page without the user refreshing.
You can use any solution from the following:
Using ActionDispatch::Flash:
flash[:notice] = "Thank you for your order!"
redirect_to #page
or
redirect_to #page, notice: "Thank you for your order!"
Using alert, in show.js.haml file (assuming you use action show in orders_controller.rb):
alert("Thank you for your order!");
and then add respond_to :js, only: :show, and format.js in action show for orders_controller.rb

ajax link not working though jquery is loaded

I have a link to in my view
= link_to "Remove from Handy List", {controller: "handy_lists", action: "destroy_via_ajax", tradie_id: "1"}, method: :get, remote: true, class: "pull-right"
In my routes I have
get "handy_lists/destroy_via_ajax/:tradie_id", to: "handy_lists#destroy_via_ajax"
The action for now simply displays
def destroy_via_ajax
puts "it deletes"
end
Whenever I click the button the server isn't responding. I've checked and javascript and jquery are loaded so I know it can't be that. I don't know what I'm missing. What's wrong with the link and how can I fix it?
There are several things which could be wrong:
Is your remote link working?
This would be the first thing to test. I would use the development console in either Chrome or Mozilla & click on the "network" tab, to see if the link is actually requesting some sort of ajax link.
Likelihood is that it is, but I don't think you've set up your system correctly
Your controller setup could be incorrect
You're calling the action "destroy with ajax"... why not just use the respond_to function in the normal destroy action?
You could try this:
def destroy
respond_to do |format|
format.js
end
end
This will allow you to create destroy.js.erb in your views/controller folder, where you can then call something like:
alert('Deleted Successfully!');
This should work, but I am open to chat if you need more help!

Don't render layout when calling from Ajax

I have a rails action called index that renders the content for my page along with the layout. When I go to the /index action with a browser it works like expected. I want to be able to also render this action by calling it with Ajax, I am doing this using the following:
<%= link_to "Back", orders_path, :id => 'back_btn', :remote => true %>
<%= javascript_tag do %>
jQuery("#back_btn").bind("ajax:complete", function(et, e){
jQuery("#mybox").html(e.responseText);
});
<% end %>
When the action is called this way I would like it to render and pass the index action back, excluding the layout. How can I do this?
You should be able to add a format.js action to your controller action like so:
respond_to do |format|
format.js
format.html
format.json { render json: #foos }
Ideally, you would want to create a index.js.erb file that would build the contents of the page:
$('#foos_list').update("<%= escape_javascript(render(#foos)) %>");
If you're going to update the contents of a div, to basically update a whole page inside of a layout, then you're going to want to change it up a little bit. Inside of the format.js, you can do this:
format.js { render 'foos/index', :layout => false }
But if you're trying to go with an ajaxified front-end, may I recommend a framework for doing this, like Spine? It will go a long way in helping you build your site.
Also, using a framework like this will force you to separate your application per #Zepplock's second suggestion.
You can just detect if the request is an XML HTTP Request, then render a blank layout like so:
render layout: 'blank' if request.xhr?
You'll need to create a blank layout in app/views/layouts/blank.html.erb like this:
<%= yield %>
You need a way to let server know that there's a difference in request type. It can be done in several different ways:
Append a key value to the URL (for example layout=off) and change your controller logic to render data with no view. This is kind of a hack.
Make your controller return data via XML or JSON (controller will know what content type is being requested) then format it accordingly and present in browser. This is more preferred way since you have a clear separation between content types and is better suited for MVC architecture.
Create an API that will serve data. This will lead to separate auth logic, more code on client side, additional APi controller(s) on server etc. Most likely an overkill for your case

Rails - display results of index and show actions via ajax

I have a very simple Post resource with two actions, index and show. My template contains a sidebar with links to each previous post. I want the sidebar links to display their content (i.e. the results of the "show" action) via ajax
I know there are lots of excellent tuts that show you how to create a form that submits with ajax but this time I want to use it to display the contents of my index and show actions without page referesh
. Are there any decent tutorials out there that give tips on how to do this?
I reckon I need to create a show.js.erb file, and tell my index action to respond to js but I'm a little bit stuck getting any further. I don't quite know what to put in controller's show action or show.js.erb - it's a little difficult to visualise what I need to do
PS - using rails 3.0.7, jquery-1.5
Got this working, it was very simple in the end.
Step 1 - add :remote => true to links in sidebar
#application.html.haml
%nav#sidebar
- for post in #posts
= link_to post.title, post_path, :remote => true
%div#main
= yield
Step 2 - tell your controller to respond to JS on the show action
def show
#post = Post.find(params[:id])
#posts=Post.all # needed for sidebar, probably better to use a cell for this
respond_to do |format|
format.html # show.html.erb
format.js # show.js.erb
end
end
Step 3 - Create _post.html.haml
# _post.html.haml
%article.post
= sanitize post.body
Step 4 - Create show.js.erb and replace the html in the #main div with the contents of the _post partial (that we created in step 3)
# show.js.erb
$("#main").html("<%= escape_javascript(render #post) %>");
Now all the content is passed via ajax and it's working fine.
I don't have a full answer at hand, because I'm relatively new to this, too.
But, I would start by taking a look at JQuery's get() method. You should be able to use that to call the index or show method. Those methods should return the html that you want to display in the non-sidebar section of the page. You can use get()'s callback handler to place that HTML into the appropriate div on the page.
Sorry that this is a little vague, but if you play with this I bet you'll figure it out.

Resources