Rails Render Index with URL Parameters - ruby-on-rails

At my work, we are in the middle of breaking up our Rails monolith. We are currently serving our react app through the asset pipeline. I am implementing JWT for authentication. I am trying to pass the token in the url without using sessions/cookies as part of an admin impersonating a user.
class ReactPagesController < ApplicationController
def index
render :index #this will open up the react app
end
end
Is it possible to render a view and pass along parameters in the url?
I want this to open up the index page with url parameter (i.e. localhost:4000/users?jwt=abc.def.ghi
I've tried doing something like render :index, jwt: abc.def.ghi, but that doesn't work. Is the only way to do this via redirect_to?

You are actually defining a redirection:
You want to go to localhost:4000/users
The page display the index page, and URL becomes localhost:4000/users?id=123
For the normal webpage, changing URL will make the browser redirect. As you can see the result when executing this JS in the Chrome Console:
window.location.href = "google.com"
the browser will redirect you to google.com
So, for a Rails's application, you should do a redirection by redirect_to to achieve the current needs.
However, if you really want to change the URL without redirection, you can do it via Javascript. Just use window.history to change your URL
Your controller:
# app/controllers/users_controller.rb
def index
#desired_id = 123
end
and your view
<%-# app/views/users/index.html.erb %>
<!-- rest of HTML -->
<script>
window.history.pushState("", "", "?id=<%= j #desired_id %>");
</script>

you can use redirect_to
redirect_to users_url, id: 5
will get you to /users?id=5

I don't think so, render is for rending the view and has nothing to do with the setting the url.
ruby docs

Related

How to render a different controller / action from within an action in Rails 4.2?

I know this is possible but I want to render a controller / action in response to a different action like in my routes.rb, I have:
get ':handle' => 'handler#index'
and in handler_controller, I have:
def index
handle=Handle.where('handle=?',params[:handle]).first
if handle.handle_type=='Location'
# call location / show with id from handle
else
render text: "not found"
end
end
How would I do this? I should mention, I don't want to do a redirect.
Maybe this can help:
def action_that_calls_one_from_another_controller
controller_you_want = ControllerYouWant.new
controller_you_want.request = request
controller_you_want.response = response
controller_you_want.action_you_want
end
You can solve this by using an "internal redirect" approach.
Inside rails this can be done via middleware that calls #app again and tracks redirect loops. See tutorial here
Also can be done by utilizing nginx's X-Accel-Redirect: make a regular routes for referenced resources, but instead of regular redirect issue a X-Accel-Redirect header, for user it will be like your page rendered without redirect.

Handling a redirect from an old permalink to a new one

I have a Page model in my rails 4 app. It has an :permalink attribute that is used so that when someone goes to "mysite.com/pages/page-name", the controller finds the Page with "page-name" as the permalink and then shows the view.
pages_controller.rb:
def show
#page = Page.find_by_permalink!(params[:id])
end
After a few months of the site being up, I want to change the permalink of a certain page, however I don't want to lose all the incoming links. I'm thinking I would do this.
First I'd add_colum :new_permalink to the Page model. Then if this :new_permalink attribute was anything but nil or blank, it would pull up a new page in the controller like this:
def show
#page = Page.find_by_permalink!(params[:id])
if !#page.new_permalink.blank?
#page = Page.find_by_permalink!(#page.new_permalink)
end
end
This works, but the url in the browser still shows the old URL. I suppose this might not be so bad, but I think I'd like it to actually forward to the new page. Perhaps, instead of "new_permalink" it should be a new url and actually do a redirect? What would be your best solution for this? And could I make it a 301 redirect?
Yes, you should use a 301 redirect so that both the user and search engines would send the browser to the correct location.
def show
#page = Page.find_by_permalink!(params[:id])
if #page.new_permalink.present?
redirect_to page_path(#page.new_permalink), status: :moved_permanently
return
end
end

Rails 3.2 - How to merge params without displaying everything in the URL?

In my app I have a /thanks page that users were originally redirected to when completing a certain action. Now I want to redirect them to this page after multiple kinds of events and render different partials based on what the event was. So I added this to the /thanks page:
- case #event
- when "reservation"
= render 'thanks_job_created'
- when "charge"
= render 'thanks_job_charged'
Then, in the the JobsController#create action, I changed redirect_to thanks_jobs_path to this:
redirect_to thanks_jobs_path(params.merge(event: "reservation"))
...and added #event = params[:event] to JobsController#thanks.
The behavior works as intended, but I've found that using params.merge this way now displays every paramter in the URL, including authenticity token of the #create form, all of the Job attributes, etc. Before the URL looked correct (/jobs/thanks) because the only params were action and controller which are already indicated in the URL.
Is there a way for me to use params.merge without displaying all of that info in the URL?
If you just want to pass the event as a parameter, you don't need to use params.merge at all.
redirect_to thanks_jobs_path(event: "reservation")
will give you the path /jobs/thanks?event=reservation.
You could simply use except:
params.merge.except(:auth_token)
In your situation:
redirect_to thanks_jobs_path(params.merge(event: "reservation").except(:auth_token))

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

redirect_to inside view - RAILS - DEVISE redirect to user_session_path

How do I redirect_to a certain path or page inside the view. I've read that redirect_to is an ActionController something, and cannot be used in the view. How can I do this in the view using only Rails, and how can I in addition to this write the redirection inside the controller or the model or helper and then just writing in the instance variable inside the view. I am using Devise. I do not want to use Javascript nor JQuery. Just Rails!
I tried this:
class Post < ActiveRecord::Base
attr_accessible :content, :title
#Uchecker = user_signed_in?
redirect_to user_session-path
end
When you use the *redirect_to* from a controller, instead of rendering a view, what it does is to render an http redirect
Now if you want to do a redirection from the view, you can still use javascript
<script type="text/javascript">
window.location = "<%= user_session_path %>";
</script>
Not the best practice but it works, and its a common practice for intermediate pages (i.e. when you search for a trip, the trip search could take like 60 seconds, so you render a view where you show something to the user like you are searching for the best trip, and you do a javascript redirection, once the result is ready, the page is loaded).

Resources