Share a partial among different resources - ruby-on-rails

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.

Related

render partial on click

I would like to call partials on some standard operations. I am using this method for calling the partial:
%li= link_to 'Delete Event', 'javascript:void(0);', :class => 'alert tiny button', :data => {'reveal-id' => :RevealDelete}
= render 'layouts/reveal_delete', :item => event_display(#event.event), :resource => #event
Then in my partial,
#RevealDelete.reveal-modal
%a.close-reveal-modal ×
%h3= "Delete #{item}"
%p Are you sure you want to delete this?
=link_to "Delete #{item}", resource, :method => :delete, :remote => :true, :confirm => resource, :class => 'button close-reveal-modal'
%a.button.alert.close-reveal-modal Cancel
How can I have this has as something like:
link_to 'Delete', '#', :partial => 'layouts/delete', :remote => :true?
so that I only render that partial when clicked and not when the page loads?
You can do that with javascript like:
<%= link_to "Delete", delete_content_path, :remote => true %>
The action in your corresponding controller then will be this:
My Controller:
def delete_content
respond_to do |format|
format.js
end
end
Then you can create the delete_content.js.erb inside your correct directory of the link and there you put the following code:
delete_content.js.erb
$('#div_id').html("<%= render :partial => 'my_partial' %>");
Then in your view:
delete_content.html.erb
<div id = "div_id">
#this div is html div that will render your partial
</div>
Don't forget to put your partial _my_partial.html.erb in the same folder.
To add to the accepted answer, I only got it to work after changing the js portion to the following:
$('#div_id').html("<%= escape_javascript(render :partial => 'my_partial') %>");
Without the escape_javascript it was just rendering the partial in the background and not updating the view.
on the view do this:
link_to "Delete #{item}", '/model/confirm_deletion', :method => :delete, :remote => true #add the class and extra attributes if neeeded
on your controller
def confirm_deletion
end
and add a view to the confirm_deletion action in js
#RevealDelete.reveal-modal
%a.close-reveal-modal ×
%h3= "Delete #{item}"
%p Are you sure you want to delete this?
=link_to "Delete #{item}", resource, :method => :delete, :remote => :true, :confirm => resource, :class => 'button close-reveal-modal'
%a.button.alert.close-reveal-modal Cancel
:javascript
$(body).append($('#RevealDelete'));
that would make an ajax request to load that custom confirmation dialog, maybe you want to add some wrapper to insert the dialog instead of using body.append

Deleting from a namespace

I have setup a admin namespace in order to access models in the admin area: /admin/pages
However i have the following problem
i cant get the delete function to work under Admin::PageController for example or any of my models.
Does anyone know how to do this.
I have the following:
Admin::PageController I have the following
def destroy
#page = Page.find(params[:id])
#page.destroy
respond_to do |format|
format.html { redirect_to admin_pages_url }
format.json { head :ok }
end
end
Then on my page index file where i want a link to delete the record i have the following: (/admin/pages)
<%=link_to admin_page_path(page), :class => 'ico del' do %>
<%='Delete'%>
<% end %>
Does not seem to work. Anyone know how to get this to work?
you have missed :method option in link_to call
link_to 'Delete', admin_page_path, :confirm => 'Are you sure?', :method => :delete
or
<%=link_to admin_page_path(page), :class => 'ico del',:method => :delete do %>
<%='Delete'%>
<% end %>
The link_to helper defaults to a GET request unless you specify additional attributes to tell it how you want it to be handled.
In this case, you need to set some extra arguments:
<%=link_to "Delete", admin_page_path(page), :class => "ico del", :remote => true, :method => :delete %>
What actually happens in the background is the Rails UJS (unobtrusive javascript adapter) captures the click event and sends the request via AJAX. So you should see it hit your server with a POST (but it passes in _method => delete as well) to delete the object.
I'm also assuming you have your routes set up correctly. Something like:
namespace :admin do
resources :pages
end

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

How do properly delete this?

Something is seriously not adding up here.. My page just refreshes, nothing happens, it never touches any of my debuggers hanging out on all my methods except for index.
my html:
<%- for image in #images %>
<%= image.attachment_file_name %>
<%-# link_to_delete image, :url => destroy_image_admin_wysiwyg_path(image.id) %>
<%= link_to 'delete', { :url => destroy_image_image_path(image.id) },
#:confirm => 'Are you sure?',
:post => true
%>
<br />
<% end %>
my controller
def destroy_image
debugger
#img = Image.find(params[:id])
#img.destroy
respond_to do |format|
format.html { redirect_to admin_image_rotator_path }
end
end
My routes:
map.resources :images, :member => { :destroy_image => :post }
My disgusting hack that works that I will replace as soon as I find something better
I moved the action over to a simpler controller I built myself.
Changed my routes to :
admin.resources :wysiwygs, :member => { :destroy_image => :post }
Changed my html :
<%= link_to 'delete', :controller => "wysiwygs", :action => "destroy_image" %>
But when I clicked on the link..it brought up.. the show action ?? fffffffffuuuuuuu
I retaliated by just moving my action to the show action, and passing a hidden field in my html..
<%= link_to 'delete', :controller => "wysiwygs", :action => "destroy_image", :hidden_field => {:value => image.id} %>
def show
# this was previously in destroy_image
#img = Image.find(params[:hidden_field][:value])
#img.destroy
respond_to do |format|
format.html { redirect_to admin_image_rotator_path }
end
end
It seems you're going down the wrong path here. If a before_filter is blocking your action, figure out why. Use skip_before_filter :filter_name if the filter is not needed.
Don't use show actions or HTTP GET for deletes. Even if it works, it will confuse things down the road. Use a DELETE verb:
map.resources :images, :member => { :destroy_image => :delete }
pass it in the link helper:
<%= link_to "delete", destroy_image_image_path(image), :method => :delete %>
And use ImagesController#destroy_image to perform the action. Better yet, consider using the standard RESTful ImagesController#destroy which map.resources gives you for free.
Not sure what was wrong in the first place, but in your second, working solution, i think you should write your link_to as follows:
link_to 'delete', :controller => "wysiwygs", :action => "destroy_image", :id => image.id
That at least would send you to the correct action.
Depending on your routes, you will have to make this a method => :post or not.
Check your rake routes output, it will show you what are the possible routes, and also what names they got, which in turn you can use as a method (add _path or _url at the end). Then it should be even easier to write something like:
link_to 'delete', wysiwygs_destroy_image_path(image)
Good luck!
You're doing a POST but your resource says that :destroy_image is only available via GET. Try changing your route to:
map.resources :images, :member => { :destroy_image => :post }
Also, take a look at your link_to. The second parameter takes a URL, not a hash that has a :url key. As mentioned elsewhere, depending on your Rails version you may need :method => :post instead of :post => true. In Rails 2.3.8, you would want this line instead:
<%= link_to 'delete', destroy_image_image_path(image), :method => :post %>

Button_to uses POST Link_to uses GET, why? ROR

I've ran into a ror problem using the link_to. Why does my link to use the GET method and my button_to use the POST method, after I specified my "method"=>"post" within the link_to parameters?
View:
<%= button_to "pdf", :action => 'getquote' %>
<%= link_to 'pdf', {:controller => 'inventories', :action => 'getquote', :method => :post } %>
Controller Method:
def getquote
#cart = find_cart
respond_to do |format|
format.pdf
end
end
Terminal Output (Button/Link, respectively):
Processing InventoriesController#getquote (for 127.0.0.1 at 2010-01-30 01:38:02) [POST]
Parameters: {"action"=>"getquote", "authenticity_token"=>"D2cwnHyTHgomdUM3wXBBXlOe4NQLmv1Srn0paLbExpQ=", "controller"=>"inventories"}
Processing InventoriesController#show (for 127.0.0.1 at 2010-01-30 01:39:07) [GET]
Parameters: {"method"=>"post", "action"=>"show", "id"=>"getquote", "controller"=>"inventories"}
I think your html options have to be in a separate hash from your url options:
<%= link_to 'pdf', {:controller => 'inventories', :action => 'getquote'}, {:method => :post } %>
I looked all over for a proper example, with no luck. For my code, I've mostly given up and just use the new style:
<%= link_to 'Delete', custom_event, :confirm => 'Are you sure?', :method => :delete %>
Might be useful for someone who is visiting :)
By default, button_to performs POST action only.
to do make a GET the syntax is as follows:
<%= button_to 'pdf', { :action => 'getquote'}, :method => :get %>
One possibility is that you have Javascript disabled, in which case it will fall back to a GET.

Resources