Himadri Ganguly
Himadri Ganguly

Reputation: 743

Generating wrong URL in the form action using form_for in rails4

I am using rails 4.0.0. I am a newcomer to rails and learning rails watching video tutorials and stuck in a problem so need some help.

I have a controller called Subjects and following is the code

Subject Constoller

class SubjectsController < ApplicationController

  before_action :set_subject, only: [:show, :edit, :update]

  def index
    @subjects = Subject.all
  end

  def list
    @subjects = Subject.all
    #@subjects = Subject.order("subjects.position ASC")
  end 

  def show
    @subject = Subject.find(params[:id])
  end

  def new
    @subject = Subject.new(:name => "default")  
  end

  def create
    @subject = Subject.new(subject_params)
        if @subject.save
        redirect_to(:action => 'list')
    else
        render('new')
    end
  end

  def edit

  end

  def update
    if @subject.update(subject_params)
        redirect_to @subject
    else
        render("edit")
    end
  end

  def delete
    @subject = Subject.find(params[:id])
  end

  def destroy   
    Subject.find(params[:id]).destroy
    redirect_to(:action => "list")
  end

  private

  # Use callbacks to share common setup or constraints between actions.
    def set_subject
      @subject = Subject.find(params[:id])
    end

  # Never trust parameters from the scary internet, only allow the white list through.
    def subject_params
      params.require(:subject).permit(:name, :position, :visible)
    end

end

I created a view for the List Action

View for the List Action

<h1>List</h1>
<div class="subject list">
  <h2>Subjects</h2>

  <table class="listing" summary="Subject list">
    <tr class="header">
      <th>Position</th>
      <th>Subject</th>
      <th>Visible</th>
      <th>Pages</th>
      <th>Actions</th>
    </tr>
    <% @subjects.each do |subject| %>
    <tr>
      <td><%= subject.position %></td>
      <td><%= subject.name %></td>
      <td class="center"><%= subject.visible ? 'Yes' : 'No' %></td>
      <td class="center"><%= subject.pages.size %></td>
      <td class="actions">
        <%= link_to 'Show', subject, :class => 'action show'%>
        <%= link_to "Edit", edit_subject_path(subject), :class => 'action edit' %>
        <%= link_to "Delete", {:action => 'delete', :id => subject.id}, :class => 'action delete' %>
      </td>
    </tr>
    <% end %>
  </table>
</div>

I also have a view for delete and code is as follows

View for Delete Action

<h1>Delete</h1>
<%= link_to("<< Back to List", {:action => 'list'}, :class => 'back-link') %>

<div class="subject delete">
  <h2>Delete Subject</h2>

  <%= form_for(:subject, :url => {:action => "destroy", :id => @subject.id}) do |f|%>

    <p>Are you sure you want to permanently delete this subject?</p>

    <p class="reference-name"><%= @subject.name %></p>

    <div class="form-buttons">
      <%= submit_tag("Delete Subject") %>
    </div>

  <% end %>
</div>

Here is the configuration of my routes file

SimpleCms::Application.routes.draw do  
  # The priority is based upon order of creation: first created -> highest priority.
  # See how all your routes lay out with "rake routes".

  # You can have the root of your site routed with "root"
  # root 'welcome#index'
  root 'demo#index'

  # Example of regular route:
  #   get 'products/:id' => 'catalog#view'
  get 'demo/index'
  get 'demo/hello'
  get 'demo/other_hello'
  #get 'subjects/index'
  get 'subjects/list'
  get 'subjects/delete'
  get  '/subjects/:id/destroy' => 'subjects#destroy'
  resources :subjects
  get 'subjects/show'
  get 'subjects/new'
  get 'subjects/:id' => 'subjects#show'

  # Example of named route that can be invoked with purchase_url(id: product.id)
  #   get 'products/:id/purchase' => 'catalog#purchase', as: :purchase

  # Example resource route (maps HTTP verbs to controller actions automatically):
  #   resources :products
  #resources :subjects

  # Example resource route with options:
  #   resources :products do
  #     member do
  #       get 'short'
  #       post 'toggle'
  #     end
  #
  #     collection do
  #       get 'sold'
  #     end
  #   end

  # Example resource route with sub-resources:
  #   resources :products do
  #     resources :comments, :sales
  #     resource :seller
  #   end

  # Example resource route with more complex sub-resources:
  #   resources :products do
  #     resources :comments
  #     resources :sales do
  #       get 'recent', on: :collection
  #     end
  #   end

  # Example resource route with concerns:
  #   concern :toggleable do
  #     post 'toggle'
  #   end
  #   resources :posts, concerns: :toggleable
  #   resources :photos, concerns: :toggleable

  # Example resource route within a namespace:
  #   namespace :admin do
  #     # Directs /admin/products/* to Admin::ProductsController
  #     # (app/controllers/admin/products_controller.rb)
  #     resources :products
  #   end
end

So the main concept is as follows when i will call http://localhost:3000/subjects/list it will show all the subjects and there is also three button that is show, edit and delete and after clicking on the delete link it will go to the delete view and after clicking on the submit button of the form it will be deleting the particular item.

But the main problem is that the form_for in delete view is producing the url in the form action is /subjects/8 where 8 is the id of the subject to be deleted but the url should be /subjects/destroy?id=8 to delete the item but when id is passed along with the action in form_for it produces the wrong url but when only the action is passed it produces the url as /subjects/destroy.

I cannot figure out what is wrong so please help. Thanks to all in advance.

Upvotes: 0

Views: 2077

Answers (2)

Ridhi
Ridhi

Reputation: 1

Try this:

<%= form_for(@subject, :url => {:action => "destroy") do |f|%>

Instead of this:

<%= form_for(:subject, :url => {:action => "destroy", :id => @subject.id}) do |f|%>

You don't need to mention the id because in form_for it takes id of the variable mentioned by default.

Upvotes: 0

rails_id
rails_id

Reputation: 8220

Try a link with delete method instead use a form.

<p>Are you sure you want to permanently delete this subject?</p>

<p class="reference-name"><%= @subject.name %></p>

<%= link_to 'Delete Subject', @subject, method: :delete %>

UPDATE

If you want to use a form for destroy action, try this :

<% form_for @subject, :html => {:method => :delete} do |form| %>

Upvotes: 3

Related Questions