IIC2513 / Syllabus-2023-1

Repositorio oficial del curso IIC2513 Tecnologías y Aplicaciones Web 🎉👩‍💻👨‍💻
67 stars 8 forks source link

Restriccion Unique pero para un par de columnas... #114

Closed EleaTriesToCode closed 1 year ago

EleaTriesToCode commented 1 year ago

Holis !

En nuestro juego es importante controlar que dos cartas no pueden ser en una misma posicion en una ciudad de un jugador - tenemos una tabla con las cartas en las ciudades, que tiene como columnas el id del jugador, la posicion, y detalles de las cartas. Para traducir este problema, pensabamos aplicar un restriccion unique a la par de keys jugadorID y posicion... Pero después de muchos intentos con propuestas en stackoverflow todavia no lo hemos logrado :/

Por ejemplo, eso de abajo parece que no funciona :

image image

Ustedes tendrian unos tips sobre como hacer eso ? Quizas mejor usar de validaciones, pero no entiendo bien como dentro de una validacion la columna posicion hacer referencia a la otra columna jugadorID...

Cualquier tip seria muy agradecido ! :D

valeeeriquelme commented 1 year ago

Por la forma en que describes el problema asumo que están tratando de establecer una relación 1:1 entre las cartas y los jugadores. Osea, una carta puede pertenecer a un solo jugador y un jugador puede tener solo una carta (si no es así, no me hace sentido el unique).

Como es una relación entre dos modelos, me apoyaría de las asociaciones para definir esa relación. Te recomiendo esta documentación para ver como aplicar asociaciones hasOne belongsTo (https://medium.com/@andrewoons/how-to-define-sequelize-associations-using-migrations-de4333bf75a7). Esta guía toma como ejemplo la relación Customer y Order, que se parece a su caso, pero en este caso un customer si puede tener más de una order, así que cuidado con eso.

Para el caso de la posición, entiendo que este si es un atributo. En ese caso, ahí está bien hacerlo de la forma que muestras con unique, pero a nivel de endpoint (no de validación) agregaría una revisión para ver si hay otra carta en esa posición. Algo tipo, "findOne wehre position is (x,y)" y si hay una carta con esa posición, que no se permita la acción.

EleaTriesToCode commented 1 year ago

Hola ! Gracias por la repuesta :)

No lo he explicado con muchos detalles, porque no me parecia necesario para el problema, pero a modo de clarificación : no tenemos cartas en cuanto tales, ya que las generamos aleatoriamente cuando y dónde las necesitamos (eso permite hacer todo lo que el juego necesita sin tener que multiplicar tablas y asociaciones) - en vez de eso, solamente tenemos una tabla de cartas-en-la-ciuda dónde cada row viene con el id de un jugador, una posicion, y detalles de la carta (su precio y su tipo). Cada carta-en-la-ciudad pertenece a un jugador, un jugador tiene varias cartas-en-la-ciudad. Tenemos que decir por ende que en la tabla cartas-en-la-ciudad no se puede tener dos rows con un atributo id jugador y posicion iguales - o sea para un mismo jugador, hay dos rows o sea dos cartas en la misma posicion. No sé si lo hago más claro o más confuso ? A mi parecer la arquitectura de db que tenemos ahora nos permite hacer todo lo que queremos, de una manera que nos parecía muy facil. Espero que le hace sentido, y que no tenemos que cambiar la arquitectura de nuestra db ?

De todos modos, quizás la restricción sobre posición de hecho sería más facilmente arreglada en la API directamente, voy a intentar eso ! Gracias de nuevo :D

valeeeriquelme commented 1 year ago

Si, ahora es más claro. Enntiendo entonces que tienen una relación 1:n (un jugador tiene muchas cartas pero una carta puede ser solo de un jugador). No les digo que cambien la arquitectura, de hecho está bien como la definieron. El tema es que al ocupar unique en ambos atributos, están limitando a que en toda la tabla cartas-en-la-ciudad no pueda repetirse al atributo jugador, osea que un jugador solo podrá estar asociado a una carta, y no veo que eso responda a su arquitectura.

La sugerencia es que manejen las asociaciones de la forma en que aparece en la guías que les mandé (en particular hasmany y belongs to one). Ya que de esa forma estarán levantando correctamente la arquitectura que planteas y se evitará a nivel de bdd que una carta pueda ser asociada a más de un jugador.