Last Updated
Viewed 20 Times

I have two controllers in my app. as of now- User & Post.The user controller has only these methods as of now are - index,new,create and show. I show users posts in users#show view page only.

I wanted to add a functionality to delete the post. I added the method to delete post in post's controller....But i when click on delete button it shows an error The action 'destroy' could not be found for UsersController

Which is true, I dont have method destroy in users controller.

How can i delete post using posts controller only? I dont want to user controller here , to delete post as - i want to add functionality to delete user in future

class UsersController < ApplicationController

  def index
    @users = User.all
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(set_params)
    if @user.save
      UserNotifierMailer.send_signup_email(@user).deliver
      flash[:success] ="Success"
      redirect_to new_sessions_path and return
    else
      render 'new'
    end

  end

  def show
    @user = User.find(params[:id])
    @posts = @user.posts
  end

  private

  def set_params
    params.require(:user).permit(:name, :email, :password, :password_confirmation)
  end

  def post_params
    params(:post.require).permit(:title, :body)
  end

end

User#show

<div class="col-md-8">
    <h1> Posts ( <%= @posts.count %> ) </h1>
    <%= @posts.each do |p| %>

        <div class="form-field">
            <h4><b><%= p.title %></b>  <%= link_to "Edit", edit_post_path(p.id), class: "btn 
                 btn-warning col-md-2-offset", style: "align-right" %><%= link_to "Delete", 
                 @post , method: :delete,data: { confirm: "You sure? "}, class: "btn btn-danger 
                 col-md-2-offset", style: "align-right" %></h4> 
            <%= p.body %>
        </div>
    <% end %>

Post Controller - delete method

 def destroy
     @post = Post.find(params[:id])
     @post.destroy
     flash.now[:success] = "Succesfully Deleted"
     redirect_to user_path(current_user)
  end

Routes

Rails.application.routes.draw do
  root 'posts#index'
  resources :users
  resources :posts
  resource :sessions, only: [:new, :create, :destroy]
  resources :passwords, only: [:new, :create, :edit, :update]
end

Rake routes : DELETE /posts/:id(.:format) posts#destroy

Similar Question 1 : How to delete session in rails?

I am able to log in into application even after logging out, by clicking the back button on search bar.

For some strange reasons, I am not able to delete the session completely.

I am not using any gem. I want to create rails authentication from scratch.

Sessions Controller:

 class SessionsController < ApplicationController
  def new
  end

  def create
    user = User.find_by_email(params[:email])
    if user && user.authenticate(params[:password])
      log_in user
      redirect_to user
    else
      flash.now[:danger] = 'Invalid email/password combination'
      render 'new'
    end
  end

  def destroy
    reset_session
    redirect_to root_path
  end

end

Application Helper

  class ApplicationController < ActionController::Base

  protect_from_forgery with: :exception

  helper_method :current_user,:logged_in?, :logged_in_user,:current_user

   def log_in(user)
     session[:user_id] = user.id
   end

   def current_user
      @current_user ||= User.find_by(id: session[:user_id])
   end

   def logged_in?
     !current_user.nil?
   end

   def logged_in_user
     unless logged_in?
       flash[:danger] = "Please log in."
       redirect_to new_session_path
     end
   end


   def current_user?(user)
     user == current_user
    end

end

Allpication.html.erb

  <body>

    <div class="container">

       <% flash.each do |message_type, message| %>
          <div class="alert alert-<%= message_type %>"><%= message %></div>
       <% end %>

       <header>

         <% if logged_in? %>
           <%= link_to "Log out", sessions_path, method: "delete" %>
           <%= link_to "Edit", edit_user_path(current_user) %>
         <% else %>
           <li>
             <%= link_to "Sign Up", new_user_path %>
           </li>
           <li>
             <%= link_to "Log in", new_sessions_path %>
           </li>
         <% end %>



         </header>
         <%= yield %>
       </div>
    </body>

Please help me. I am going nuts.

User Controller

class UsersController < ApplicationController
    before_action :logged_in_user, only: [:new, :show, :edit, :update]
    before_action :correct_user, only: [:new, :show, :edit, :update]

    def index
      @users = User.all
    end

    def new
      @user = User.new
    end

    def create
      @user = User.new(set_params)
      if @user.save
        redirect_to new_session_url
      else
        render 'new'
      end
    end

    def show
      @user = User.find(params[:id])
      @posts = @user.posts
    end

    def edit
      @user = User.find(params[:id])
    end

    def update
       @user = User.find(params[:id])
       if @user.update(update_params)
        redirect_to @user
      else
        render 'edit'
      end
    end



    private

    def set_params
      params.require(:user).permit(:name, :email, :password, :password_confirmation)
    end
    def update_params
      params.require(:user).permit(:name, :email, :password, :password_confirmation)
    end


    def correct_user
      @user = User.find(params[:id])
      redirect_to(root_url)  unless current_user?(@user)
    end


end

User is able to log in only he/she logged in.

I have updated my code as per what i have been suggested or what i have i tried.

I have 3 models in my application namely - user, post and comments. They are associated like this

  • A user can have posts
  • A posts belongs to a user
  • A post can have many reviews
  • A review belongs to a user

Posts Model

class Post < ApplicationRecord
  belongs_to :user
  has_many :comments, dependent: :destroy
  validates :title, presence: true
  validates :body, presence: true
end

User Model

class User < ApplicationRecord

  before_create { generate_token(:auth_token) }

  before_save { self.email = email.downcase }

  has_secure_password
  has_many :posts


  validates :name, presence: true
  validates :email, presence: true, uniqueness: true
  validates :password, confirmation: true
  validates :password_confirmation, presence: true, unless: Proc.new { |a| !a.new_record? && a.password.blank? }

  def send_password_reset
    generate_token(:reset_password_token)
    self.reset_password_sent_at = Time.zone.now
    save!
    UserMailer.password_reset(self).deliver
  end


  def generate_token(column)
    begin
      self[column] = SecureRandom.urlsafe_base64
    end while User.exists?(column => self[column])
  end

end

Review Model

class Review < ApplicationRecord
    belongs_to :user
end

User Controller - show method

  def show
    @user = User.find(params[:id])
    @posts = @user.posts
    @reviews = @posts.reviews //This line shows error
  end

I think something is wrong in the way i am associating these models. I want to show comments made on a post with that post. I show from posts users controller....but i when i tried to display comments the same way. I

I had manually gone and made a comment to post in rails console.

Review table from schema

  create_table "reviews", force: :cascade do |t|
    t.string "comment"
    t.string "user_id"
    t.string "post_id"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

I am running:

Rails 6 Ruby 2.5 Postgres 11.5 Mac OSX

I have the following routes defined:

Rails.application.routes.draw do
  get 'welcome/index'
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  root 'welcome#index'

  post 'search_controller/search'
end

I have the following code in my view:

 <%= form_for :search, :url => url_for(:controller => 'search_controller', :action => 'search'), remote: true do |f| %>
  <%= f.text_field :search_term %>
  <%= f.submit %>

The resultant form code is:

<form action="/search_controller/search" accept-charset="UTF-8" data-remote="true" method="post">
  <input type="text" name="search[search_term]" id="search_search_term">
  <input type="submit" name="commit" value="Save Search" data-disable-with="Save Search">
</form>

Which to me looks as I would expect. I have also attempted a rails 6 style form as per :

<%= form_with(url: "/search_controller/search", method: "post") do %>
  <%= label_tag(:q, "Search for:") %>
  <%= text_field_tag(:term) %>
  <%= submit_tag("Search") %>

which results in the same issue.

When I click the button, I get a HTTP 404 response:

rails-ujs.js:215 POST http://localhost:40250/search_controller/search 404 (Not Found)

When I run rails routes I get :

   Prefix Verb   URI Pattern                                                                              Controller#Action
                        welcome_index GET    /welcome/index(.:format)                                                                 welcome#index
                                 root GET    /                                                                                        welcome#index
             search_controller_search POST   /search_controller/search(.:format)                                                      search_controller#search
        rails_mandrill_inbound_emails POST   /rails/action_mailbox/mandrill/inbound_emails(.:format)                                  action_mailbox/ingresses/mandrill/inbound_emails#create
        rails_postmark_inbound_emails POST   /rails/action_mailbox/postmark/inbound_emails(.:format)                                  action_mailbox/ingresses/postmark/inbound_emails#create
           rails_relay_inbound_emails POST   /rails/action_mailbox/relay/inbound_emails(.:format)                                     action_mailbox/ingresses/relay/inbound_emails#create
        rails_sendgrid_inbound_emails POST   /rails/action_mailbox/sendgrid/inbound_emails(.:format)                                  action_mailbox/ingresses/sendgrid/inbound_emails#create
         rails_mailgun_inbound_emails POST   /rails/action_mailbox/mailgun/inbound_emails/mime(.:format)                              action_mailbox/ingresses/mailgun/inbound_emails#create
       rails_conductor_inbound_emails GET    /rails/conductor/action_mailbox/inbound_emails(.:format)                                 rails/conductor/action_mailbox/inbound_emails#index
                                      POST   /rails/conductor/action_mailbox/inbound_emails(.:format)                                 rails/conductor/action_mailbox/inbound_emails#create
    new_rails_conductor_inbound_email GET    /rails/conductor/action_mailbox/inbound_emails/new(.:format)                             rails/conductor/action_mailbox/inbound_emails#new
   edit_rails_conductor_inbound_email GET    /rails/conductor/action_mailbox/inbound_emails/:id/edit(.:format)                        rails/conductor/action_mailbox/inbound_emails#edit
        rails_conductor_inbound_email GET    /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                             rails/conductor/action_mailbox/inbound_emails#show
                                      PATCH  /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                             rails/conductor/action_mailbox/inbound_emails#update
                                      PUT    /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                             rails/conductor/action_mailbox/inbound_emails#update
                                      DELETE /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                             rails/conductor/action_mailbox/inbound_emails#destroy
rails_conductor_inbound_email_reroute POST   /rails/conductor/action_mailbox/:inbound_email_id/reroute(.:format)                      rails/conductor/action_mailbox/reroutes#create
                   rails_service_blob GET    /rails/active_storage/blobs/:signed_id/*filename(.:format)                               active_storage/blobs#show
            rails_blob_representation GET    /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
                   rails_disk_service GET    /rails/active_storage/disk/:encoded_key/*filename(.:format)                              active_storage/disk#show
            update_rails_disk_service PUT    /rails/active_storage/disk/:encoded_token(.:format)  

Note that you can see the route at search_controller_search.

Given these details, why am I getting the 404?

cc