Edit a nested resource in rails - ruby-on-rails

In the following code segment
.comment
%p= comment.comment
%p= comment.user.email
= link_to 'Edit', edit_post_comment_path(comment.post, comment)
= link_to "Delete", [comment.post, comment], method: :delete, data: {confirm: 'Are you sure"'}
why do both Edit and Delete take in comment.post as a parameter? What does it mean?

It require comment.post because you have made nested routes, check your routes.rb file where you have define routes as below:
resources :posts do
resources :comments
end
and your routes is for EDIT and DELETE is
edit_post_comment GET /posts/:post_id/comments/:id/edit(.:format) comments#edit
DELETE /posts/:post_id/comments/:id(.:format) comments#destroy
That's why you always need to pass comment.post as a parameter.
If you don't want comment.post as parameter you can change your routes as:
resources :posts
resources :comments
OR if you don,t want to pass comment.id in any particular action do your routes as
resources :posts do
resources :comments, :except => [:delete]
end
resources :comments, :only => [:delete]
NOTE: I am assuming that you don't want comment.post parameter for :delete action

Comment is a nested resource here which means comments belongs to a post.
Because rails routes are defined in a RESTFUL Way.
If you see in the RESTful way, all the CRUD operations in comment resource require post resource id, since comment is associated with post.
Not only the 'Edit' and 'Delete' operation requires parent resource id, All the CRUD operation requires it.
Have a look here at Nested resource section.

Related

Ruby-on-rails - Destroy - Error: No route matches [GET]

I am using destroy
In my view, I have:
#delete_archive_modal.modal.fade
.modal-header
%h3
%i.icon-exclamation-sign
Attention
.modal-body
%p= "Are you sure you want to delete this portal?"
.modal-footer
%a.btn{"data-dismiss" => "modal", :href => "#"} Cancel
= link_to 'Delete', delete_portal_path(portal)
Routes:
resources :portals do
resources :pill_tabs, only: [:show, :edit]
resources :page_urls do
collection do
get :redirects
end
end
resources :zero_touch_configs do
member do
get :history
end
end
member do
get :navigation
get :history
get :sitemap
get :url_list
post :generate_sitemap
post :add_modules
post :archive
post :delete
end
collection do
get :index, path: '/'
get :new, path: '/new(/:portal_type)'
get :accessible_sites
get :archive_index
get :delete
end
And in my controller:
def destroy
#portal = Portal.find(params[:id])
#portal.destroy
flash[:notice] = 'Portal deleted successfully.'
redirect_to action: :archive_index
end
routes:
portals GET /portals(.:format) portals#index
GET /portals/new(/:portal_type)(.:format) portals#new
accessible_sites_portals GET /portals/accessible_sites(.:format) portals#accessible_sites
archive_index_portals GET /portals/archive_index(.:format) portals#archive_index
delete_portals GET /portals/delete(.:format) portals#delete
history_portal_stack_wrapper GET /portals/:portal_id/stack_wrappers/:id/history(.:format) stack_wrappers#history
drafts_portal_stack_wrapper GET /portals/:portal_id/stack_wrappers/:id/drafts(.:format) stack_wrappers#drafts
purge_portal_stack_wrapper GET /portals/:portal_id/stack_wrappers/:id/purge(.:format) stack_wrappers#purge
all_drafts_portal_stack_wrappers GET /portals/:portal_id/stack_wrappers/drafts(.:format) stack_wrappers#all_drafts
portal_stack_wrappers GET /portals/:portal_id/stack_wrappers(.:format) stack_wrappers#index
POST /portals/:portal_id/stack_wrappers(.:format) stack_wrappers#create
new_portal_stack_wrapper GET /portals/:portal_id/stack_wrappers/new(.:format) stack_wrappers#new
edit_portal_stack_wrapper GET /portals/:portal_id/stack_wrappers/:id/edit(.:format) stack_wrappers#edit
portal_stack_wrapper GET /portals/:portal_id/stack_wrappers/:id(.:format) stack_wrappers#show
PATCH /portals/:portal_id/stack_wrappers/:id(.:format) stack_wrappers#update
PUT /portals/:portal_id/stack_wrappers/:id(.:format) stack_wrappers#update
DELETE /portals/:portal_id/stack_wrappers/:id(.:format) stack_wrappers#destroy
history_portal_config_bundle GET /portals/:portal_id/config_bundles/:id/history(.:format) config_bundles#history
portal_config_bundles GET /portals/:portal_id/config_bundles(.:format) config_bundles#index
POST /portals/:portal_id/config_bundles(.:format) config_bundles#create
new_portal_config_bundle GET /portals/:portal_id/config_bundles/new(.:format) config_bundles#new
edit_portal_config_bundle GET /portals/:portal_id/config_bundles/:id/edit(.:format) config_bundles#edit
portal_config_bundle GET /portals/:portal_id/config_bundles/:id(.:format)
But I am getting a routing error and don't know where to go from here...
No route matches [GET] "/portals/asdg/delete"
Can anyone share a guide or point me to documentation that helps me understand what's wrong here?
Try
= link_to 'Delete', portal_path(portal), method: :delete
Here are the all 7 routes for portal
portals GET /portals(.:format) portals#index
POST /portals(.:format) portals#create
new_portal GET /portals/new(.:format) portals#new
edit_portal GET /portals/:id/edit(.:format) portals#edit
portal GET /portals/:id(.:format) portals#show
PATCH /portals/:id(.:format) portals#update
PUT /portals/:id(.:format) portals#update
DELETE /portals/:id(.:format) portals#destroy
And in your routes you have delete_portal path will exist because of
member do
post :delete
end
If you want to call this then you have do define method for this action in your controller and call this path with method: :post
But in RESTful routes delete action have always DELETE method, see in above routes.
There are two issues in your link_to tag.
You used delete_portal_path(portal) but if you run rake routes on your console you will see no such route exist. it have portal_path(portal).
You need to specify method type in route in case of Show(GET default), update(PUT) and delete(DELETE). Because all share same path portal_path(portal).
So your final route should be:
= link_to 'Delete', portal_path(portal), method: :delete
More detail here
You need to define http method when you use delete
= link_to 'Delete', portal_path(portal), method: :delete
It will work.

when does rails make path with a dot rather than backslash?

why rails is making a path like
/notification_templates/duplicate_me.1
it is supposed to be
/notification_templates/duplicate_me/1
my routes are
resources :notification_templates do
collection do
get :blast_send
patch :deactivate
patch :activate
get :get_list
post :duplicate_me
end
end
and my link is
<%= link_to "Duplicate", duplicate_me_notification_templates_path(template), method: :post, class: "btn btn-primary" %>
You are trying to pass a resource to a collection route. For this to work, your route should be defined as a member route instead:
resources :notification_templates do
collection do
get :blast_send
patch :deactivate
patch :activate
get :get_list
end
member do
post :duplicate_me
end
end
And the reason it translates the route to a dot currently is that the path helper most probably understands the parameter passed in (template) as a format specification. Formats are separated from the route using a dot.
Since the route is made for collection, it does not expect a template instance variable for id.
To make the route as /notification_templates/duplicate_me/1, make the changes in your routes.rb like
resources :notification_templates do
collection do
get :blast_send
patch :deactivate
patch :activate
get :get_list
end
post :duplicate_me, on: :member
end
and change your view to
<%= link_to "Duplicate", duplicate_me_notification_template_path(template), method: :post, class: "btn btn-primary" %>
When you want to pass id like
/notification_templates/duplicate_me/1
as member for the resource you should make member routes. Please look in this enter link description here . it would help you.
This way would help you.
resources :notification_templates do
collection do
get :blast_send
patch :deactivate
patch :activate
get :get_list
end
member do
post :duplicate_me
end
end

Finding routes within nested resource in Rails

I am wondering how to access routes in nested resources in rails. I added categories and it as broken my application.
Routes:
resources :categories do
resources :posts do
resources :comments
end
end
It errors out in this:
<% #posts.each_with_index do |post, index| %>
<%= link_to post do %> # originally, this used to work but now it says 'undefined method "post_path"'
<li class="post-title"><%= truncate post.title, length: 50 %></li>
<li class="post-content"><%= truncate post.content, length: 400 %></li>
<li><span class="post-comments"><%= post.comments.count %> comments</span></li>
<% end %>
My root is set to posts#index and has a listing of posts. However, the route nesting (originally I didn't have categories) has broken the routes.
Running rake routes I get in part this:
category_posts GET /categories/:category_id/posts(.:format) posts#index
POST /categories/:category_id/posts(.:format) posts#create
new_category_post GET /categories/:category_id/posts/new(.:format) posts#new
edit_category_post GET /categories/:category_id/posts/:id/edit(.:format) posts#edit
category_post GET /categories/:category_id/posts/:id(.:format) posts#show
PATCH /categories/:category_id/posts/:id(.:format) posts#update
PUT /categories/:category_id/posts/:id(.:format) posts#update
DELETE /categories/:category_id/posts/:id(.:format) posts#destroy
How can I adjust routes to compensate for nesting? Or is there a better way to nest?
You'd need to define another block that nests posts under category resource:
# Existing
resources :posts do
resources :comments
end
# Additional block
resources :categories do
resources :posts do
resources :comments
end
end
With the additional block, your existing routes remain unchanged so existing routes don't break!
It is always better to restrict the routes to only what you need/use. For example if you only need /categories/:category_id/posts, i.e. just the index method on the posts_controller, then your route will be updated to:
resources :categories do
resources :posts, only: [ :index ]
end
This way you have more control on your routes and greater maintainability of the application.
vee's answer is correct if you want to use the nested routes and still preserve the original URLs. This is recommend this if your site is live and changing the URLs would affect links to your indexed pages.
Otherwise, you should point your links to the nested resource, like this:
<%= link_to post.title, [post.category, post] %>
See: Rails - link_to, routes and nested resources

how to fill twice id from routes rails

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

Post to Create Action Using link_to

I'm trying to post to my registration controller using a link_to link.
I have <%= link_to "Register for Period", registration_path(period_id: period.id), :method => :post %>
Which generates a link like: http://localhost:3000/registrations/6?period_id=25 where the 6 is the event_id. I need to save the period_id and the user_id to the registration database.
I get the following error in the browser: No route matches [POST] "/registrations/6"
What am I doing wrong?
routes:
Mavens::Application.routes.draw do
devise_for :users
resources :events
resources :periods
resources :products
resources :cart_rows
resources :product_requests
resources :inqueries
resources :registrations
match '/profile', to: 'static_pages#profile'
root :to => 'static_pages#home'
get "static_pages/home"
get "static_pages/about"
end
If you put in your routes.rb:
resources :registrations do
member do
post :save_period
end
end
And in your link:
<%= link_to "Register for period",
save_period_registration_path(id: #registration.id, period_id: period.id), :method => :post %>
You will have a route that matches your resquest.
When you only have a resources :registrations rule on your routes.rb, only the default restful routes are created, and there is no POST to a single resource created by default.
I believe you will have to read something about the CSRF token, because if you have a protect_from_forgery on your application_controller, probably this POST request from a single link would not work.
Your routes.rb is missing the required path. It IS a standard path, so adding 'resources :registrations' would work.
If more complex, post your routes.rb and we can tell what to add.

Resources