I have this custom action in my videos controller:
def upvoted_songs
#votes = current_user.videos_votes.where("value = 1")
#videos = #votes.videos.page(params[:page]).per(15)
end
this is my routes:
resources :videos do
member do
put 'topic_update'
get 'upvoted_songs'
end
end
And this link in my videos index view:
<%= link_to "Upvoted Songs", videos_path, :action => "upvoted_songs", :class => "upvoted_songs chosen_home_option" %>
and a view file called videos/upvoted_songs.html.erb.
Why doesn't the link direct to the upvoted_songs.html.erb view but rather stay on the video index view?
UPDATE:
These is my routes.rb:
root :to => "videos#index"
resources :video_votes
resources :videos do
resources :comments
member do
put 'topic_update', :on => :member
get 'upvoted_songs', :on => :collection, :as => 'upvoted'
end
end
resources :comment_titles
resources :users
resources :profiles
resources :genres
resources :topics
resources :topicables
resource :session
I initially get this error:
ArgumentError
can't use member outside resource(s) scope
Then after refreshing the page, I get this error:
ActionController::RoutingError in Videos#index
Showing /rubyprograms/dreamstill/app/views/videos/_video.html.erb where line #22 raised:
No route matches {:action=>"show", :id=>#<Video id: 485, title: "I'm Ready For You", description: nil, embed_code: nil, thumbnail_url: nil, released: nil, user_id: 57, created_at: "2011-04-02 08:47:36", updated_at: "2011-04-09 22:42:48", video_url: "http://www.youtube.com/watch?v=wy86KNtOjVg", video_votes_count: 0, vote_sum: 3, rank_sum: 28927.724512>, :controller=>"videos"}
22: <%= link_to video.title, video_path(video), :class => "normal" %>
To see what routes are available for use in your app use rake routes on the command line in the root directory of the app. You should see a line that refers to upvoted_songs.
Then use it like so:
<%= link_to "Upvoted Songs", upvoted_songs_video_path(video), :class => "upvoted_songs chosen_home_option" %>
Since you have it has a member route the url helper will take a video object (or id) and generate a url that looks something like: /videos/7/upvoted_songs
However, your code suggests that you might be doing something that does not rely on a single video object, and wouldn't need that in the URL either. So you would want to change that route from a member route to a collection route. The URL would then end up looking something like /videos/upvoted_songs and you wouldn't be passing it a video object.
Hope this helps :)
PART 2
Remove the member block:
resources :videos do
resources :comments
put 'topic_update', :on => :member
get 'upvoted_songs', :on => :collection, :as => 'upvoted'
end
You are linking to videos_path, which is a helper for "videos#index".
As ctcherry explained, your current route is using a member route and not a collection. The following is more what you're looking for:
resources :videos do
put 'topic_update', :on => :member
get 'upvoted_songs', :on => :collection, :as => 'upvoted'
end
Then you can use upvoted_videos_path in place of just videos_path.
You don't have an id. Do a rake routes | grep upvoted and see what your route should look like.
it's probably something like upvoted_songs_video_path(video)
Related
I have in routes.rb
get '/cities/:city/:section' => 'cities#show', as: 'city_section_slug'
get '/cities/:city/:section/:subsection' => 'cities#show', as: 'city_subsection_slug', :constraints => { :subsection => /[^\/]*/ }
And rake show these routes
city_section_slug GET (/:locale)/cities/:city_id/:section(.:format) cities#show {:locale=>/ru|en/}
city_subsection_slug GET (/:locale)/cities/:city_id/:section/:subsection(.:format) cities#show {:subsection=>/[^\/]*/, :locale=>/ru|en/}
But when I try create a link:
= link_to city_subsection_slug_path(#city,section.alias, subsection.alias)
Iv got such error:
ActionController::RoutingError (No route matches {:controller=>"cities", :action=>"show", :locale=>:ru, :city=>#<City id: 42, name: "City">, :section=>"events", :subsection=>"sobytiya/ya-ochevidets"}):
Any ideas where I am wrong?
The reason is your constraint on subsection param. You specified that it can be anything as long as it does not contain / character. Your subsection does conatin it hence the error. If you want to allow / character, then do:
get '/cities/:city/:section/:subsection' => 'cities#show',
as: 'city_subsection_slug',
constraints: { :subsection => /^[a-z0-9_\/]+$/ }
Eventually, you can use glob param:
get '/cities/:city/:section/*subsection' => 'cities#show',
as: 'city_subsection_slug',
#config/routes.rb
resources :cities, only: [] do
get ":section", action: :show, as: :city_section_slug #-> url.com/cities/:city_id/:section
get ":section/*subsection", action: :show, as: :city_subsection_slug #-> url.com/cities/:city_id/:section/:subsection
end
The corresponding links:
<%= link_to "x", city_section_slug_path(#city, section.alias) %>
<%= link_to "x", city_subsection_slug_path(#city, section.alias, subsection.alias) %>
Wildcard
If you're expecting to send sobytiya/ya-ochevidets to your subsection path, you'll be best using a wildcard route
i try to fill twice id in url, but when i send params twice id just one id fill the url id.
My route :
namespace :admin do
resources :stores
get "/:id/new_items"=> 'stores#new_items', as: :store_new_items
post "/:id/create_items"=> 'stores#create_items', as: :store_create_items
get "/:id/show_items/:id"=> 'stores#show_items', as: :store_show_items
get "/:id/items/:id/new_items_sub" => 'stores#new_items_sub', as: :store_new_items_sub
post "/:id/items/:id/create_items_sub" => 'stores#create_items_sub', as: :store_create_items_sub
get "/:id/items/:id/show_items_sub/:id" => 'stores#show_items_sub', as: :store_show_items_sub
end
my view :
<%= link_to "add new items", admin_store_new_items_sub_path(#store.id, #items.id), :class=> "btn" %>
i hope my url like this :
http://localhost:3000/admin/#{store.id}/items/#{items.id}/new_items_sub
but i get same id like this :
http://localhost:3000/admin/#{store.id}/items/#{store.id}/new_items_sub
please tell me when i'm wrong? thanks
you have to create neseted routes for that .have a look at
http://guides.rubyonrails.org/routing.html#nested-resources
for example
resources :publishers do
resources :magazines do
resources :photos
end
end
will accept routes /publishers/1/magazines/2/photos/3
Your params should be unique, so you can't pass more than one different :id params. Instead. you can do something like:
get '/:store_id/show_items/:id', as: :store_show_items
and in view:
<%= link_to 'show items', store_show_items_path(#store.id, #item.id) %>
Also, you should read more about Resources and Nested Resources in Rails, there's probably no need to complicate your life by creating each route independently.
You could refactor this to use nested routes like this (you may have to change controller method names):
namespace :admin do
resources :stores do
resources :items, :only => [:new, :create, :show] do
resources :subs, :only => [:new, :create, :show]
end
end
end
This would give you a few url helpers like this: new_store_item_sub_path(#store.id, #item.id) for the new action and store_item_sub_path(#store.id, #item.id, #sub.id) for the show action.
Run rake routes to see what helpers and routes you have access to.
Have a look here to find out more about nested routes.
Your code can be DRYed up significantly. Hopefully this works; might need some tweaking:
namespace :admin do
resources :stores do
member do
get :new_items, as: :store_new_items
post :create_items, as: :store_create_items
end
get "show_items/:id"=> 'stores#show_items', as: :store_show_items
resources :items do
get :new_items_stub => 'stores#new_items_sub', as: :store_new_items_sub
post :create_items_stub => 'stores#create_items_sub', as: :store_create_items_sub
get "show_items_sub/:id" => 'stores#show_items_sub', as: :store_show_items_sub
end
end
end
Uses Member Routes (see 2.10) & Nested Resources
Nested Resources
The crux of your issue is that you're trying to pass the :id param twice
Fortunately, Rails has a solution to this, in the form of Nested Resources. These work by taking the "parent" id and prepending a singular prefix, such as :store_id, allowing you to use the :id param for another set of methods
I have the following route, that appears in the list when I perform "rake routes":
page_upload_image POST /pages/:page_id/upload_image(.:format) pages#upload_image
I also have the following in my routes file:
resources :pages do
post :sort, :on => :collection
post :upload_image, :on => :collection
end
I'm then using JavaScript to capture and POST values pulled from the following:
%form.new-page-image{:class => "hide", :action => "/pages/#{#page.id}/upload_image"}
%input.page_image{:type => "file", :name => "page[image]", :multiple => "true"}
I have the following for my upload_image action in my pages controller:
def upload_image
image = params[:page][:image]
uploader = PageImageUploader.new
uploader.store!(image)
render json: uploader.to_json
end
For some reason, even though the route exists, when I post to it, I get the following:
ActionController::RoutingError (No route matches [POST] "/pages/1/upload_image"):
I'm wondering why a route, that appears legitimate (shows up properly when executing rake routes) would return this error when I try to post to it.
Try changing your routes to this instead, as it looks like you want a member route instead of a collection route:
resources :pages do
post :sort, :on => :collection
post :upload_image, :on => :member
end
I would also advise against using interpolation in the route, as it can quickly get long and messy. Instead try to name your routes using as: and call them using the names instead.
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
I'm trying to setup a route that looks like this: acme.com/posts/:category/:status. Both :category and :status are optional. I wrote many variations, but none worked:
resources :posts do
match '(/:category)(/:status)', to: 'posts#index', as: 'filter', on: :collection
end
# Category Links
link_to "Questions", filter_posts_path(:questions)
link_to "Suggestions", filter_posts_path(:suggestions)
# Status Links
link_to "Published", filter_posts_path(params[:category], :published)
link_to "Draft", filter_posts_path(params[:category], :draft)
The idea is to be able to 1) filter by category, 2) filter by status, and 3) filter by both category and status if both are available. The current setup has also broken my /posts/new path, always redirecting to posts#index.
I had this variation and it seems working fine:
namespace :admin do
resources :posts, :except => [:show] do
collection do
get "/(:category(/:status))", to: "posts#index", as: "list", :constraints => lambda{|req|
req.env["PATH_INFO"].to_s !~ /new|\d/i
}
end
end
end
= CONTROLLER=admin/posts rake route
list_admin_posts GET /admin/posts(/:category(/:status))(.:format) admin/posts#index
You can use the more RESTful resources :posts (in config/routes.rb) and send the params in the query string.
With that approach, all parameters are optional and you're not limited to using predefined parameters.
Do this works for you?
resources :posts do
collection do
match '/:category(/:status)', to: 'posts#index', as: 'filter'
match '/:status', to: 'posts#index', as: 'filter'
end
end
Hope at least it helps!
You could try something like this:
match '/filter/*category_or_status' => 'posts#index', as: 'filter'
With this you can build your own filter path. Then you could parse params[:category_or_status] in your controller and get the category or status if they are given.