Open a record using token - ruby-on-rails

I'm building a RoR app where each record has a unique, 7 character token (hex). I would like to create link on a page where a user can provide that token and be brought to the edit path for that record. I've scoured the WWW and can't seem to find a clean method to accomplish this task.
Any ideas?
I realize I run a slight risk of duplication, but this will be a novelty app more than anything.

Vanity URLs in Rails
For if you want to be able to navigate to /model/5na09zn instead of /model/{id}:
1. config/routes.rb
resources :model
--- becomes --->
resources :model, :except => ['show', 'update', 'destroy']
get 'posts/:hex_token' => 'model#show', :as => 'model'
put 'posts/:hex_token' => 'model#update'
delete 'posts/:hex_token' => 'model#destroy'
2. app/controllers/model.rb
Do this for all show, update and destroy:
(Better yet, write a controller function to handle this automatically!)
def show
#model = Model.find(params[:id])
...
end
--- becomes --->
def show
#model = Model.find_by_hex_token(params[:model])
...
end

Related

Using Rails 2.3.8 I am trying to create a new view for a child object

So I have a pretty basic issue I guess. I'm using Ruby 1.8.7 and Rail 2.3.8 b/c the web host is pretty out of date. Anyways, I have an Event which has RSVPs associated with it. I have an administrator that I want to have access to a better view (more information_ of the RSVPs for the event.
The RSVP currently indexes like normal /events/1/rsvps which I get to using event_rsvps_path(event) and use an index.html.erb file. I made a adminindex.html.erb and put an adminindex in the rsvp controller. But now I don't know how to create a link to that adminindex.html.erb file.
The usual methods like link_to :controller=>'rsvps', :action=>'adminindex' don't work for obvious reasons to me.
The Routes file has map.resources :rsvps, :except => :update
Can someone tell me how to link the index to the adminindex file if the admin is signed in?
The problem is in your routes.rb file. Creating a resource only makes routes for the 7 RESTful actions (index, show, new, create, edit, update, destroy)
Since you have a custom action, you have to add a custom route for it. Try this:
map.resources :rsvps, :except => :update, :collection => { :adminindex => :get }
Run rake routes to see if it made the route correctly.

Rails routing URL folders for product categories on show actions

I'm trying to formulate some better urls for a "product" model I have, only on the show action. I'm currently using friend_id to generate pretty slugs, which is fine, but I'm trying to improve the URL flow if I can.
Current my paths work like this
example.com/products/pretty-url-slug
When saving a parictular product (to the Product Model), I also save a type_of attribute. Which could be android, iphone, windows
So I am trying to ultimately have robust URLS like this
example.com/products/iphone/pretty-url-slug
The problem is, that I don't have or believe I want an actual "iphone", "android", etc controller. But I'd rather just update a combination of the routes and show action to handle this properly.
So far I've attempted to solve this by using a catch all on the routes, but is not working correctly. Any suggestions or different ways to handle this elegantly?
routes
resources :products
# at the bottom of my routes a catch all
match '*products' => 'products#show'
# match routes for later time to do something with to act like a
# normal category page.
match 'products/iphone' => 'products#iphone_index'
match 'products/android' => 'products#android_index'
match 'products/windows' => 'products#windows_index'
show action in the products controller
def show
# try to locate the product
if params[:product].present?
slug_to_lookup = params[:product].split("/").last
type_of = params[:product].split("/").second
#product = Product.find_by_slug(slug_to_lookup)
else
#product = Product.find_by_slug(params[:id])
end
# redirect if url is not the slug value
if #product.blank?
redirect_to dashboard_path
elsif request.path != product_path(#product)
redirect_to product_path(#product)
end
end
This way to handle the problem sort of works, but I can't fiqure out how to append the type_of attribute and generate a valid URL.
What about defining your routes like this:
get ':controller/:action/:id/:user_id'
Here, Anything other than :controller or :action will be available to the action as part of params.
Thanks for the suggestion. I was actually able to solve this and pretty simple when I thought it over. This might be helpful for others.
In my routes I just created a route for every type of category I have. so every time a new category, I would need to add an additional route, example:
# match for each product category
match 'shop/iphone/:slug' => 'products#show', :as => :product_iphone
match 'shop/android/:slug' => 'products#show', :as => :product_android
match 'shop/windows/:slug' => 'products#show', :as => :product_windows
Then in the show action for products instead of directing, you would just render the products/show if the slug matches an existing product
#product = Product.find_by_slug(params[:slug])
Then in your views, you could link to a particular category like this
link_to "product", product_android_path(#product)

Rails always routes an action to show action, and the action it self becomes the id

There's a strange behavior in rails I found recently related to routes and actions, specifically, it's on rails 2.3.5. I have a controller, let's call it Users. In the routes, I declare Users as a resources.
map.resources :users
And within the controller, I have the standard action: index, show, edit, update & destroy. Also, I added other action to fullfil certain requirements.
def generated_pdf_report
# do something
end
The problem is, when I go to page /users/generated_pdf_report, I get this on the console:
Processing UsersController#show (some timestamps) [GET]
Parameters: {"action"=>"show", "id"=>"generated_pdf_report", "controller"=>"users"}
As you can see, the server route the request to method show rather than to method generated_pdf_report. What's interesting, is that I have other controllers having similar action and is working fine.
The solution to the above problem is easy enough, make sure the added feed is above the resources:
map.feed 'users/generated_pdf_report', :controller => 'users', :action => 'generated_pdf_report'
map.resources :users
My question is: Anyone knows why rails behaves like that? The above solution is kind of sloppy, what do you think the best practices for such problem like one mentioned above.
As outlined in the Rails 2 routing guide, you can add collection routes like so:
map.resources :users, :collection => { :generated_pdf_report => :get }
When rails looks at
/users/generate_report
That is exactly the path it would use to show a user whose id was generate_report, so that is what it does, assuming you haven't told it otherwise.
A shorter alternative to what you wrote is
resources :users, :collection => {:generate_report => :get}
Which tells rails to map a GET to /users/generate_report to your generate_report action

Why Rails process link_to with :action=>methodname as ID=>methodname

I'm trying to make a link in Rails (2.1) that:
Only appears for admin users
When clicked, executes a method in the controller,
The method executes a small shell script (e.g. a short sql query which outputs a text file),
Prompts the user to download the output text file,
Everything is done on the same page without redirecting to another page (ideally)
I tried these solutions to run a shell script from Ruby: (1), (2). In my reports_controller.rb:
def runreport
#system('sh hello.sh')
puts `whoami` # << this is just to test shell script calling
end
And in my view/report/index.html.erb:
<% if is_logged_in? && logged_in_user.has_role?('Administrator') -%>
<p><span class="encapsulated"><%= link_to "Download File", { :action => 'runreport' } %></span></p>
<% end -%>
(The <span class="encapsulated"> just puts the link in a nice button form). However, when I clicked the link, it returns an error:
ActiveRecord::RecordNotFound in ReportsController#show
Couldn't find Report with ID=runreport
...
app/controllers/reports_controller.rb:100:in `show'
With Parameters:
{"id"=>"runreport"}
It looks like when the link is pointed to itself (reports), the default method to execute is "show". But wasn't it specifically told to do action => 'runreport'? I've scratched my head and looked for answers for a few hours and couldn't figure it out :( Thus, my questions are:
What am I doing wrong?
Why is it looking for the id=>"runreport"?
How to fix the error? and if it's possible to tell it to not do redirection
And what's the ideal way to deliver the file to the user after the script is done?
Thank you in advance for any help/feedback!
Cheers!
EDIT: This is how the routes.rb on reports look like:
map.resources :reports,
:member => { :claim => :put, :close => :put, :open => :put, :baz => :post },
:collection => {:search => :get} do |report|
report.resources :blah, :foo => { :bar => :post }
end
This is on Rails 2.1, so I assume it's different from 3.x
Generally the issue is with the routes.
If you define restful routes as in
map.resources :reports
or in case of rails 3 and above
resources :reports
Its assumed that /reports/:id is the show action. So when you go to "/reports/runreport" it goes to the show action and tries to find an Report object with the Id "runreport".
Read this http://guides.rubyonrails.org/routing.html#resources-on-the-web
You may want to define collection route on reports to make this work. Read this http://guides.rubyonrails.org/routing.html#adding-more-restful-actions
I have not figured out entirely why the controller always defaults to the show method, but I've found a workaround. I just make it call my runreport method when the link is clicked (which will reload the same page), before it calls the show method.
I'm guessing, since the page is always calling the show method, which is a "member" method, it will always look for some id.
Thanks for all your help!

Help with rails routes

Im having a little trouble setting up routes.
I have a 'users' controller/model/views set up restfully
so users is set up to be a resource in my routes.
I want to change that to be 'usuarios' instead cause the app will be made for spanish speaking region... the reason the user model is in english is cause I was following the authlogic set up and wasnt sure if naming the model usuario instead would create trouble.. so basically this is what I have in mr routes.rb to get this functionality done.
map.resources :usuarios,:controller=>"users", :path_names => {:edit => 'editar' }
the problem is that when I try to register a new user I get this error
ActionController::MethodNotAllowed
Only get, put, and delete requests are allowed.
this happens after I have filled out my register form and clicked on submit...
Have you tried using the 'as' option to change how the url looks without modifying the routes?
This example is from the documentation:
# products_path == '/productos'
map.resources :products, :as => 'productos' do |product|
# product_reviews_path(product) == '/productos/1234/comentarios'
product.resources :product_reviews, :as => 'comentarios'
end
You can try rake routes | grep usuarios from a terminal window (cd to the project root first) to make sure that the proper named routes are setup properly. You can cross reference that with the form tag you are using to make sure that the action for the form is correct.

Resources