Rails: url_to scope - ruby-on-rails

In the following piece of code (of course in a view) I have <td><%= post.full_hsh %></td> displaying correctly the value of the field post.full_hsh, but url_for gives an error: No route matches {:controller=>"posts", :action=>"edit", :id=>nil}.
Why is post.full_hsh correct in a row and nil in the row below? Thanks
<% #posts.each do |post| %>
<tr>
<td><%= truncate post.body, :length => 100, :separator => ' ' %>...</td>
<td><%= post.created_at %></td>
<td><%= post.full_hsh %></td>
<td><%= url_for :controller => 'posts', :action => 'edit', :id => post.full_hsh %></td>
</tr>
<% end %>
EDIT:
my routes.rb file:
get "admin/index"
root :to => 'home#index'
#access posts via /posts/ab123c or /p/ab123c
resources :posts, :path => 'p', :except => [:new, :index, :delete]
resources :posts, :except => [:new, :index, :delete]
match '/p/:id/delete' => 'posts#delete', :as => 'posts_delete'
match '/admin' => 'admin#index'

post.full_hsh is an attribute of the post objection. you probably want :id => post instead
You want to generate the URL based on the object itself, in this case post, not on the attribute of an object (post.full_hsh)

Related

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 to set up routes correctly

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

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

Rails - will_paginate has broken link_to

I've added the will_paginate gem, and it's working fine on all other areas of site. However, whenever I try clicking in the 'Show' links in the view, to link to the order, it's giving me this error message: *
The #orders variable appears to be empty. Did you forget to pass the collection object for will_paginate?*
Anyone have any ideas why this is happening and how I can fix it? I've tried restarting the server. Thanks!!
View code:
<h3>Your Orders:</h3>
<table class="order-items">
<th>Date</th>
<th>Order No.</th>
<th>View Order</th>
<% #orders.each do |order| %>
<tr>
<td><%= order.created_at.strftime("%d %b. %Y") %></td>
<td><%= order.id %></td>
<td><%= link_to 'Show', order_path(order) %></td>
</tr>
<% end %>
</table>
<p><%= will_paginate #orders %></p>
Controller Code:
#customer = Customer.find(params[:id])
#orders = #customer.orders.paginate page: params[:page], order: 'id desc',
per_page: 5
Routes:
resources :orders
resources :customers
get 'admin' => 'admin#index'
get 'account' => 'customers#show'
match '/account', :to => 'customers#show'
match'/signup', :to => 'customers#new'
controller :sessions do
get 'login' => :new
post 'login' => :create
delete 'logout' => :destroy
end
resources :users
resources :line_items
resources :carts
get "store/index"
resources :products do
get :who_bought, on: :member
end
resources :line_items do
put 'decrease', on: :member
put 'increase', on: :member
end
root to: 'store#index', as: 'store'

Rails - will_paginate gem not working when using .each do

EDIT: I've altered the code to now read:
View code:
<h3>Your Orders:</h3>
<table class="order-items">
<th>Date</th>
<th>Order No.</th>
<th>View Order</th>
<% #orders.each do |order| %>
<tr>
<td><%= order.created_at.strftime("%d %b. %Y") %></td>
<td><%= order.id %></td>
<td><%= link_to 'Show', order_path(order) %></td>
</tr>
<% end %>
</table>
<p><%= will_paginate #orders %></p>
Controller Code:
#customer = Customer.find(params[:id])
#orders = #customer.orders.paginate page: params[:page], order: 'id desc',
per_page: 5
Routes:
resources :orders
resources :customers
get 'admin' => 'admin#index'
get 'account' => 'customers#show'
match '/account', :to => 'customers#show'
match'/signup', :to => 'customers#new'
controller :sessions do
get 'login' => :new
post 'login' => :create
delete 'logout' => :destroy
end
resources :users
resources :line_items
resources :carts
get "store/index"
resources :products do
get :who_bought, on: :member
end
resources :line_items do
put 'decrease', on: :member
put 'increase', on: :member
end
root to: 'store#index', as: 'store'
The problem is now that I'm getting the error:
The #orders variable appears to be empty. Did you forget to pass the collection object for will_paginate?
whenever I click on a "Show" link in the list of orders in the view. Tried restarting the server just in case, but can't get it working :S!
It should be
<% #orders.each do |order| %>
not
<% #customer.orders.each do |order| %>
Pls check this code
#customer = Customer.find(params[:id])
#orders = #customer.orders.paginate page: params[:page], order: 'title',per_page: 5
in view
<% #orders.each do |order| %>

Resources