0

I'm new to rails and am working on a simple reddit-type app for practice. I'm trying to let users update the link they have posted. This is the links_controller:-

  class LinksController < ApplicationController
  before_action :logged_in_user, only: [:new, :create, :edit, :update]
  #before_action :correct_user, only: [:edit, :update]

  def new
    @link = Link.new
  end

  def create
    @user = current_user
    @link = @user.links.build(params)
    if @link.save
      flash[:success]= "Link submittd successfully"
      redirect_to root_path
    else
      flash[:danger]= "Link submission failed"
      render 'new'
    end
  end

  def edit
    @user = current_user
    @link = @user.links.find_by(id: params[:id])
  end

  def update
    @user = current_user
    @link = @user.links.find_by(id: params[:id])
    if @link.update_attributes(params)
      flash[:success] = "Link successfully edited"
      redirect_to current_user
    else
      flash[:danger] = "Link edit failed"
      render 'edit'
    end
  end

  private

    # def link_params
    #   params.permit(:title, :url)
    # end

    def logged_in_user
      redirect_to login_path unless logged_in
    end

    def correct_user
      @link = current_user.links.find_by(id: params[:id])
      redirect_to root_path if @link.nil?
    end
end

Currently I'm facing this error:-

Log:-

Started GET "/edit_link" for ::1 at 2017-05-23 13:20:56 +0530
Processing by LinksController#edit as HTML
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  Link Load (0.2ms)  SELECT  "links".* FROM "links" WHERE "links"."user_id" = ? AND "links"."id" IS NULL ORDER BY "links"."created_at" DESC LIMIT ?  [["user_id", 1], ["LIMIT", 1]]
  Rendering links/edit.html.erb within layouts/application
  Rendered links/edit.html.erb within layouts/application (4.6ms)
Completed 500 Internal Server Error in 70ms (ActiveRecord: 1.6ms)

ActionView::Template::Error (First argument in form cannot contain nil or be empty):
    4: <div class="row">
    5:   <div class="col-md-6 col-md-offset-3">
    6: 
    7:     <%= form_for(@link, url: edit_link_path) do |f| %>
    8: 
    9:       <%= f.label :title %>
   10:       <%= f.text_field :title, class: 'form-control' %>

This is the edit form for the link:-

<% provide(:title, 'Edit Link') %>
<h1>Edit Link</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">

    <%= form_for(@link, url: edit_link_path) do |f| %>

      <%= f.label :title %>
      <%= f.text_field :title, class: 'form-control' %>

      <%= f.label :url %>
      <%= f.text_field :url, class: 'form-control' %>

      <%= f.submit "Save Changes", class: "btn btn-primary" %>
    <% end %>
  </div>
</div>

The routes file:-

  Rails.application.routes.draw do

  root 'static_pages#home'
  get '/login', to: 'sessions#new'
  post '/login', to: 'sessions#create'
  delete '/logout', to: 'sessions#destroy'
  get '/signup', to: 'users#new'
  post '/signup', to: 'users#create'
  get '/submit_link', to: 'links#new'
  post '/submit_link', to: 'links#create'
  get '/edit_link', to: 'links#edit'
  patch '/edit_link', to: 'links#update'
  get '/contact', to: 'static_pages#contact'

  resources :users
  resources :links
end

As it stands it is really messy. There are many different things that could be wrong and I don't have enough grasp over the various factors to find out the best way to do this.

I'm especially struggling with the params, strong params.

Basically this is what I'm trying to implement:-

  • Only logged in user who is the owner of the link can access the edit and update actions for the link. I'm using the before_action filters to ensure this.
  • I'm using strong params as defined in the link_params method in private

I'm not 100% sure on the code in the edit and update actions. What I've listed up there is just what I think should be the logical code.

If you could show me how to get this to work and also the best practice to be followed while doing this, it would be great.

Update:- I tried to use link_params earlier but that seemed to generate the error of the required link not being present, so I have muted it for now and am trying to work out how to get it to work through params first.

As it stands it seems that the edit and update actions are not receiving the params[:id] that is required for them to proceed with the action. I don't know how to get the params to be accessible in the actions. I've used the custom route get "edit_link_path" for the links#edit and patch "edit_link_path" for the links#update. Don't know if this is a problem.

Most recent update:-

updated routes.rb (with the link.id appendage to edit and update routes):-

Rails.application.routes.draw do

  root 'static_pages#home'
  get '/login', to: 'sessions#new'
  post '/login', to: 'sessions#create'
  delete '/logout', to: 'sessions#destroy'
  get '/signup', to: 'users#new'
  post '/signup', to: 'users#create'
  get '/edit_link/link.id', to: 'links#edit'
  patch '/edit_link/link.id', to: 'links#update'
  get '/submit_link', to: 'links#new'
  post '/submit_link', to: 'links#create'
  get '/contact', to: 'static_pages#contact'

  resources :users
  resources :links
end

A list of all available routes:-

$ rails routes
         Prefix Verb   URI Pattern                  Controller#Action
           root GET    /                            static_pages#home
          login GET    /login(.:format)             sessions#new
                POST   /login(.:format)             sessions#create
         logout DELETE /logout(.:format)            sessions#destroy
         signup GET    /signup(.:format)            users#new
                POST   /signup(.:format)            users#create
                GET    /edit_link/link.id(.:format) links#edit
                PATCH  /edit_link/link.id(.:format) links#update
    submit_link GET    /submit_link(.:format)       links#new
                POST   /submit_link(.:format)       links#create
        contact GET    /contact(.:format)           static_pages#contact
          users GET    /users(.:format)             users#index
                POST   /users(.:format)             users#create
       new_user GET    /users/new(.:format)         users#new
      edit_user GET    /users/:id/edit(.:format)    users#edit
           user GET    /users/:id(.:format)         users#show
                PATCH  /users/:id(.:format)         users#update
                PUT    /users/:id(.:format)         users#update
                DELETE /users/:id(.:format)         users#destroy
          links GET    /links(.:format)             links#index
                POST   /links(.:format)             links#create
       new_link GET    /links/new(.:format)         links#new
      edit_link GET    /links/:id/edit(.:format)    links#edit
           link GET    /links/:id(.:format)         links#show
                PATCH  /links/:id(.:format)         links#update
                PUT    /links/:id(.:format)         links#update
                DELETE /links/:id(.:format)         links#destroy   links#update
                PUT    /links/:id(.:format)         links#update
                DELETE /links/:id(.:format)         links#destroy

Currently the error is No route matches [PATCH] "/links/2/edit"

As you can see above in the list of available routes, there is a "edit_link GET /links/:id/edit(.:format) links#edit" but there is no equivalent for the update action even though the routes.rb file has the listing for that. Don't understand why.

Ragav Y
  • 1,662
  • 1
  • 18
  • 32

1 Answers1

0

Ok, finally figured it out and fixed everything. The problem was with the routing. I had to route the link id in the routes for edit and update and it had to be patch '/link.:id'. Everything else including strong params and correct_user works after that. Great!

Ragav Y
  • 1,662
  • 1
  • 18
  • 32