problem with routes?

0

I have two models, Tarea and Comentario , and the relationship is one to many. This would be the code for my router:

Rails.application.routes.draw do
  resources :tareas do
    resources :comentarios
  end
  root to:'tareas#index' 
  #put 'tareas/finalizar'
  match 'tareas/finalizar/:id', to:'tareas#finalizar',via: :get
  get 'tareas/create'
  get 'tareas/new'

  get 'tareas/show'

  get 'tareas/edit'

  get 'tareas/update'

  get 'tareas/destroy'


end

When I call the function finalizar tarea I should run the controller tasks with the end method, but apparently this method does not recognize me.

My controller code

class TareasController < ApplicationController
      def index        @tareas=Tarea.select("id,titulo,descripcion").where(:activo=>true).order("id DESC")
      end

      def new
        @tarea=Tarea.new()
      end

      def create
        @tarea=Tarea.new(tarea_params)
        @tarea.activo=true
      if @tarea.save()
        redirect_to tareas_path,:notice=>"La tarea se guardo correctamente"
      else
        render "new"
      end
    end

      def show
        @tarea=buscar_id
      end
    private
     def buscar_id
    Tarea.find(params[:id])

      end
        def edit
        @tarea=Tarea.find(params[:id])
        @[email protected]
        @[email protected]
        @[email protected]
        puts "tarea #{@tarea.titulo} descripcion #{@tarea.descripcion}"
        end

      def update
        @titulo=params[:tarea]["titulo"]
        @descripcion=params[:tarea]["descripcion"]
        @prioridad=params[:tarea]["prioridad"]
        @tarea=Tarea.find(params[:id])
        @tarea.titulo=@titulo
        @tarea.descripcion=@descripcion
        @tarea.prioridad=@prioridad
        if @tarea.save()
          redirect_to tareas_path,:notice=>" La tarea a sido modificado exitosamente"

        else
    render "edit"      
        end


      end

      def destroy
        @tarea=buscar_id
        if @tarea.destroy()
          redirect_to tareas_path,:notice=>"la Tarea a sido eliminado correctamente"

        else
          redirect_to tareas_path,:notice=>"la tarea no ha sido elminada"

        end
      end
      private 
      def tarea_params
        params.require(:tarea).permit(:titulo,:descripcion,:prioridad)
      end


        def finalizar
         @tarea=Tarea.find(params[:id])
         @tarea.activo=false
          if @tarea.update()
             redirect_to tareas_path,:notice=>"la tarea a finalizado"
          else
           redirect_to tareas_path,:notice=>"la tarea NO  a finalizado"
          end
          end
    end
    
asked by 15.08.2017 в 16:58
source

2 answers

1

When you define "Private" in a controller, all the methods that come after that declaration will be private, unless you declare another visibility. As Gerry suggests you should leave all methods private or protected for the end to better organize your code and avoid this problem.

Besides the problem in your controller you also have errors in your routes file: First of all when you put

resources :tareas

you are already creating all your REST routes (index, new, create, show, edit, update, destroy). Below you create the same actions again. However you are not doing well. If you would like to create the route for the "show" action, for example, you will need to pass the ID in the route (later you are using it in the controller). Therefore the correct way to create that route "manually" would be:

get "tareas/:id", to "tareas#show"

On the other hand, be careful that there are actions that should not be GET. It is very bad practice to modify a resource from a GET call. To create them you should use POST, to modify them PUT or PATCH and to destroy them DELETE. GET should always be safe and indeterminate and it is worthwhile to read a little more about this.

But again, all those routes that you use in your controller are created with the "resources: tasks". Therefore, your entire route file could be reduced to:

Rails.application.routes.draw do
  resources :tareas do
    member do
      put "finalizar"
    end
    resources :comentarios
  end
end

Notes: The route that is created to finish is slightly different from the one you create but it is more standard. Instead of being "tasks / finalize /: id" the path will be "tasks /: id / finalize". On the other hand, note that "end" I also put it as PUT and not GET. Therefore you should specify this method when you create your links or redirects. Example in a view:

<%= link_to "Finalizar", finalizar_tareas_path(@tarea), method: :put %>
    
answered by 15.08.2017 / 20:34
source
1

The action finalizar is after private , this means that it is not a public method and, therefore, is not found when trying to execute it.

Simply move that method ( finalizar ) before of the declaration of private methods (i.e. before private ).

This is how your controller should look:

class TareasController < ApplicationController
  def index
    @tareas = Tarea.select("id,titulo,descripcion").where(:activo=>true).order("id DESC")
  end

  def new
    @tarea = Tarea.new
  end

  def create
    @tarea = Tarea.new(tarea_params)
    @tarea.activo = true

    if @tarea.save
      redirect_to tareas_path, :notice => "La tarea se guardo correctamente"
    else
      render "new"
    end
  end

  def show
    @tarea = buscar_id
  end

  def buscar_id
    Tarea.find(params[:id])
  end

  def edit
    @tarea = Tarea.find(params[:id])
    @titulo = @tarea.titulo
    @descripcion = @tarea.descripcion
    @prioridad = @tarea.prioridad
    puts "tarea #{@tarea.titulo} descripcion #{@tarea.descripcion}"
  end

  def update
    @titulo = params[:tarea]["titulo"]
    @descripcion = params[:tarea]["descripcion"]
    @prioridad = params[:tarea]["prioridad"]
    @tarea = Tarea.find(params[:id])
    @tarea.titulo = @titulo
    @tarea.descripcion = @descripcion
    @tarea.prioridad = @prioridad

    if @tarea.save
      redirect_to tareas_path, :notice => "La tarea a sido modificado exitosamente"
    else
      render "edit"      
    end
  end

  def destroy
    @tarea = buscar_id
    if @tarea.destroy
      redirect_to tareas_path, :notice=> "la Tarea a sido eliminado correctamente"
    else
      redirect_to tareas_path, :notice=> "la tarea no ha sido eliminada"
    end
  end

  def finalizar
    @tarea = Tarea.find(params[:id])
    @tarea.activo = false

    if @tarea.update
      redirect_to tareas_path, :notice => "la tarea a finalizado"
    else
      redirect_to tareas_path, :notice => "la tarea NO  a finalizado"
    end
  end  

  private 
  def tarea_params
    params.require(:tarea).permit(:titulo, :descripcion, :prioridad)
  end
end

You will notice that I also deleted the first declaration private (just before buscar_id ) since it is unnecessary because you include it again below. If you want the buscar_id method to be private then move that method towards the end, after private .

Although it is possible that you add private methods before public methods (using private and public ) it is not recommended because your code tends to be less ordered and more difficult to update / debug; therefore it is best to declare all public methods first and then all private methods.

    
answered by 15.08.2017 в 18:52