IIC2143-2020-1 / proyecto

Repositorio para el proyecto semestral de IIC2143 Ingeniería de Software 2020-1
22 stars 8 forks source link

Form Select #130

Closed Gaonuk closed 4 years ago

Gaonuk commented 4 years ago

Tengo mi entidad Comuna, y la relacione con Usuario y Local, en usuario y local tengo belongs_to :comuna y en Comuna tengo has_many :locals y has_many :userss. A la hora de agregarle la comuna al usuario cuando uso sign_up de devise, uso un select al estilo drop down menu que tiene los valores de las distintas comunas disponibles para escoger, pero cuando pongo crear usuario, la comuna no se agrega al usuario o local, he probado de distintas formas pero el error que me aparece es "Comuna must exists"

valerojasm commented 4 years ago

Hola! Cuando uno hace submit del formulario se gatilla la acción create, la que si te fijas no sabe que debe guardar desde el field comuna (que por como lo describes empaqueta una instancia de Comuna en la request), el id de esta en el nuevo usuario que está creando. Por lo tanto, esto debes manejarlo desde el controlador en el método create, desempaquetando lo que viene en la request. Si te fijas en el sector private del controlador hay métodos que hacen esto para otras situaciones, tu tendrías que hacer algo similar del estilo:

def obtener_comuna
  @comuna = Comuna.find(params[:<nombre_del_field_segun_tu_ruta>])
end

(Ojo, esto también puedes ponerlo directamente en la acción, pero por seguridad se acostumbra que sea un método privado. Si decides hacerlo como te explico acá, luego debes agregarlo al before_action de la acción, que en este caso sería create.)

Luego, ya puedes guardar la comuna en tu usuario al momento del create, user.comuna = @comuna.

Ojalá te sirva. Saludos!

oscars810 commented 4 years ago

Hola, tengo el mismo problema e hice lo que dijiste pero me dice que user no existe. Busqué en internet soluciones y en general hacen esto:

    def posts_params
      params.require(:post).permit(:your_posts_params, :user_id)
    end

Pero tampoco me funcionó. Creo que es porque ahí guardan parametros pero no identidades, no sé en verdad.

Esto es lo que tengo actualmente en mi controlador:

before_action :obtener_comuna, :configure_sign_up_params, only: [:create]

def create
    super
    user.commune = @comuna
end

def obtener_comuna
   @comuna = Commune.find_by('nombre = ?', params[:commune])
end

Igual tengo la duda si eso funcionara y yo actualizo user.commune se hacen solo los cambios de poner el id de la comuna en la fila del respectivo usuario en la bdd?

Gaonuk commented 4 years ago

@valerojasm Muchas gracias por la respuesta y lo siento por responder tan tarde. Lo que yo quiero hacer no es pasar una instancia de Comuna por el select del form hacia el controller, quiero que el usuario escoja una comuna de las disponibles, en el select se muestran solo sus nombres y se pasa el valor de la id de esa comuna seleccionada para luego agregarlo a la tabla como user.comuna_id = "id de la comuna seleccionada". Lo que me pasa es que si pongo belongs_to en el user, entonces este tiene que existir a la hora de ser creado y me dice "Comuna must exist", pero al quitarlo y ver que pasa, me aparece

Parameters: {..., "user"=>{"nombre"=>"Holasd", "edad"=>"0023-12-31", "email"=>"l@l.cl", "telefono"=>"123123", "genero"=>"Hombre", "comuna_id"=>"9", "descripcion"=>"23", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Sign Up"}
Unpermitted parameter: :comuna_id

Este el codigo del select que uso para poder escoger una comuna:

<%= f.collection_select :comuna_id, Comuna.all, :id, :nombre, prompt: true, class: "form-control" %>

Aqui esta la funcion que utilizo para sanitizar los params pero al parecer no cambia nada

before_action :user_params, only: [:create]
private
def user_params
    params.require(:user).permit(:nombre, :edad, :email, :telefono, :genero,
                                 :descripcion, :comuna_id, :password, :password_confirmation)
  end
oscars810 commented 4 years ago

Al final lo logramos solucionar de otra forma, @Gaonuk si aún tienes el problema te puedo explicar como lo hicimos! 😄

Gaonuk commented 4 years ago

@oscars810 te lo agradeceria muchisimo! Llevo mucho tiempo con este problema y aun no se como solucionarlo!

benjastraub commented 4 years ago

@oscars810 si pudieras ponerlo acá por favor. Tengo el mismo problema

oscars810 commented 4 years ago

Ningun problema en dejarlo acá, así sirve para todos. 😄 Primero hay que poner en el controlador el nombre de la variable que va a enviar el form en la vista para que se agregue a la bdd. Esto se agrega en el sanitizador por lo que queda algo así:

def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up, keys: [:variable_form])
end

Luego, en el formulario colocamos un select que mostraba los nombres pero enviaba las id. Esto lo sacamos de la documentacion: https://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-select Ahí está muy bien explicado y no es para nada dificil.

Y eso es todo 😆... Porque al enviarse el id al controlador en una variable que tiene el mismo nombre que la columna a la cual se quiere agregar (:commune_id en nuestro caso), rails sabe que debe ir ahí y lo pone solo. Y como ya está hecha la relación del modelo usuario con comuna, puedes hacer perfectamente user.commune para obtener la comuna del usuario que quieras.

Espero les sirva mucho!

Gaonuk commented 4 years ago

@oscars810 Probe usar su metodo, pero al momento de crear un usuario no me aparece el Select para escoger una Comuna :cry: . Ademas, cual es la relacion que tienen entre el Usuario y la Comuna? Muchas gracias de antemano!

oscars810 commented 4 years ago

Nuestra relacion es: comuna has_many users y user belongs_to comuna.

Y lo del select fijate bien en tu codigo porque si no te aparece debe ser un problema en el orden que estas poniendo las etiquetas html.

Gaonuk commented 4 years ago

@oscars810 Tengo el select puesto de la siguiente forma:

<%= form_for(resource, as: resource_name, url: registration_path(resource_name),
                       html: {class: "box"}) do |f| %>

# Aqui tengo Nombre, mail, telefono, edad y genero 

<div class="field">
              <label for="comuna_id" class="label">Seleccione una comuna:</label>
              <% select("post", "comuna_id", Comuna.all.collect { |p| [p.nombre, p.id] }, {include_blank: true}) %>
</div>
# Aqui tengo Descripcion y la password 

<% end %>

Lo raro es que usando el select de esta manera,

<%= f.collection_select :comuna, Comuna.all, :id, :nombre, prompt: true, class: "form-control" %>

Si me aparecen las comunas, pero me sigue diciendo que el parametro :comuna_id no esta permitido a pesar de haber usado

def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up, keys: [:comuna_id])
end

No entiendo :sob:

oscars810 commented 4 years ago

Tres errores que veo a simple vista es que tienes select( ... ) y debería ser f.select( ... ) porque tienes que indicarle que el select es del form f. El otro error es en ("post", "comuna_id"... , ahí solo tienes que poner la variable que vas a enviar al controlador, es decir :comuna_id (que asumo que ese es el nombre de la columna en su tabla de usuarios y ese es el nombre de la variable que estas permitiendo en el controlador [y tiene que ir sin comillas]). Y el tercer error, es que en esa linea tienes que poner <%=%> para que aparezca en html.

Por ultimo, como dato, nosotros pusimos <div class="select">, pero no se que tanto influirá realmente.

Gaonuk commented 4 years ago

Ohh muchas gracias @oscars810! Ahi lo arregle y ahora el select si aparece! Pero lamentablemente sigo teniendo el problema de que no esta permitido el parametro :comuna_id

Gaonuk commented 4 years ago

@valerojasm Sigo teniendo el problema de

Unpermitted parameter: :comuna_id

y no se como solucionarlo, he buscado por todos lados, y he intentado muchas maneras de hacerlo, ya sea con

def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up, keys: [:comuna_id])
  end

o con

params.require(:user).permit(#aqui van los atributos del usuario, :comuna_id)

o haciendolo a traves de nested parametters pero nada me funciona. Este es uno de los links en los que me base para hacer el select y supuestamente deberia funcionar pero nop. :cry: https://levelup.gitconnected.com/rails-nested-forms-in-three-steps-5580f0ad0e

valerojasm commented 4 years ago

Hola @Gaonuk ! Mándame un mail a varojasm@uc.cl para poder ayudarte!