问题
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"):
回答1:
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?
回答2:
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.
来源:https://stackoverflow.com/questions/25189818/button-to-in-email-not-posting