named route's URL in Rails - ruby-on-rails

HI,
I have a problem printing the named route's URL in production application. In one of my email template (email registration confirmation), am trying to append the confirmation url. this is the template snippet
<p>Welcome to example. To complete your registration, please click on the link below or paste it into a browser to confirm your e-mail address. You will then be redirected to example.com login page </p>
<p> <%= confirmlogin_url(:id => #user.id, :msg => #user.verification_code )%> </p>
and my named route looks like this
match 'confirm_registration' => 'users#confirm_user' ,:as=> :confirmlogin
It works fine in the development environment, and the email is rendered with the confirmation url like this
Welcome to example. To complete your
registration, please click on the link
below or paste it into a browser to
confirm your e-mail address. You will
then be redirected to example.com.
http://localhost:3000/confirm_registration?id=16&msg=7fe548db-ab7d-3a8d-a87f-94ba89b0c29b
But in production environment i expected localhost:3000 be replaced with my actual domain name. But it still prints the local host url..
I just wanted to confirm this is the expected behavior..?

Put this onto your production.rb
ActionMailer::Base.default_url_options[:host] = "0.0.0.0:3000"
Use your hostname.

Related

Link to non http protocol from a Rails mailer template

I'd like to have a link in an email (opened on an iOS devise) open an iOS app.
I have Rails mailer template that contains a link, which opens the app 'myapp' on an iOS device:
<%= link_to 'Reset my password', "myapp://?password_reset_token=#{#token}" %>
This link is rendered properly when used in a regular view, displayed in a browser.
The problem is when the link is used in a mailer template it displays without the href:
<a href>Reset My password</a>
I get the same results when I put the <a> tag manually in the template instead of using link_to. Still results in blank href.
It seems that using any protocol other than http or https yields the same results.
Is there any way to make this non http link display properly
The way I got around this was to adjust my url like this:
"myapp://myapp.com?password_reset_token=#{#token}"
The addition of the 'myapp.com' part made it work, and I can just ignore that part, and parse out the query params that I need.
Above solution do not work as
when I check mail in gmail the href remove from mail, it looks like <a href>Reset My password</a>
So I have done a workaround for it
I have redirected to a route and in that I embed script as below
<script>
$(function(){
window.location = "myapp://myapp.com"+window.location.search
})()
</script>
so it will redirects with all parameters to the URI

Button_to in email not posting

SEE UPDATE for evolution of this question
On my website, each user has a dashboard where s/he can click a link to either ACCEPT or DECLINE an request. Depending on what is clicked, the Request record is then PATCHed with the relevant status. To make it easier for users, I'm trying to embed this dashboard in an email to them so that they never have to go to the website directly; think of an email that looks like this:
Hi there,
You have the following requests, click ACCEPT/DECLINE next to the request to do so
Request A: ACCEPT, DECLINE
Request B: ACCEPT, DECLINE
....
The only way to make this work thus far has been to have a parallel set of GET routes for the links used in email, versus the PATCH routes for the links used in the actual website dashboard.
Wondering if there's a better way of doing this?
Routes
patch 'inventories/:id/accept', to: 'inventories#accept', as: 'lender_accept'
patch 'inventories/:id/decline', to: 'inventories#decline', as: 'lender_decline'
get 'inventories/:id/accept_email', to: 'inventories#accept', as: 'lender_accept_email'
get 'inventories/:id/decline_email', to: 'inventories#decline', as: 'lender_decline_email'
Link in email
<%= "#{link_to 'ACCEPT', lender_accept_email_url(borrow), method: :patch} or #{link_to 'DECLINE', lender_decline_email_url(borrow)}" %>
Link on website dashboard
<%= "#{link_to 'ACCEPT', lender_accept_path(borrow), method: :patch} or #{link_to 'DECLINE', lender_decline_path(borrow), method: :patch}" %>
UPDATE
Ok tried the button_to to generate a form to POST to avoid using GET to do POST as was the "patchy" solution above, still not working...
Routes:
post 'inventories/:id/accept', to: 'inventories#accept', as: 'lender_accept'
post 'inventories/:id/decline', to: 'inventories#decline', as: 'lender_decline'
Mailer view:
<%="#{button_to 'YES', lender_accept_url(borrow), method: :post, id: "accept #{borrow.id}", style: "background-color:green; color: white; width: 40px; display: inline"} %>
<%="#{button_to 'NO', lender_decline_url(borrow), method: :post, id: "decline #{borrow.id}", style: "background-color:gray; width: 40px; display: inline"}" %>
I did an inspect element on the email as well just to confirm that the button_to was generating the appropriate code:
<form action="inventories/2037/decline" method="post" target="_blank" onsubmit="return window.confirm("You are submitting information to an external page.\nAre you sure?");"><div><input style="background-color:gray;width:40px;display:inline" type="submit" value="NO"></div></form>
<div>
<input style="background-color:gray;width:40px;display:inline" type="submit" value="NO">
</div>
</form>
In my mailer settings, I set the host properly to my domain name, so when I get the email and click the button, I get taken to /inventories/2037/decline appropriately, but I still get the error, because apparently the logs say I'm still trying to go for GET... why is that??
2014-08-17T06:18:03.206205+00:00 app[web.1]: ActionController::RoutingError (No route matches [GET] "/inventories/2037/decline"):
Wondering if there's a better way of doing this?
Making GET request is ideal solution. Don't use any other request. It either be not supported by email client and potentially add big security hole.
It is your misconception that big websites use post/patch requests to perform such action in email. They all use get requests, they include some token which is tied up/trigger that particular action when user visits there website.
OK tried the button_to to generate a form to POST to avoid using GET to do POST as was the "patchy" solution above, still not working.
Obviously, it won't work. There is no rails JavaScript file. Moreover, even if you include it it won't work either, because of csrf-token token. External form submission is not allowed by default in rails application.
My suggestion is to send user to your dashboard with some extra parameters like www.example.com/dashboard?take_action=accept and use JavaScript to trigger the required action. This will is best practice. This will avoid you using lender_accept request as get.
To to more precise, don't do this.
get 'inventories/:id/accept_email', to: 'inventories#accept', as: 'lender_accept_email'
get 'inventories/:id/decline_email', to: 'inventories#decline', as: 'lender_decline_email'
This is bad. Since, get request isn't for updating/deleting.
Since, you want to link this actions into your email, you should put dashboard link with some extra parameter. Now, with JavaScript perform accept/decline action whenever you see those parameters which you passed to your email.
More:
Can I put both Get and Post URL link in an email
Is it possible to perform a HTTP POST from a HTML email?
Is it possible to send a POST request from within an Outlook email?
I'm pretty sure the link in the email will not be able to use "PATCH" method because the email doesn't have rails.js. (https://github.com/rails/jquery-ujs/blob/master/src/rails.js)
I don't think embedding rails.js will work though because most email legit providers will probably disable javascript in emails.
You can add get 'inventories/:id/accept', to: 'inventories#accept', as: 'lender_accept' in your route to circumvent this problem, but if using get is bad practise if you are actually changing anything in database.
My easy solution would be to link the user to some page where they can accept or decline on your website rather than accept or decline from the email.

Rails Devise "You need to sign in or sign up before continuing"

everybody.
I was using Devise for authentication in Rails 4 and got some troubles with Devise. When I enter the link: http://yourdomain.com:3000/users/edit.535db919486f611779000000 , it just render the text "You need to sign in or sign up before continuing." without rendering layout, instead of redirect to login page (see attachment)
I guess Rails understand the numeric after "edit." is format and it didn't know how to render it.
What I want is when user enter any link without logged in, it will redirect to login page. Could anyone help me?
With this link, it throw an unknown format exception.
Your problem is to do with the passing of a value after . - EG edit.234234324 or login.23424234
As you can see from your screenshot, you're receiving the error because Rails is treating the number as a format (in the same way it would treat .html, .js or .json as formats)
I don't know why it works for edit, but it looks like it's rendering json to me, probably because it's confused with the type of format you've sent
The way to fix this is to get your config/routes.rb & URLs fixed
You've not detailed how you're sending the numbered requests to your URL helper, but if you're requesting pure URLS, you need to remove the number from the end:
localhost:3000/users/login
localhost:3000/users/edit
These are the URLs which should load (with no numbers)
I would imagine you are getting the error because you're calling the devise url helpers like this:
<%= link_to "login", user_new_session_path(some_value) %>
You just need to use user_new_session_path

Create Link to External Website

I am trying to create an external link to each individual listing's assigned website address. Using the following code: (The listing website is saved as google.com)
External Link
Takes me to:
localhost:3000/google.com
Is there any way to generate a link that would go to www.google.com instead of trying to find a route in my application.
The reason why it's bringing you to localhost:3000/google.com it's probably because the string you are passing to the href attribute is not a full qualified URL.
In fact, if in HTML you write
External Link
The string will be appended to the current page path. You should make sure that the input you pass always contains the schema. If the input never contains that, then you can assume it's http://
External Link
But this is not really a solution, just a workaround. You should definitely make sure that when you populate the website URL, you store a complete URL. In fact, some sites may require https.
In Rails you normally use the url_for and link_to helpers to generate an URL, but they will both cause the same issue unless you pass a full URL.
<%= link_to "External Link", "http://#{listing.website}" %>
Do it the Rails way:
<%= link_to 'External Link', "http://#{listing.website}" %>
You need to put in the protocol.
Google
Do you get it? =)
You can create link like this:
External Link

the method problem and the difference between url and path

when i read the book "Aglie web development with rails 4th",i found the code
<%= button_to 'Add to Cart', line_items_path(:product_id => product) %>
what's the difference if i use "line_items_url" and the code doesn't has the method like :method=>:post,
why?
The path version produces relative urls such as /order/34/lines/ while the url version produces a full url such as http://localhost:3000/order/34/lines/.
The second form is often used in mailers when the user click a link in a mail client or in an external webmail.
In your site you won't notice any difference.
Moreover the :method=>:post option will produce a post request to your webserver. It will do that by adding a javascript code which will create a form on the fly, add parameters to it and do a submit call to send your browser to the requested page with a post method.
The _url helper generates an URL that includes the protocol and host
name. The _path helper generates only the path portion.

Resources