Edit model - token URL - ruby-on-rails

I want users to be able to edit a model through a different than the default URL /merchants/:id/edit(.:format), which will be using a token. This token is created randomly and stored in the database.
The link I want to create will be similar to this merchants/token-124512/edit.
Now I want to be able to send this link to users via e-mail. The default link with the id is link_to "link", edit_merchant_path(#merchant, :only_path => false).
How would the one with token be like? Also, how can I declare this one in the routes.rb?

Solution
First of all I would suggest to use _url instead of _path in your mailer because you want to resolve full path.
Try with:
link_to "link", edit_merchant_url(id: #merchant.token)
Why _url?
using _path will get you <a href=merchants/token-124512/edit'>link</a>, but in mail you want to know host as well so you should get this:
<a href='hostname.com/merchants/token-124512/edit'>link</a>

If you are using rails 4, you can use the new concept called 'param' in your routes, which will change the default route.
You can pass any field instead of your id.
# config/routes.rb
resources :merchants, param: :token_field
# app/controllers/merchants_controller.rb
#merchant = Merchant.find_by(token_field: params[:token_field])
Example
resources :merchants, param: :your_fleld
merchants GET /merchants(.:format) merchants#index
POST /merchants(.:format) merchants#create
new_merchants GET /merchants/new(.:format) merchants#new
edit_merchants GET /merchants/:your_field/edit(.:format) merchants#edit
Merchant.find_by(your_field: params[:your_field])
You can find the documentation here

Related

Error using alias for routes in Ruby on Rails

I have a route with a namespace
namespace :publishers do
resources :authors
get 'books' :to => 'books'
get 'books/custom_report/:id', :to => "curriculos#custom_report"
end
Often I will have to make links in my application and I know than it`s possible to use a alias for routing like this:
<%= link_to "Books", publishers_books_path %>
I call that publishers_books_path a alias route, does this is the correct name?
Furthermore, I still not able to understand the logic with this alias naming because i can`t use for a new or a custom action like this
link_to 'Show the report', publishers_books_custom_report_path(params[:id])
I'm always get a error of undefined_method for publishers_books_custom_report_path
So there`s some questions
First of all whats it`s the correct name of this feature in RoR?
How I can use the custom_report as aliases to link_to? And also if i need to use some basic operations like new, update, insert?
Can someone give me the link to the documentation to really understant that feature?
First of all whats it`s the correct name of this feature in RoR?
The docs use "path helper" and "named route helpers" interchangeably.
How I can use the custom_report as aliases to link_to?
Use rails route or visit /rails/info/routes in your dev server to get a list of all your routes, their helpers, and controller actions.
Apparently it is publishers_path which doesn't seem right. You can fix this with an as.
get 'books/custom_report/:id', to: "curriculos#custom_report", as: :books_custom_report
And also if i need to use some basic operations like new, update,
insert?
A get declares just that one specific route. If you need all the operations on a model, declare it as a resource.
namespace :publishers do
resource :authors
resource :books
get 'books/custom_report/:id', to: "curriculos#custom_report", as: :books_custom_report
end
Can someone give me the link to the documentation to really understand that feature?
Rails Routing From The Outside In.

Can I have several New methods in a rails controller on Rails 5.2?

My application has several ways to create notifications:
A user can create a notification using the standard "new" method
A link in a view can create a notification from an action using a dedicated "new_action"
etc.
So I created additional route and views for the new_action_notification_path:
resources :notifications do
member do
get :new_action
end
collection do
get :index_all
end
end
In the controller
# GET /notifications/new_action
def new_action
#playground = Playground.find(current_playground)
#notification = #playground.notifications.build( playground_id: params[:playground_id], …
And in the view:
<%= link_to t('Reject'), new_action_notification_path(
playground_id: current_playground,
description: t("#{this_object.class.name}#{'Rejected'}"),
But this does not behave as expected:
If I write new_action_notification_path in the view, as above, the generated URL looks like /notification/729/new_action?code=QWSTZ ...
If I write new_notification_path in the same place, the generated URL looks like /notification/new?code=QWSTZ ...
Why is it different, and how can I remove the notification id from the first URL?
Thanks a lot!
The reason your url's are different is because you have a nested route for the new_action.
resources :notifications do
member do
get :new_action
end
end
With a nested route, you are going to get an id number between your resources. The 729 is the id you are passing in to the link_to helper. The other route helper, new_notification_path, is creating a new notification, so it doesn't need an id. If you look at your routes, with rails routes in your console or localhost:3000/rails/info/routes in your browser, you'll see that the new_action needs an id.
new_action_notification_path GET /notifications/:id/new_action
new_notification_path GET /notifications
The :id part of the route is a placeholder for an id number (although it can be anything you pass in, really) to look up the resource before it. In this case, the id is use to look up the notification.

How do I get the format of my URLs to be username/controller/:id in Rails 3.1?

I want it similar to the way Twitter handles the URLs for its tweets.
For instance, right now my URL looks like this: mydomain.com/feedbacks/1/, where feedbacks is the name of the controller.
I want it to look like: mydomain.com/username/feedbacks/1/ which is similar to Twitter's: twitter.com/username/status/:id/.
My routes.rb looks like this:
resources :users do
resources :feedbacks
end
When I have it like this, it gives me the URLs as mydomain.com/users/1/feedbacks, but I want the actual username in the URL.
How do I get that?
Thanks.
Edit 1: If you are adding another answer to this question, please make sure it addresses my comments/questions to the answer already given. Otherwise it will be redundant.
scope ":username" do
resources :feedbacks
end
From the docs:
This will provide you with URLs such as /bob/posts/1 and will allow
you to reference the username part of the path as params[:username] in
controllers, helpers and views.
UPDATE:
I have tested and confirmed the accuracy of paozac's answer. I'll clarify it a bit.
Suppose you had a #feedback object with an id of 12, and the associated user had a username of foouser. If you wanted to generate a URL to the edit page for that #feedback object, you could do the following:
edit_feedback_url(:username => #feedback.user.username, :id => #feedback)
The output would be "/foouser/feedbacks/12/edit".
# A URL to the show action could be generated like so:
feedback_url(:username => feedback.user.username, :id => feedback)
#=> "/foouser/feedbacks/12"
# New
new_feedback_url(:username => current_user.username)
#=> "/foouser/feedbacks/new"
Additionally, as noted by nathanvda in the comments, you can pass ordered arguments which will be matched with the corresponding dynamic segment. In this case, the username must be passed first, and the feedback id should be passed second, i.e.:
edit_feedback_url(#feedback.user.username, #feedback)
Also, if you need help handling the params from the controller, I suggest creating a new question specific to that.
Once you have defined the scope like dwhalen says you can generate the url like this:
feedbacks_url(:username => 'foo')
and get
http://www.example.com/foo/feedbacks
or
edit_feedback_url(:username => 'foo', :id => 1)
and get
http://www.example.com/foo/feedbacks/1/edit

What is the best way to deal with Vanity URL helpers in Rails 3?

I have a web application I am working on with Rails 3 and I have just implemented some basic Vanity URL paths to existing resources in the application. What I am looking to do is to not have to explictly build the urls on the user's profile page for the resources that are available, e.g. I would like to be able to build a URL with link_to in the view in the format of:
typealoud.com/:user_id/:thread_id/:comment_id
And not what the standard nested resource helpers give me, something like:
typealoud.com/threads/:thread_id/comments/:comment_id
Should I do this myself as a URL helper, or is there an existing gem?
To do this, I would put this at the top of my routes:
match ':user_id/:thread_id/:id', :to => "comments#show"
I've changed comment_id in this example to id because it's "The Rails Way" that the last id parameter is simply called id. It also results in shorter code.
If you wish to have a routing helper for it use the :as option:
match ':user_id/:thread_id/:id', :to => "comments#show", :as => "comment"
Then you can use comment_path/comment_urlto access the route, but you must pass in three arguments to it, each of them being an object or an id of an object.

renaming routes (map, link_to, to_param) in rails

I'm having a little issue...I setup a rails application that is to serve a german website. To make use of Rails' internal pluralization features, I kept all my models in english (e.g. the model "JobDescription").
Now, if I call "http://mysite.com/job_descriptions/", I get all my job_descriptions....so far, so good. Because I didn't want the english term "job_descriptions" in my url, I put the following into my routes.rb
map.german_term '/german_term', :controller => 'job_descriptions', :action => 'index'
map.german_term '/german_term/:id', :controller => 'job_descriptions', :action => 'show'
If I call "http://mysite.com/german_term/" or "http://mysite.com/german_term/283" I get all my job_descriptions, which is fine.
However, to make the URL more SEO friendly, I'd like to exchange the id for a more userfriendly slug in the URL. Thus, I put the following in my job_description.rb:
def to_param
"#{id}-#{name.gsub(/[^a-z0-9]+/i, '-')}"
end
which, whenever I use "job_description_path" in any link_to method, renders my URLs out to something like "http://mysite/job_descriptions/13-my-job-description-title".
However, and this is where I'm stuck, I'd like to get "http://mysite/german_term/13-my-job-description-title". I already tried to exchange the "job_description_path" with "german_term_path" in the link_to code, but that only generates "http://mysite/german_term/13". Obviously, to_param isn't called.
One workaround I found is to build the link with:
<%= link_to job_description.name, german_term_path(job_description.to_param) %>
But that's rather tedious to change all the link_to calls in my code. What I want is to replace "job_description" by "german_term" whenever it occurs in a URL.
Any thoughts?!?
Regards,
Sebastian
I think you're going to need to use the restful route helpers to get what you want.
In that case, it wouldn't take much re-factoring (assuming you've mapped JobDescriptions as a resource). Leave your to_param as is and change your JobDescriptions route to something like the following:
map.resources :job_descriptions, :as => 'german_term'
Hope this helps!
Rails only utilizes the
def to_params
end
URL builder when you are using a restful route/link helper. The only way I am aware of is to do it similar to how you did, unless you are willing to just scrap your english language links and do it all in German. In that case, just get rid of the named route lines and change the to_params to use the correct name field from the database. At that point, the REST routes should behave correctly.

Resources