How to setup a rails 3 route for a nested resource and custom controller action - ajax

I have a recommendation that is nested below Categories and Awards.
So Category/:id/awards/:id/recommendations/:id
I have an Assets model that handles paperclip attachments to the Recommendation. A Recommendation has_many Assets, Assets belong_to :recommendation
In my Recommendation new/edit views I am rendering a form partial (as is normal) that gives the user the option to upload several assets.
If there are Assets already related, then it lists them. I am working on setting up a custom delete action on the recommendations controller.
My current link_to:
<%= link_to "Delete Attachment",
{:controller => :recommendations, :action => :destroy_asset, :id => asset.id },
{:remote => "true", :confirm => "Are you sure you want to delete this image?"}
%>
My Controller action:
def destroy_asset
##recommendation = Recommendation.find(params[:id])
#asset = Asset.find(params[:id])
#asset.destroy
respond_to do |format|
format.js
end
end
routes:
resources :recommendations
resources :categories do
resources :awards do
resources :recommendations
end
end
I am still learning remote => true, and how to route this sucker. Not sure if I need to have the route nested or not. I tend to think not. Since I have an Asset.id in my loop, I should just be able to execute the destroy without needing the Recommendation at all.
So the question/s: do I need a route to access a custom action in my recommendations_controller?
thanks

Try this:
resources :categories do
resources :awards do
resources :recommendations
member do
get :destroy_asset
end
end
end
end
Or If you only want only destroy_asset action under recommendation controller, do something like this :
resources :recommendations
member do
get :destroy_asset
end
end
Or If you want custom match, do something like this :
match "asset/:id/destroy_asset", :to => "recommendations#destroy_asset",
:as=> "destroy_asset"

Related

How can I create a new layout and have it show up only in certain situations using ruby padrino?

I'm using padrino with my website, and need to override the default layout to use a different layout in certain situations i.e. when a user clicks on a certain thing.
Padrino documentation gives these examples:
SimpleApp.controllers :posts do
# Apply a layout for routes in this controller
# Layout file would be in 'app/views/layouts/posts.haml'
layout :posts
get("/posts") { render :haml, "Uses posts layout" }
end
SimpleApp.controllers :admin do
get :index do
render "admin/index", :layout => :admin
end
get :show, :with => :id do
render "admin/show", :layout => false
end
end

Rails remote delete and update view through Ajax

In the past, whenever I wanted to update a part of my view through Ajax, I've done the following:
create a partial out of the part I want to update and give it a unique ID, say #tracks
create a special action in the controller for that Ajax call, say remove_track that updates all the values, etc. and add format.js
create a new JS file with the same name as the action so Rails calls it automatically remove_track.js.erb which contains something like: $('#tracks').html("<%=j render 'cds/show_tracks' %>");
set remote: true in the link that calls this action.
All this is fine, but now I am trying to delete and update a common index view using the regular destroy method for flexibility, meaning I can call this method either through Ajax or normally. I figured it's such a common thing to do that there has to be a better way than all of the above.
I can get the destroy method to call my destroy.js.erb file by simply putting this into the controller:
format.js { layout: false }
and of course setting remote: true on the link.
what I cannot do is get the view to refresh. The table I want to refresh is encased in a div with a unique ID, but since it's not a partial, it refuses to refresh the content. Maybe I'm missing something.
Am I doomed to have to create a partial and refresh it with the method above or is there a more magical way of doing it (other than using Turbolinks)?
Thanks.
PS
Also, I just noticed this has the added disadvantage that I cannot pass the rest of the params to the destroy method since it only passes the object ID to destroy using the regular CRUD routes. If I try to use platform(action: destroy) or platform(method: delete) I get an error:
No route matches {:action=>"destroy", :controller=>"platforms"}
Which means I have to create a new route if I want to pass those parameters...
Yet another disadvantage to all this is that I'm repeading all the logic for searches and sorting that I have in the index method again in the destroy method. I am certain this is definitely not the way to do it.
Thanks to this page I found the proper way to do it. So simple and effective.
http://carmennorahgraydean.blogspot.com.es/2012/10/rails-328-ajax-super-basic-example.html
Update your destroy line in index.html.erb:
<%= link_to 'Destroy', pony, method: :delete, data: { confirm:
'Are you sure?' }, :remote => true, :class => 'delete_pony' %>
Create a file, destroy.js.erb, put it next to your other .erb files
(under app/views/ponies). It should look like this:
$('.delete_pony').bind('ajax:success', function() {
$(this).closest('tr').fadeOut();
});
Add format.js { render :layout => false } to your controller:
respond_to do |format|
format.html { redirect_to ponies_url }
format.json { head :no_content }
format.js { render :layout => false }
end
Hope this helps someone else.

Updating (Hiding) a group of objects in Rails 3

I've some difficulty in determining any way to update my objects as a group. I have an Alert model which has some alerts for the user. I'd like to provide a way to update them in bulk, as I've noticed that I often want to. I just don't know Rails well enough to know what 'the Rails way' would be.
My controller:
class AlertsController < ApplicationController
def index
#alerts = Alert.all(show: true)
end
def destroy
alert = Alert.get(params[:id])
## I lied, I'm not really deleting things, just hiding them from showing
alert.update(show: false) if alert
respond_to do |format|
format.js { render :nothing => true }
end
end
I've been using this code in my *.html.haml view to create the delete link for each individual alert:
- #alerts.each do |alert|
%span{ :class => 'description' }=alert.description
= link_to "Destroy", alert, :confirm => "Are you sure", :method => :delete, :remote => :true
What I want to have is a link on my index page Delete All which I could use to hide(update) all of the alerts. I've been attempting this with a destroy_all method for my controller, but I felt like it wasn't quite the right approach, as I didn't know how to link to something like that. Thank you for pointing me in the right direction.
Here is the destroy_all method I'd hacked together, for reference.
def destroy_all
#alerts.each do |alert|
alert.update(show: false) if alert
respond_to do |format|
format.js {render :nothing => true}
end
end
end
I don't know how you have routed to this controller but I would probably do something like this:
#routes.rb
resources :alerts do
delete :remove_all, :on => :collection
end
This will create a route looking like /alerts/remove_all which can only be called through the DELETE protocol. By specifying :collection it tells the routing the this route is not a sub route to one specific Alert so no :id is included.
Then the controller action could probably look something like this:
def remove_all
Alert.update_all({ show: false }, { show: true })
respond_to do |format|
format.js {render :nothing => true}
end
end
The update_all function will make sure that there is only one database update instead of one for each alert that is to be removed. The first argument is a hash containing the updates and the second argument is a hash with the conditions for which records are to be updated.
And from the view you should be able to link to the action like this:
= link_to "Remove All", remove_all_alerts_path, :confirm => "Are you sure", :method => :delete, :remote => :true
remove_all_alerts_path is a path helper that is automatically generated when you use the above syntax in routes.rb

Problem rendering an Ajax partial with link_to specifying a controller action

I have a div (id="content") on a "proposition" show page into which I want to render different partials depending on which tab at the top of the div is selected.
I'm trying to render a partial (substantive_content) with AJAX using the following link_to:
<%= link_to "Connected", :url => {:controller => "propositions",
:action => "substantive_content"}, :remote => true %>
I've got two problems:
On clicking the link, a GET request
is sent to
PropositionsController#show, and
not (I presume) to the "substantive
content" action. This just refreshes the page and doesn't do anything remotely. The correct partial isn't displayed.
I'm not sure how then to render a
partial into the "content" div.
At the moment I have this in the PropositionsController:
def substantive_content
respond_to do |format|
format.js{ render :update do |rightbar|
rightbar.replace_html 'content', 'Hello World!'
end}
end
end
... but am not sure where to go from here. Am I even going about this in the right way? I'm very new to rails, javascript, etc.
Any help with either of these problems would be fantastic. Thanks!
In your routes.rb file you should have an entry for the substantive_content action. It might look something like this:
match "substantive_content" => "propositions#substantive_content", :as => substantive_content
Then in your view the link should look something like this:
<%= link_to "Connected", substantive_content_path, :remote => true %>
I would render a js.erb file when the js request comes to the substantive_content action. The action would look soemthing like this:
def substantive_content
respond_to do |format|
format.js
end
end
Then create a substantive_content.js.erb file in your views/propositions directory. In that file you can use jquery to update the content div:
$('#content').html("<%= render :partial => 'your_partial_name_here' %>");
Without knowing more about the actual application you're working on, its hard to say if this is the best way to accomplish what you want. I generally try to stay as "RESTful" as possible with my apps so I'm reluctant to create actions aren't part of the normal index, new, create, show, etc. set. That's not to say that it isn't neccesary in this case, but it's something to think about.

Form behavior posting nested resource

I am using Ruby on Rails 3 and I would like to change its conventional behavior on posting a form in order to post from a signup action to the create action instead that from the new action. That is, I would like to use the signup action instead of the (conventional) new action in my User controller and trigger the create action to save my model data that contains nested resources.
In my /config/routes.rb file I have:
resources :users do
collection do
get 'signup'
end
resource :profile
end
In my /app/controllers/users_controller.rb I have
class UsersController < ApplicationController
def signup
#signup_user = User.new(params[:user])
#signup_user.build_profile # NOTE: Nested resource
...
end
def create
...
#signup_user.save
respond_to do |format|
format.html { render :action => :signup } # signup.html.erb
end
end
end
In my /app/views/users/signup.html.erb file I have
<%= form_for #signup_user do |f| %>
...
<% end %>
My problem is that if I submit the above form, I will be redirected to the index action of the user controller and not to the create action I expect. It seams that the form posts only to the index action.
How can I solve the problem?
I tryed to use the following
<%= form_for( :user, #signup_user, :url => { :controller => "users", :action => "create" }, :html => { :method => :post } do |f| %>
but I have still the problem: I am redirected to the index action.
SOLUTION
The problem did seam to be in the routers.rb. The correct code was
resources :users do
collection do
get 'signup'
post 'create'
end
resource :profile
end

Resources