rails using link_to with namespaced routes - ruby-on-rails

I've created a set of routes & controllers with the admin namespace, and I was having some issues using the link helpers with these new routes.
I see that there are some new path helpers, such as admin_projects_path which leads to the /admin/projects. however, i'm having trouble linking to the show, edit, destroy, etc. paths for these objects within the namespace. how do I do that?

If you're using Rails 3, you can use your admin namespace with the variable instead of writing the long helper path name.
view:
<td><%= link_to 'Show', [:admin, project] %></td>
<td><%= link_to 'Edit', [:edit, :admin, project] %></td>
<td><%= link_to 'Destroy', [:admin, project], confirm: 'Are you sure?', method: :delete %></td>
controller:
redirect_to [:admin, #project]

You should see all of your routes listed in rake routes and you can use those by name to get the proper namespacing. Using the automatic detection where you pass in :controller and :action manually won't work as you've discovered.
If it's listed as new_thing in the routes, then the method is new_thing_path with the appropriate parameters. For instance:
link_to('New Project', new_admin_project_path)
link_to('Projects', admin_projects_path)
link_to(#project.name, admin_project_path(#project))
link_to(#project.name, edit_admin_project_path(#project))
link_to(#project.name, admin_project_path(#project), :method => :delete)

Some methods require a :url option as a parameter, and in those cases you can use url_for to generate the path:
icon(:url => url_for(:controller => "admin/projects", :action => "edit", :id => #project),
:type => :edit)

Related

Rails no action "edit" in forum_posts_controller

The forum_posts controller is located in app/controllers/forum_threads/forum_posts_controller.rb
I don't know if I have to call forum_threads:forum_posts in the link_to.
Controller:
http://pastebin.com/t9vuyxdP
HTML:
http://pastebin.com/LextuZ74
On a side note, how do you add a button to the link_to? I've tried adding :class => "button" at the end, doesn't cause an error but still just shows a link not a button.
If you want to use link_to with older-style controller/action/id arguments:
<%= link_to "Edit", :controller => "forum_threads/forum_posts", :action => "edit", :id => forum_post.id, :forum_thread_id => #forum_thread.id %>
But Rails prefer newer RESTful routes whenever possible. If you define your controller correctly in routes.rb, you can write link_to like this:
<%= link_to "Edit", edit_forum_thread_forum_post_path(#forum_thread, forum_post) %>
UPDATE 18/11/2015: You forgot to include forum_thread_id in link_to as I saw your route require forum_thread_id and id param to make it work.
For more information on link_to, refer to: http://apidock.com/rails/ActionView/Helpers/UrlHelper/link_to

Passing a delete method with params

<% #books.each do |book| %>
<% unless book.checkout_user_id == nil %>
<%= link_to "delete checkout", book_checkout_path(book_id: book.id), :confirm => 'Are you sure?', :class => "button", :method => :delete %>
<% end %>
<% end %>
In the above code, I want to pass a parameter to my book_checkout controller. How can I make it so my destroy method will retrieve the :book_id passed in from book_checkout_path.
Then create an instance to search for a checkout with the corresponding book_id attribute rather than search by ID.
def destroy
#book_checkout = BookCheckout.where(book_id: book_id).first # this line is wrong
#book_checkout.destroy
redirect_to books_path
end
EDIT: Added routes.
routes:
book_checkout GET /book_checkouts/:id(.:format) book_checkouts#show
PATCH /book_checkouts/:id(.:format) book_checkouts#update
PUT /book_checkouts/:id(.:format) book_checkouts#update
DELETE /book_checkouts/:id(.:format) book_checkouts#destroy
I had to fix my original code for a workaround, but it isn't the cleanest.
<%= link_to "delete checkout", book_checkout_path(id: book.id, check: book.id), :confirm => 'Are you sure?', :class => "button", :method => :delete %>
My original link_to NEEDS to pass id because my routes expect that, so I added a check which passes the attribute i will need.
#book_checkout = BookCheckout.find_by(book_id: params[:check])
In my checkout controller, I used the params[:check] instead of params[:id], because I cannot overwrite params[:id] with the book.id.
#book_checkout = BookCheckout.find_by(book_id: params[:book_id])
Since the route only has one id, I think you can use
book_checkout_path(book.id)
However, it seems strange to use the Book id to find the BookCheckout. Is there any special reason you can't do:
book_checkout_path(book_checkout.id)
and
#book_checkout = BookCheckout.find_by(id: params[:id])
Also, is it possible that both the Book id and the Book Checkout id are the same (1)? This would make it appear to succeed when it shouldn't.

routes when trying to make a link_to look like a button

I had my link for editing brands like this:
<%= link_to 'Edit', :action => 'edit', :id => brand %>
I found around here a way to make it look like a button, so I did this (not sure why the url helper method needs to be used, but with :action => 'edit' it didn't work, it kept thinking it was post action):
<%= button_to 'Edit', admin_brand_edit_path(brand), :method => "get" %>
However, the generated url is like this:
http://localhost:3000/admin/brand/edit.1
Where it should be
http://localhost:3000/admin/brand/edit/1
Result of rake routes for brand edit:
admin_brand_edit GET /admin/brand/edit(.:format) admin/brand#edit
admin_brand_update POST /admin/brand/update(.:format) admin/brand#update
routes.rb
get 'admin/brand/edit'

Share a partial among different resources

I have the following bit of code in my views:
- if admin?
.meta
Administrator options:
= link_to 'Edit This Post', edit_post_path(#post)
|
= link_to 'Delete This Post', #post, :method => 'delete', :confirm => 'Are you sure?'
I find that I use this same basic snippet a lot, but sometimes with different resources, and sometimes with more than one resource on a page. I'd like to extract this into a partial to DRY it up, but I need to write is so it could work with local or instance variables for any model. For instance, I need it to work with:
#post, post, #page, page
How do you do that?
You can cleanly write your partial to be independent of the given object:
- if admin?
.meta
Administrator options:
= link_to 'Edit', [:edit, object]
|
= link_to 'Delete', object, :method => 'delete', :confirm => 'Are you sure?'
And then you could do something like
render :partial => 'shared/admin_link', :locals => { :object => #post }
You can commit a variable to a partial using the :object or the :collection options in the render method. The :object option passes a single object to the partial that can contain anything. The :collection option is used to pass an Array of Objects that must be from the same Class.
For example you have your #post and pass it to the partial like this
<%= render :partial => 'layouts/my_partial', :object => #post, :as => :my_local_var %>
Then you can access the object by calling my_local_var in the partial. Using :collection is slightly different but you can read it on your own here: http://guides.rubyonrails.org/layouts_and_rendering.html
A Problem will be the usage of one partial in different Classes because of the routes names. Then you cant use the edit_modelname_path(#instance_var) you must use the routes Hash { :controller => params[:controller], :action => 'edit' } in the link_to method!
// For Link creation wihout params[:controller] :
Its just an Idea I didnt do this before but you can try this for example:
You render the partial and use :object => #instancevar, :as => :my_local_var you can use the following line for dynamic link creation:
<%= link_to "link text", { :controller => my_local_var.class.to_s.pluralize.downcase, :action => 'edit', :id => my_local_var.id } %>
Then you dont depend on the params[:controller] but are able to link to the vars edit link.

ROR ways of calling destroy action

I ask this question only because I'm curious.
The first line is standard, RESTful and of course invokes destroy method.
The second line returns a routing error.
The question is how to repair the second line to work like the first one. As I mentioned before, It's just for my curiosity and better ROR understanding.
<%= link_to 'delete', file, :method => :delete %></td>
<%= link_to 'delete', {:action => :destroy, :controller => 'files', :id => file.id.to_s}, :method => :delete %>
Bye
Disclaimer: I know this is not the way to do a delete. It is proof of concept on just how to access an action via a controller outside of REST.
You can do this:
<%= link_to 'delete', {:action => :destroy, :controller => 'files', :id => file.id} %>
You don't need the method destroy if you explicitly access the action. Also don't need the to_s for the file.id

Resources