Pregunta

Tengo una entidad Usuario que tiene un campo actual ubicación (ciudad y país). Para mantener esta información que he creado una entidad llamada Localización cuales has_many usuarios.

No estoy del todo seguro de si debo poner en el modelo de usuario "has_one" o "belongs_to", pero por lo que he leído si quería tener la clave externa de la ubicación que debo poner "belongs_to". También quiero ser capaz de editar del usuario Ubicación actual al editar el usuario. así que estoy usando atributos anidados. Pero cuando edito el usuario termino añadiendo una nueva ubicación cada vez sin tener que asociar al usuario que se ha modificado. ¿Me puedes ayudar?

Mi código es el siguiente:

#User Model
class User < ActiveRecord::Base
  ## Relationships
  belongs_to :current_location, :class_name => 'Location'
  accepts_nested_attributes_for :current_location
end

#Location Model
class Location < ActiveRecord::Base
  #Relationship
  has_many :users
end

# part of the _form_edit.haml
- form_edit.fields_for :current_location do |location_form|
  = location_form.label :location, "Current Location"
  = location_form.text_field :location

#Application Helper
#nested attributes for user and location
def setup_user(user)
  returning(user) do |u|
    u.build_current_location if u.current_location.nil?
  end
end

#in the user controller (added after edit)
def update
    @user = @current_user
    if @user.update_attributes(params[:user])
      flash[:notice] = "Account updated!"
      redirect_to account_url
    else
      render :action => :edit
    end
  end
¿Fue útil?

Solución

El problema exacto que está enfrentando, como otros han apuntado a cabo es que el controlador no está recibiendo el identificador de ubicación, ya que debería. A mi me parece se está pasando el ID de la población a través del parámetro incorrecto. Por desgracia, un ID de ubicación no existe en un nuevo disco, así que esto no es posible en el formulario.

Su problema se deriva de la utilización accepts_nested_attributes_for en una relación belongs_to. El comportamiento no está claramente definido. Esto parece ser un error documentado. Por lo que el accepts_nested_attributes_for debe estar en una cuenta con uno o tiene muchos lados de una relación.

Estas son algunas soluciones posibles:

  1. Mover El accepted_nested_attributes_for al modelo Ubicación y construir sus formas al revés.

    -form_for @location do |location_form|
     ...
     =location_form.fields_for @user do |user_form|
       ....
    

    Desafortunadamente esto no permite una forma lógica de presentación de la información. Y hace editando el derecho de usuario difícil.

  2. El uso de un modelo de unirse y hacer una tiene uno:. Través de la relación

    Sinceramente no estoy seguro de lo bien accept_nested_attributes_for obras con un: a través de la relación, pero sin duda va a resolver su problema con la vinculación de registros

  3. .
  4. Ignorar accepts_nested_attributes_for y manejar la asociación en el controlador de la manera antigua.

    En realidad mantener el accepts_nested_attributes_for. Proporciona algunos métodos de conveniencia a mano, sólo que no permitan que se quede a las update_attributes / crear comunicado.

    def update 
      @user = @current_user 
      completed = false
      location_params = params[:user].delete(:current_location_attributes)
    
      User.transaction do
        @location = Location.find_or_create_by_id(location_params)
        @user.update_attributes(params[:user]) 
        @user.current_location = @location
        @user.save!
        completed = true
      end
      if completed
        flash[:notice] = "Account updated!" redirect_to account_url 
      else 
        render :action => :edit 
      end
    end
    

Los campos de poblará un campo id en el hash current_location_attributes automáticamente, si no es la creación de una nueva ubicación. Sin embargo, find_or_create_by_id, requiere una: la entrada id en el hash para que funcione. Se va a crear con una identificación correcta de auto incrementa si el identificador no está en la base de datos. Si va a crear una nueva ubicación que tendrá que añadirlo. Más fácil para añadirlo a la forma con =location_form.hidden_field :id, 0 unless current\_location.new\_record?.

Sin embargo, es posible que desee reducir en la creación lugar duplicado, y cambiar la línea Location.find_or_create_by_id a Location.find_or_create_by_location. Esto también va a reducir los errores de validaciones fallidas singularidad.

Otros consejos

no proporcionan Identificación del atributo anidado. Así carriles piensa que es una nueva.

- form_edit.fields_for :current_location do |location_form|
    = location_form.label :location, "Current Location"
    = location_form.text_field :location
    = location_form.hidden_field :id unless location_form.new_record?

No estoy seguro si la respuesta anterior es realmente correcto. Lo que necesita es especificar el ID de usuario para la ubicación, no la ubicación en sí.

- form_edit.fields_for :current_location do |location_form|
  = location_form.label :location, "Current Location"
  = location_form.text_field :location
  = location_form.hidden_field :user_id

Por defecto belongs_to :current_location, :class_name => 'Location' esperará que la tabla tiene un campo Users current_location_id. Una vez que tenga esto, usted debe ser capaz de hacer algo como:

@user = @current_user
@user.update_attributes(params[:user])

@location = @user.current_location or @user.build_current_location
@location.update_attributes(params[:location]) 

@user.current_location.save!
@user.save!
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top