I want to modify the value in the object. However, modified routing does not work properly.
#routes
root 'freelancers#index'
get 'new' => 'freelancers#new'
post 'category' => 'freelancers#category'
get 'video' => 'freelancers#video'
get 'video/show/:id' => 'freelancers#video_show'
get 'video/new' => 'freelancers#video_new'
post 'video/create' => 'freelancers#video_create'
get 'video/:id/edit' => 'freelancers#video_edit'
patch 'video/show/:id/update' => 'freelancers#video_update'
get 'design' => 'freelancers#design'
Form code:
<%= form_for(#video, :html => { :multipart => true, :id => #video.id, :url => '/video/show/:id/update' }, method: :patch ) do |f| %>
i expect the output of /video/show/3/update
but the actual output is video.3
Fast way:
Change this line:
patch 'video/show/:id/update' => 'freelancers#video_update'
To:
patch 'video/show/:id/update' => 'freelancers#video_update', as: :update_video
This will create update_video_path as named helper in your application. Then you will be able to use it:
<%= form_for(#video, :html => { :multipart => true, :id => #video.id, :url => update_video_path(#video) }, method: :patch ) do |f| %>
You can check the documentation for more information.
Right way:
Seems that you need to refactor your routes and controllers. It is a good practice when your controller covers one resource. In your case it seems that you need at least two controllers: FreelancersController and VideosController, and videos resources should be nested inside freelancers.
For example, it might look like this:
root 'freelancers#index'
resources :freelancers, only: [:index, :new] do
collection do
get :design
post :category
resources :videos, only: [:index, :new, :create, :show, :edit, :update]
end
end
I left design and category in the example as is, but probably these routes also need the separate controllers.
This way is better, because:
Routes become more understandable and more supportable
Your controllers are responsible for only one resource each
You get a bunch of path and URL helpers without additional work
Your application follows the conventions
Of course, if you need to customize application URLs, Rails provides you the way, but in most cases following the convention is better.
You can find more information in the documentation.
Related
Am new to ruby on rails. Here Am trying to display image from database. To this effect, I leverage solution found here
link. but when I run my script it displays error
No route matches {:action=>"show", :controller=>"attachments_controller", :id=>17}
Please what am I doing wrong with the route.
Routes
Rails.application.routes.draw do
resources :attachments, only: [:index, :new, :create, :destroy]
root "attachments#create"
get "attachments/show" => "attachments#show"
end
attachments_controller
class AttachmentsController < ApplicationController
def show
#attachment = Attachment.find(params[:id])
send_data #attachment.data, :filename => #attachment.filename, :type => #attachment.content_type
end
end
show.html
<%= image_tag url_for(:controller => "attachments_controller", :action => "show", :id => #attachment.id) %>
The error message you provided states:
No route matches {:action=>"show", :controller=>"attachments_controller", :id=>17}
The routes file you provided shows the routes you created:
resources :attachments, only: [:index, :new, :create, :destroy]
get "attachments/show" => "attachments#show"
Running rake routes will show that you've created the 4 routes in the first line, plus a route that responds to 'attachments/show'. If you really want to define the route like this, you should try:
get "attachments/:id", to: "attachments/show"
Your first route only responds to the word show, and would supply no params. The last route will take whatever comes after attachments, and pass it to the show action of the attachments controller as a paramater called 'id'.
Of course the easiest way to do all of that is to get rid of it all, and simply change the first route to:
resources :attachments, only: [:index, :new, :create, :destroy, :show]
Letting rails create the show route for you is exactly the same as manually defining it, and obviously reads a lot better
change
<%= image_tag url_for(:controller => "attachments_controller", :action => "show", :id => #attachment.id) %>
to
<%= image_tag url_for(:controller => "attachments", :action => "show", :id => #attachment.id) %>
I have a controller for a resource, BuddiesController. My routes config file up until now has been
resources :buddies
match ':controller(/:action(/:id))', :via => [:get, :post]
I didn't realize what the ' resources :buddies ' line was doing until I read up on routing in Rails just now, because the behavior has been identical with what I expected until now. The problem was that I wanted to add a non-CRUD action to the controller: 'search'. Every time I used link_to(:action => 'search'), I would get an exception saying that action 'show' could not be found despite the url being ' localhost:3000/buddies/search ' as expected. I have several questions arising from this:
Firstly, the form I used in 'new' stopped working:
%= form_for(#buddy, {:action => :create, :method => :post, :html => {:role => "form"}}) do |f| %>
because buddies_path couldn't be found. How could I manually add a buddies_path to my routes?
Secondly, I revised the form to use:
<%= form_for(#buddy, :url => {:action => :create, :id => #buddy.id}, :html => {:role => "form", :id => #buddy.id}) do |f| %>
but this has caused the form to give me password and email confirmation not matching errors even if they match. What's going on here?
Lastly, what is the best way to add a search action to my resource?
#routes.rb
resources :buddies
collection do
get :search
end
end
now when you run rake routes | grep 'buddies' you will get output something like this :
now you need to define this search action in your buddies controller .
#buddies_controller.rb
Class BuddiesController < ApplicationController
def search
end
end
Have your search form in app/views/buddies/search.html.erb
Now in order to open your search form / to hit your search action you need to use
<%= link_to 'Search XYZ', search_buddies_path %>
against buddies#search you can see search_buddies
In routes.rb:
resources :buddies do
collection do
post :search
end
end
This might make your routing works.
I have the following route
namespace :dashboard do
get '/courses/:id/edit' => 'courses#edit', :as => :edit_course
put 'courses/:id/update' => 'courses#update'
end
and this form
= form_tag dashboard_edit_course_url( #course), :method => 'post', :multipart => true do
...
the action being:
<form accept-charset="UTF-8" action="http://localhost:3000/dashboard/courses/54633b9fc14ddd104c004de3/edit" enctype="multipart/form-data" method="post">
But when I submit the form I get this error:
The page you were looking for doesn't exist.
You may have mistyped the address or the page may have moved.
I don't understand why? Could somebody explain?
An alternative way to handle this. In your routes write:
namespace :dashboard
resources :courses, only: [:edit, :update]
end
And in your view write:
= form_tag [:dashboard, #course], multipart: true do |f|
Then you will use rails defaults.
Your form states to use post, but you don't have a post route configured.
The rails way to do this is to submit the form to the update path via put, since you are updating a record:
= form_tag dashboard_update_course_path( #course), :method => 'put', :multipart => true do
Also, you probably want to use path instead of url.
Then just name the update route:
namespace :dashboard do
get '/courses/:id/edit' => 'courses#edit', :as => :edit_course
put '/courses/:id/update' => 'courses#update', :as => :update_course
end
The first parameter is where the form submission should go (update).
http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-form_tag
I want to add another action to my controller, and I can't figure out how.
I found this on RailsCasts, and on most StackOverflow topics:
# routes.rb
resources :items, :collection => {:schedule => :post, :save_scheduling => :put}
# items_controller.rb
...
def schedule
end
def save_scheduling
end
# items index view:
<%= link_to 'Schedule', schedule_item_path(item) %>
But it gives me the error:
undefined method `schedule_item_path' for #<#<Class:0x6287b50>:0x62730c0>
Not sure where I should go from here.
A nicer way to write
resources :items, :collection => {:schedule => :post, :save_scheduling => :put}
is
resources :items do
collection do
post :schedule
put :save_scheduling
end
end
This is going to create URLs like
/items/schedule
/items/save_scheduling
Because you're passing an item into your schedule_... route method, you likely want member routes instead of collection routes.
resources :items do
member do
post :schedule
put :save_scheduling
end
end
This is going to create URLs like
/items/:id/schedule
/items/:id/save_scheduling
Now a route method schedule_item_path accepting an Item instance will be available. The final issue is, your link_to as it stands is going to generate a GET request, not a POST request as your route requires. You need to specify this as a :method option.
link_to("Title here", schedule_item_path(item), method: :post, ...)
Recommended Reading: http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to
Ref Rails Routing from the Outside In
Following should work
resources :items do
collection do
post 'schedule'
put 'save_scheduling'
end
end
You can write routes.rb like this:
match "items/schedule" => "items#schedule", :via => :post, :as => :schedule_item
match "items/save_scheduling" => "items#save_scheduling", :via => :put, :as => :save_scheduling_item
And the link_to helper can not send post verb in Rails 3.
You can see the Rails Routing from the Outside In
In routes.rb:
resources :conversations, only: [:index, :show, :new, :create, :destroy] do
collection do
get :inbox
end
In my controller:
def inbox
<stuff>
end
In my view (using haml):
=link_to 'Inbox', inbox_conversations, :id => 'load-inbox', :class => 'message-control-highlight', :remote => true
I get the following error on page load:
undefined local variable or method `inbox_conversations' for #<#<Class:0x3d51470>:0x3d59198>
In my view, if I replace inbox_conversations with a "#", I don't get any errors on page load. I've tried appending inbox_conversation with likely classes, such as current_user and current_user.mailbox. I've also tried changing the routing from collection to member--and even taking it out of any collection/member block. What could be the problem here?
Try using inbox_conversations_path or inbox_conversations_url
=link_to 'Inbox', inbox_conversations_path, :id => 'load-inbox', :class => 'message-control-highlight', :remote => true
You need to append _path or _url to your routes, e.g.
= link_to 'Inbox', inbox_conversations_path
See the complete Rails Routing guide for all the details:
http://guides.rubyonrails.org/routing.html