How to set up routes correctly - ruby-on-rails

I can untrash all the messages checked in index view without any problem.
But in show view, the link generated show the link to /messages/discard.3
this 3 could be ID.
How can I make it work? it should be linked to messages/discard/3
My files are like these
routes.rb
get "messages/received"
get "messages/sent"
get "messages/trash"
get 'messages/:id' => 'messages#show', :as => :show_messages
match 'messages/new/:username', :to => 'messages#new', :as => :new_messages
match 'messages/deliver' => 'messages#deliver', :via => :post
match 'messages/discard' => 'messages#discard', :via => :post, :as => :discard_messages
match 'messages/untrash' => 'messages#untrash', :via => :post
view 1 (index.html.erb)
<%= form_tag(:action=> discard) do %>
<% #messages.each do |m| %>
<tr>
<td><%= check_box_tag "checked_items[#{m.id}]",m.id %></td>
<td><%= m.last_message.id %></td>
<td><%= 'unread' if m.is_unread?(current_user) %></td>
<td><%= m.last_message.created_at %></td>
<td><%= m.last_sender.username %></td>
<td><%= link_to m.subject, show_messages_path(m) %></td>
</tr>
<% end %>
view 2 (show.html.erb)
<%= link_to 'Trash', discard_messages_path(#messages) %>
messages_controller.rb
def discard
conversation = Conversation.find_all_by_id(params[:checked_items].keys)
if conversation
current_user.trash(conversation)
flash[:notice] = "Message sent to trash."
else
conversations = Conversation.find(params[:conversations])
conversations.each { |c| current_user.trash(c) }
flash[:notice] = "Messages sent to trash."
end
redirect_to :back
end

You can try change it to:
match 'messages/discard/:id' => 'messages#discard', :via => :post, :as => :discard_messages
However I think what you should do is to change your all routes to:
resource :messages do
member do
#code
end
collection do
#code
end
end
It's easier to read and maintain

Related

form not updating for specific record rails

I'm trying to update a record with a button, by having and admin user tyoe confirm a record by clicking the confirm submit button with this form, but it would just update the first record in the database, not the specific one. Can i put "hour.id" in the form_for section to make it update the record i want it to?
index.html.erb form view
<% #allhours.each do |hour| %>
<tr id="dashfield">
<td><%= hour.user.first_name + " " +hour.user.last_name %></td>
<td><%= hour.assignment %></td>
<td><%= hour.hours %></td>
<td><%= hour.supervisor %></td>
<td><%= hour.date %></td>
<td><%= link_to "confirm", edit_hour_path(hour.id, :status => 'confirmed')%></td>
</tr>
<% end %>
Controller
def index
#allhours = HourLog.where(status:'pending')
end
def update
#hour = HourLog.find_by(status:'pending')
#hour.update_attribute(update_hour_params)
redirect_to '/dashboard/hours'
end
def edit
#hour = HourLog.find(params[:id])
#hour.update_attributes(update_hour_params)
redirect_to '/dashboard/hours'
end
hour_log model
class HourLog < ActiveRecord::Base
belongs_to :user
end
routes
Rails.application.routes.draw do
root 'welcome#index'
get '/signup' => 'users#new'
resources :users
get '/dashboard/users' => 'users#index'
put '/dashboard/users' => 'users#update'
get '/login' => 'sessions#new'
post '/login' => 'sessions#create'
delete '/logout' => 'sessions#destroy'
get '/dashboard' => 'hours#new'
get '/dashboard/hours' => 'hours#index'
put '/dashboard/hours' => 'hours#update'
resources :hours
Thanks!
This line :
#hour = HourLog.find_by(status:'pending')
will find the first Hourlog that is in pending status. You should pass the hourlog id in the form and use it in the controller
change the line in the routes :
put '/dashboard/hours/:id' => 'hours#update'
in the view :
<%= form_tag dashboard_hours_path(id:hour.id), method: :put do %>
<%= hidden_field_tag :role, :value => 'confirm'%>
<%= submit_tag 'Confirm'%>
<% end %>
in the controller :
#hour = HourLog.find(params[:id])

How do I route to a new rails controller action

I'm new to Rails and have the encountered this problem.
I have a books_controller where I have defined a new action called download:
def download
#book = Book.find(params[:id])
return send_file #book.get_filepath, :type => 'application/pdf', :filename => #book.get_filename
end
My routes.rb is like:
resources :books
match '/books(/download(/:id))', :controller => "books", :action => "download"
I would like to create a URL like /books/download/10 to call the download action.
I'm not sure how I can create that link. I have tried reading the Rails Guide on routing, but am very confused by it.
I have tried
<td><%= link_to books_download_path(book) %></td>
and it clearly doesn't work.
undefined method `books_download_path' for #<#<Class:0x682ac40>:0x482cad8>
I'd appreciate any help on this.
Thanks
P.S. Maybe /books/10/download makes more sense than /books/download/10
index.html.erb
<table>
<% #recent_books.each do |book| %>
<tr>
<!-- <td><%= image_tag(book.get_thumbnail) %></td> -->
<td><%= truncate(book.get_title, :length => 30) %></td>
<td><%= book.get_author %></td>
<td><%= book.get_summary %></td>
<td><%= truncate(book.get_filename, :length => 30) %></td>
<!-- <td><%= link_to 'Download', book %></td> -->
<td><%= link_to "Download", download_book_path(book) %></td>
</tr>
<% end %>
<table>
routes.rb
Caliberator::Application.routes.draw do
resources :authors
resources :books do
get :download, :on => :member, :to => 'books#download'
end
end
For Rails 3, try this
resources :books do
get :download, :on => :member, :to => 'books#download'
end
Now, in your views, you can use.
<%= link_to 'Download', download_book_path(book) %>
This will generate books/10/download type links.
Try following
match '/books(/download(/:id))', :controller => "books", :action => "download", :as => "books_download"
Ref:- naming_routes
You have to do it like this :
<%= link_to "Download", download_books_path + "/#{book.id}" %>
For rails 3, you should write:
resources :books do
member do
get 'download'
end
end

How can I pass the parameters to controller correctly?

From show view: I'd like to pass the shown message's id to discard action and trash the message.
From index view: I'd like to pass the checked messages' ids to discard action and trash them all at once.
But I only can trash one record at once even if I check multiple and submit from index view.
How can I archive both 1 and 2 with the same action????
Routes
match 'messages/discard(/:id)' => 'messages#discard', :via => :post , :as => :discard_messages
index view
<%= form_tag(:action => discard, :via => 'post') do %>
<% #messages.each do |m| %>
<tr>
<td><%= check_box_tag "id",m.id %></td>
<td><%= m.last_message.id %></td>
<td><%= 'unread' if m.is_unread?(current_user) %></td>
<td><%= m.last_message.created_at.to_s(:jp) %></td>
<td><%= m.last_sender.username %></td>
<td><%= link_to m.subject, show_messages_path(:id => m, :breadcrumb => #box) %></td>
</tr>
<% end %>
<%= submit_tag "discard", :class => 'btn' %>
<% end %>
show view
<%= link_to 'Discard', discard_messages_path(#messages), :class => 'btn', :method => 'post' %>
controller
def discard
conversation = Conversation.find_all_by_id(params[:id])
if conversation
current_user.trash(conversation)
flash[:notice] = "Message sent to trash."
else
conversations = Conversation.find(params[:conversations])
conversations.each { |c| current_user.trash(c) }
flash[:notice] = "Messages sent to trash."
end
redirect_to :back
end
use the [] naming in your html, which rails will then make available as an array in the params
index.html.erb
<td><%= check_box_tag "message_id[]", m.id %></td>
controller
# ...
else
conversations = Conversation.where("id IN (?)", params[:message_id][])
# ...
to simplify things further I would remove the conditional in your action and create two separate actions
routes
resource :messages do
member do
post 'discard' # /messages/:id/discard
end
collection do
post 'discard_all' # /messages/discard_all?message_id[]=1&message_id[]=22
end
end

How to delete multiple checked records in rails?

I figured out how to display checkbox for each row.
The problem is that I can't find out how to write form_tag and submit tag in order to pass the checked rows parameter to messages_controller with using detele action.
and what to write in delete action.
Please help me out!
My view is
<table>
<tr>
<th>delete</th>
<th>ID</th>
<th>Read</th>
<th>Date</th>
<th>Sender</th>
<th>Subject</th>
</tr>
<% #messages.each do |m| %>
<tr>
<td><%= check_box_tag '', m.id, false, class: 'delete_multiple_checkbox', name: "conversations[]" %>
<td><%= m.last_message.id %></td>
<td><%= 'unread' if m.is_unread?(current_user) %></td>
<td><%= m.last_message.created_at %></td>
<td><%= m.last_sender.username %></td>
<td><%= m.subject %></td>
</tr>
<% end %>
</table>
and controller should be something like this( according to this here https://github.com/frodefi/rails-messaging/blob/master/app/controllers/messaging/messages_controller.rb)
def trash
conversation = Conversation.find_by_id(params[:id])
if conversation
current_user.trash(conversation)
flash[:notice] = "Message sent to trash."
else
conversations = Conversation.find(params[:conversations])
conversations.each { |c| current_user.trash(c) }
flash[:notice] = "Messages sent to trash."
end
redirect_to messages_path(box: params[:current_box])
end
route.rb
Example::Application.routes.draw do
root :to => "top#index"
devise_for :users, :controllers => { :registrations => "registrations" }
get 'girls', :to => 'girls#index', :as => :user_root
match '/girls/comment' => 'girls#comment', :via => :post
get "girls/show"
resources :girls
resources :home
devise_for :users do get 'logout' => 'devise/sessions#destroy' end
resources :girls do
collection do
get 'tag'
end
end
resources :contacts
resources :user_profiles
match 'messages/new/:username', :to => 'messages#new'
get "messages/sent"
get "messages/trash"
get "messages/received"
get "messages/show"
get "messages/trash"
match '/messages/deliver' => 'messages#deliver', :via => :post
end
Modify the syntax listed below to fit your requirement:
Model.where(:id => [1,2,3,4,5]).destroy_all
or
Model.where(id: params[:id]).destroy_all
All you have to do is wrap the whole messages rendering block with a form_tag and add a submit_tag wherever you'd like. I assumed your controller is MessagesController under blank namespace and the action is trash. Note that if your controller is under messaging namespace you might want to change the :controller => :messages into :controller => 'messaging/messages'.
<% form_tag :url => { :controller => :messages, :action => :trash}, :method => :delete do %>
<% #messages.each do |m| %>
<tr>
<td><%= check_box_tag '', m.id, false, class: 'delete_multiple_checkbox', name: "conversations[]" %>
<td><%= m.last_message.id %></td>
<td><%= 'unread' if m.is_unread?(current_user) %></td>
<td><%= m.last_message.created_at %></td>
<td><%= m.last_sender.username %></td>
<td><%= m.subject %></td>
</tr>
<% end %>
<%= submit_tag "Trash All Checked" %>
<% end %>
I also assumed your routes.rb accepts a HTTP DELETE method for the specified route. You can check that with rake route | grep messages and verify the route is set.
If it is not you will have to add it with:
resources :messages do
collection do
delete :trash
end
end

Creating a link to subscribe to a product?

I need help on figuring how to make a link for my Product that enables users to subscribe to it. I first have my Subscription model:
class Subscription < ActiveRecord::Base
attr_accessible :subscribable_id
belongs_to :subscriber, :class_name => "User"
belongs_to :subscribable, :polymorphic => true
end
Then my Product model:
class Product < ActiveRecord::Base
attr_accessible :name, :price
belongs_to :user
has_many :subscriptions, :as => :subscribable
end
My plan is to make my view, similar to the DELETE method a link to click to subscribe to a product. Here is my routes, controller and then view:
resources :products do
post :subscribe_product, :on => :collection
end
ProductsController:
def subscribe_product
#product = Product.find(params[:id])
# Not sure what goes here next?
# Something like: user.subscriptions.create(:subscribable => product)
end
View:
<table>
<% for product in #products %>
<tbody>
<tr>
<td><%= product.name %></td>
<td><%= product.price %></td>
<td><%= link_to 'Delete', product, :confirm => 'Are you sure?', :method => :delete %></td>
<td><%= link_to 'Subscribe', :controller => "products", :action => "subscribe_product", :id => product.id %></td>
</tr>
</tbody>
<% end %>
</table>
Right now this gives a strange error:
ActiveRecord::RecordNotFound in ProductsController#show
Couldn't find Product with id=subscribe_product
Theirs 2 things,
Creating the method to subscribe.
Making the link correct.
How would I do these two?
By default link_to uses GET, so your router thinks you are trying to go to ProductsController#show with the first param being the ID
http://yoursite.com/products/subscribe_product/5
This is a get request to the products controller with an id param of subscribe_product.
If you pass :method => :post to your link_to helper, it will issue a post request, which is what your router is expecting.
<%= link_to 'Subscribe', :controller => "products", :action => "subscribe_product", :id => product.id, :method => :post %>
Without posting your user model, I can't know for sure, but the method will look like this:
#product.subscriptions.create(:user_id => user.id)
# user.id would be current_user.id, or whatever you are storing the current user as
Your subscribe_product path uses POST, so you'll want to change your link to use that method:
<%= link_to 'Subscribe', {:controller => "products", :action => "subscribe_product", :id => product.id}, :method => :post %>
Your action will probably look something like this:
#product.subscriptions << Subscription.new(:user_id => current_user.id)

Resources