¿Cómo obtengo un controlador de mesa para mostrar una asociación de clave extranjera? [Rubymine 2020.2.3, Ruby.2.7.2p137, gem 3.1.2]

Estoy cerca del plazo para un proyecto universitario (3 semanas) y he encontrado varios problemas. Al ser un curso de proyecto, no siempre puedo referirme a mi tutor.

Anteriormente He hecho una pregunta que ha proporcionado soluciones para una mesa que no tenía una llave extranjera, gracias a la gente amable en este sitio, finalmente se resuelve. Una cuestión más larga es conseguir mesa para trabajar con una llave extranjera, una de estas tablas nunca mostrará un único registro de datos en el índice.

Este es el método Crear del controlador de mesa 'Shipment' donde trato de crear una asociación al 'Courier' al que pertenece el Shipment_to y el Courier tiene_muy de. Las siguientes líneas son según las instrucciones del documento de mi curso:

 @cour_id=params[:shipment][:courier_id]
@courier=Courier.find(@cour_id)
@shipment=Shipment.new(params.require(:shipment).permit(:tracking_number, :shipment_date))
@shipment.courier<< @courier
@shipment.save
redirect_to shipment_path(@shipment)
@shipment=Shipment.new(shipment_new_path)
if @shipment.save
  redirect_to(:controller=>'shipment' ,:action=>'index')
else
  render('new')
end
end

Las asociaciones parecen ser necesarias porque una de las formas en el envío/new.erb.html es una caída de un conjunto de registros de Courier de una de sus columnas de mesa. Lo que parece mostrar desde esa forma dentro de esa página.

El tema que encuentro es en la línea '@shipment.courier Identificado @courier', el 'traducido' se trata como un método indefinido para nil:NilClass. He probado variaciones de esta línea de código (@shipment.couriers..., @shipment.courier.id...), pero no parece marcar la diferencia.

screencap del error

Sospecho que un problema más apremiante está en juego desde esta tabla en particular, noté que incluso desde el fondo, la mesa no parecería guardar nuevos registros. Aunque no hay nada particularmente diferente de esta tabla en comparación con otros. Inicialmente he atribuido que es incapaz de pasar datos debido a una desalineación entre las asociaciones de mesa, ahora lo interpreto como una cuestión de no poder funcionar sin estar adecuadamente conectado con el id de la tabla Courier.

La pregunta es, ¿cómo puedo hacer que las asociaciones funcionen?

Pregunta hecha hace 3 años, 4 meses, 24 días - Por compilercaptain


3 Respuestas:

  • Esto es realmente sólo un recurso estándar de nido de la época que estás describiendo. Realmente no sé qué hacer del conjunto de código en su pregunta - pero la forma de Rails de hacer esto sería:

    resources :couriers do
      resources :shipments, 
         only: [:index, :new, :create]
    end
    
    class ShipmentsController < ApplicationController
      # use callbacks to avoid repitition
      before_action :set_courier, only: [:new, :create, :index]
    
      # GET /couriers/1/shipments
      def index
        @shipments = @courier.shipments
      end
    
      # GET /couriers/1/shipments/new
      def new
        @shipment = @courier.shipments.new 
      end
    
      # POST /couriers/1/shipments
      def create
        @shipment = @courier.shipments.new(shipment_params)
        if @shipment.save
          # shorthand for courier_shipments_path(@courier)
          redirect_to([@courier, :shipments])
        else
          render(:new)
        end
      end
    
      private
    
      # use a private method instead of repeating yourself
      def shipment_params
        params.require(:shipment)
              .permit(:tracking_number, :shipment_date)
      end
    
      def set_courier
        @courier = Courier.find(params[:courier_id])
      end
    end
    
    # app/views/shipments/new.html.erb
    <%= form_with(model: [@courier, @shipment]) do |f| %>
      
    <%= f.label :tracking_number %> <%= f.text_field :tracking_number %>
    <%= f.label :delivery_date %> <%= f.date_field :delivery_date %>
    <%= f.submit %>
    <% end %>

    Respondida el Dec 21, 2020 a las 08:00 - por codesculptor3f6e

    Votos positivos: 0 | Votos negativos: 0

  • El error que estás experimentando ("undefined method courier' for nil:NilClass") indica que el objeto@shipmentes nulo y, por lo tanto, no tiene el métodocourier` disponible. Esto suele ocurrir cuando el objeto no se ha inicializado correctamente o no se ha asignado a la variable antes de intentar acceder a sus atributos o métodos.

    En tu código, parece que estás creando un nuevo objeto Shipment, pero luego intentas asociar un Courier a ese objeto sin haber asignado ningún valor a la variable @shipment. La línea @cour_id=params[:shipment][:courier_id] asigna el valor del courier_id recibido en los parámetros, lo cual es correcto, pero luego necesitas utilizar este valor para asociar el Courier al Shipment.

    Te recomendaría ajustar tu código de la siguiente manera:

    ruby
    @shipment = Shipment.new(params.require(:shipment).permit(:tracking_number, :shipment_date))
    @courier = Courier.find(params[:shipment][:courier_id])
    @shipment.courier = @courier
    
    if @shipment.save
      redirect_to shipment_path(@shipment)
    else
      render 'new'
    end
    

    En este código, primero creas un nuevo objeto Shipment con los parámetros permitidos. Luego, encuentras el objeto Courier correspondiente al courier_id recibido y lo asignas al atributo courier del objeto @shipment. Finalmente, guardas el objeto @shipment y rediriges según el resultado.

    Asegúrate de que la asociación entre Shipment y Courier esté correctamente definida en los modelos correspondientes para poder acceder a los métodos de asociación, como courier. Con estos ajustes, deberías poder establecer la asociación correctamente y guardar los registros de manera adecuada. ¡Espero que esto te ayude a solucionar el problema!

    Respondida el Dec 22, 2020 a las 08:01 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Problema con la asociación

    La línea @shipment.courier << @courier intenta agregar un objeto Courier a una asociación has_many, pero la asociación courier en el modelo Shipment está definida como has_one. Para una asociación has_one, debes usar @shipment.courier = @courier para asignar el objeto Courier.

    Problema al guardar registros

    Si la tabla Shipment no puede guardar nuevos registros, podría deberse a:

    Validaciones fallidas: Verifica las validaciones definidas en el modelo Shipment para asegurarte de que los campos obligatorios estén presentes y los valores estén dentro del rango permitido. Problemas de asociación: Asegúrate de que las asociaciones entre Shipment y Courier estén configuradas correctamente tanto en el modelo Shipment como en el modelo Courier. Problemas de base de datos: Verifica la configuración de tu base de datos para asegurarte de que la tabla Shipment tenga permisos de escritura y que no haya restricciones que impidan insertar datos.

    Solución

    Para resolver estos problemas, intenta lo siguiente:

    • Cambia `@shipment.courier << @courier` a `@shipment.courier = @courier` para establecer correctamente la asociación `has_one`.
    • Verifica las validaciones del modelo `Shipment` y asegúrate de que se cumplan.
    • Revisa las asociaciones en los modelos `Shipment` y `Courier` para asegurarte de que estén configuradas correctamente.
    • Verifica la configuración de tu base de datos para asegurarte de que la tabla `Shipment` tenga permisos de escritura y que no haya restricciones que impidan insertar datos.

    Código actualizado*

    ruby
    @cour_id = params[:shipment][:courier_id]
    @courier = Courier.find(@cour_id)
    @shipment = Shipment.new(params.require(:shipment).permit(:tracking_number, :shipment_date))
    @shipment.courier = @courier
    @shipment.save
    redirect_to shipment_path(@shipment)
    @shipment = Shipment.new(shipment_new_path)
    if @shipment.save
      redirect_to(:controller => 'shipment', :action => 'index')
    else
      render('new')
    end
    

    Respondida el Dec 22, 2020 a las 08:10 - por Gemini

    Votos positivos: 0 | Votos negativos: 0