Catching 301 redirection in rails - ruby-on-rails

There are certain cases in which we are doing a 301 redirect for pages from the controller. redirect_to product_show_path(updated_id), status: :moved_permanently. These redirections are working but we want to setup a custom meta tag when user is landing on a page by a 301 redirect. Is there any way to know it globally that is set it in the application.html.erb file?

Use query string parameters to send additional data with a GET request (a 301 Redirect is always a GET request).
redirect_to product_show_path(updated_id, redirected_from: URI.encode(request.original_url))
This creates a param in the params hash just like any other:
<%= if params[:redirected_from].present? %>
You where redirected from <%= URI.decode(params[:redirected_from]) %>
<% end %>
This unlike the HTTP_REFERER header works in all browsers.

Related

Turbo Stream Rails does not update page

I am new to Ruby on Rails and need help with figuring out how Turbo Stream works in Rails.
I did everything by tutorials, however, the content of the page was not updating. I decided to test how Turbo Stream will behave on simple div.
In index.html.erb file I created such div with id="test":
<div id = "test">Hallow</div>
In the same file I am creating a button that calls method refresh in controller.
<%=button_to " ", refresh_path(:task => task, format: :turbo_stream)%>
The method is called and works properly, I have already checked it without Turbo Stream.
The content of refresh.turbo_stream.erb:
<%= turbo_stream.replace 'test', partial: 'refresh' %>
The content of _refresh.html.erb
<h1>GoodBye</h1>
Here is the proof that Turbo Stream works
Indeed Turbo Stream renders the page, but I get such an output.
I tried writing respond in controller, deleting turbo_stream format (it caused another error), playing with routes, but did not come up to anything.
I am sorry if this question might have been answered already, but I tried different options and nothing worked for me. Please help!
Turbo doesn't process links with formats other than html (apparently php as well).
So when you click a link or a button, that has ".json", ".xml", or ".turbo_stream" or anything else, Turbo gives up and just sends you directly to that page where browser displays it the best it can, and it knows nothing about what to do with turbo_stream, which has Content-Type: text/vnd.turbo-stream.html, so, plain text in the browser.
To fix it, remove :format:
<%= button_to "refresh", refresh_path(task: task) %>
With this button, Turbo will send a correct request, where it will wait for html or turbo_stream response, which you can see in the request header:
Accept: text/vnd.turbo-stream.html, text/html, application/xhtml+xml
If the server then responds with turbo_stream format: Content-Type: text/vnd.turbo-stream.html then stream instructions will execute on the current page. There are other rules, but one step at a time.
To render an appropriate response use respond_to method in your controller action:
respond_to do |format|
format.html { render :page } # renders `page.html.erb`
format.turbo_stream { render :page } # renders `page.turbo_stream.erb`
# or render <turbo-stream> inline
# format.turbo_stream { render turbo_stream: turbo_stream.replace :test, partial: "test_partial" }
end

Finding the current URL or "main" controller from within a Turbo Frame in Rails

I have a Turbo Frame on my page which uses the src attribute to load in /chats/. Within this frame I want to be able to know whether the main page is using the show action of the groups controller, i.e. the URL of the page is at /groups/group_name.
Using current_page?(controller: 'groups', action: 'show') returns false as it sees itself as in the chats controller. How do I work around this?
Here are the options I've found:
request.referrer
There doesn't appear to be a built-in way of getting to the controller class / action in the way that you're describing, but you can access the URL of the page which initiated the Turbo request (groups_controller#show) through request.referrer. This will be the fully-qualified URL for the page, such as http://localhost:3000/groups/1/show.
use query parameters
This requires changes to view code (you must add query params to all links where you need this functionality), but it allows you to pass controller/action names and any other arbitrary data you'd like.
Example:
in application_controller.rb:
# define a method to capture the information you wish to access during your Turbo stream request
def current_route_info
{
path: current_path,
controller: params[:controller],
action: params[:action]
}
end
No need to touch the groups controller in this example.
in show.html.erb (the page which submits the Turbo request)
<%= form_with url: turbo_view_path(info: current_route_info) do %>
...
<% end %>
OR
<%= link_to turbo_view_path(info: current_route_info) do %>
...
<% end %>
OR
<!-- you could also manually build the URL & encode the query params if you need to avoid URL helpers-->
<turbo-frame id="" src=chats_partial_path(info: current_route_info)>
...
<turbo-frame>
chats partial controller (which handles the Turbo request)
def turbo_view_method
params[:info]
# => info as defined in current_route_info
end
use flash
I've just learned the many ways you can use flash for this type of functionality that extends across requests. This is less work than using query parameters, mainly because you don't need to adjust your view code.
Example:
groups controller (which renders the show view, which submits the Turbo requests)
def show
# stick the current controller and action params into flash
# again, you can add any other arbitrary (primitive) data you'd like
flash[:referrer] = params.slice(:controller, :action)
...
...
end
chats partial controller (which handles the Turbo requests)
def chats_turbo_method
flash[:referrer]
# => { controller: "some_controller", action: "show" }
# NOTE: flash will retain this :referrer key for exactly 1 further request.
# If you require this info for multiple Turbo requests,
# you must add:
flash.keep(:referrer)
# and you will have access to flash[:referrer] for as many Turbo requests as you want to make from group#show
end

Rails Render Index with URL Parameters

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

Remove http of url for displaying website addresses in rails

In my rails app, each supplier has a website address which is displayed on their supplier show page (value is #supplier.website).
If the website url begins with http:// I'd like to remove this from the view page i.e. rather than displaying http://www.google.com it would just display www.google.com (but the actual #supplier.website will remain unchanged).
Hope that makes sense, and that someone can help...Thanks
You can do that with a URI parse.
uri = URI.parse 'http://google.com/whatever'
uri.host #=> 'google.com'
uri.path #=> '/whatever'
Best to make a helper
def website_link_text(uri)
URI.parse(uri).host
end
And then in the view:
<%= link_to website_link_text(#supplier.website), #supplier.website %>

Respond with javascript to an HTML request?

Is it possible to respond to an HTML request with javascript? By this I mean that I don't want the page to be refreshed and plus execute some javascript code. I wonder if this is possible by changing only the server side?
In my action, I have something selected to respond to js and html like this:
respond_to do |format|
format.js
format.html
end
And I have a .js.erb file that, of course, should be rendered when the browser requests a javascript.
Can this be done? How?
You cannot do this by only changing the server side code. If you'd like javascript to be executed upon the server's response, then the form will need to be submitted through javascript. This is because javascript will eval the response from the server and run the code.
This can somewhat be trivially added in Rails:
<%= form_for #user, remote: true %>
When it is submitted, then you can send back javascript. For example, to alert that a user was added:
/app/views/users/create.js.erb
alert("user <%= j #user.email %> was added");

Resources