Explorar o código

La mitad del proyecto

cesarssh.dev@gmail.com hai 1 ano
achega
dbcd0a2ec1
Modificáronse 13 ficheiros con 302 adicións e 0 borrados
  1. 34 0
      Dockerfile
  2. 24 0
      db/connection.go
  3. 53 0
      docker-compose.yml
  4. 14 0
      go.mod
  5. 18 0
      go.sum
  6. 10 0
      info.txt
  7. 2 0
      initdb/create_db.sql
  8. 36 0
      main.go
  9. 10 0
      models/Categoria.go
  10. 14 0
      models/Estudiante.go
  11. 28 0
      routes/categoria.route.go
  12. 52 0
      routes/estudiante.route.go
  13. 7 0
      routes/index.route.go

+ 34 - 0
Dockerfile

@@ -0,0 +1,34 @@
+# Build Stage
+FROM golang:1.23 AS builder
+
+# Establece el directorio de trabajo en el contenedor
+WORKDIR /app
+
+# Copia solo los archivos necesarios para la instalación de dependencias
+COPY go.mod go.sum ./
+
+# Instala las dependencias
+RUN go mod download
+
+# Copia el resto de los archivos de la aplicación
+COPY . .
+
+# Cambia al directorio donde está el archivo principal
+#WORKDIR /app
+
+# Compila la aplicación (especificando la ruta al archivo principal)
+RUN go build -o /app/api-estudiantes main.go
+
+
+
+# Final Stage: Usa una imagen base más ligera
+FROM alpine:latest
+
+# Establece el directorio de trabajo
+WORKDIR /app
+
+# Copia el binario construido desde la etapa de construcción
+COPY --from=builder /app/api-estudiantes /app/api-estudiantes
+
+# Comando para ejecutar la aplicación
+CMD ["./api-estudiantes"]

+ 24 - 0
db/connection.go

@@ -0,0 +1,24 @@
+package db
+
+import (
+	"log"
+
+	"gorm.io/driver/mysql"
+	"gorm.io/gorm"
+)
+
+// Config to connect mySQL
+var DSN = "root:password@tcp(127.0.0.1:3306)/estudiantes?charset=utf8mb4&parseTime=True&loc=Local"
+
+var DB *gorm.DB
+
+func DBConnection() {
+	var error error
+	DB, error = gorm.Open(mysql.Open(DSN), &gorm.Config{})
+
+	if error != nil {
+		log.Fatal(error)
+	} else {
+		log.Println("DB connected")
+	}
+}

+ 53 - 0
docker-compose.yml

@@ -0,0 +1,53 @@
+version: '3.7'
+
+services:
+  app:
+    container_name: go-api
+    build:
+      context: .
+      dockerfile: Dockerfile
+    image: go-api
+    ports:
+      - 8080:8080
+    environment:
+      - DB_HOST=mysql
+      - DB_PORT=3306
+      - DB_USER=root
+      - DB_PASSWORD=password
+      - DB_NAME=estudiantes
+    depends_on:
+      mysql:
+        condition: service_healthy
+    networks:
+      - go-network
+
+  mysql:
+    container_name: go-mysql
+    image: mysql:latest
+    environment:
+      - MYSQL_ROOT_PASSWORD=password
+      - MYSQL_USER=root
+      - MYSQL_PASSWORD=password 
+      - MYSQL_DATABASE=estudiantes
+
+    volumes:
+      - dbdata:/var/lib/mysql
+      - ./initdb:/docker-entrypoint-initdb.d
+    ports:
+      - "3306:3306"
+
+    networks:
+      - go-network
+    healthcheck:
+      test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ]
+      interval: 10s
+      timeout: 5s
+      retries: 3
+
+volumes:
+  dbdata:
+
+
+networks:
+  go-network:
+    driver: bridge

+ 14 - 0
go.mod

@@ -0,0 +1,14 @@
+module github.com/CesarSSH/api-estudiantes
+
+go 1.23.1
+
+require (
+	filippo.io/edwards25519 v1.1.0 // indirect
+	github.com/go-sql-driver/mysql v1.8.1 // indirect
+	github.com/gorilla/mux v1.8.1 // indirect
+	github.com/jinzhu/inflection v1.0.0 // indirect
+	github.com/jinzhu/now v1.1.5 // indirect
+	golang.org/x/text v0.19.0 // indirect
+	gorm.io/driver/mysql v1.5.7 // indirect
+	gorm.io/gorm v1.25.12 // indirect
+)

+ 18 - 0
go.sum

@@ -0,0 +1,18 @@
+filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
+filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
+github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
+github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
+github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
+github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
+golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
+gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
+gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
+gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
+gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
+gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=

+ 10 - 0
info.txt

@@ -0,0 +1,10 @@
+#REPOS UTILIZADOS
+
+go get -u gorm.io/driver/mysql
+go get -u github.com/gorilla/mux
+
+#Comandos basicos
+docker-compose up --build
+docker-compose up -d
+docker exec -it go-mysql mysql -u root -p  //ENTRAR AQUI Y CREAR LA BASE DE DATOS CON EL NOMBRE estudiantes
+go run .

+ 2 - 0
initdb/create_db.sql

@@ -0,0 +1,2 @@
+-- CREATE DATABASE IF NOT EXISTS `estudiantes`;
+CREATE DATABASE IF NOT EXISTS estudiantes;

+ 36 - 0
main.go

@@ -0,0 +1,36 @@
+package main
+
+import (
+	"net/http"
+
+	"github.com/CesarSSH/api-estudiantes/db"
+	"github.com/CesarSSH/api-estudiantes/models"
+	"github.com/CesarSSH/api-estudiantes/routes"
+	"github.com/gorilla/mux"
+)
+
+func main() {
+	//Execute this func to connect my DB
+	db.DBConnection()
+
+	//Migrations
+	db.DB.AutoMigrate(models.Estudiante{})
+	db.DB.AutoMigrate(models.Categoria{})
+
+	//Create a new router
+	router := mux.NewRouter()
+
+	//Default response
+	router.HandleFunc("/api/v1/", routes.HomeHandler)
+
+	//Estudiantes
+	router.HandleFunc("/api/v1/estudiantes", routes.GetEstudiantesHandler).Methods("GET")
+	router.HandleFunc("/api/v1/estudiante", routes.PostEstudianteHandler).Methods("POST")
+
+	//Categorias
+	router.HandleFunc("/api/v1/categorias", routes.GetCategoriasHandler).Methods("GET")
+	router.HandleFunc("/api/v1/categoria", routes.PostCategoriaHandler).Methods("POST")
+
+	// Start the server
+	http.ListenAndServe(":8080", router)
+}

+ 10 - 0
models/Categoria.go

@@ -0,0 +1,10 @@
+package models
+
+import "gorm.io/gorm"
+
+type Categoria struct{
+	gorm.Model
+	Desc string `gorm:"type: varchar(100);not null;unique_index" json:"desc"`
+	Estudiantes []Estudiante `gorm:"foreignKey:CategoriaID"` // Relación inversa
+	
+}

+ 14 - 0
models/Estudiante.go

@@ -0,0 +1,14 @@
+package models
+
+import "gorm.io/gorm"
+
+type Estudiante struct {
+	gorm.Model
+	Nombre      string    `gorm:"not null" json:"nombre"`
+	ApellidoP   string    `gorm:"not null" json:"apellido_p"`
+	ApellidoM   string    `gorm:"not null" json:"apellido_m"`
+	Sexo        string    `gorm:"not null" json:"sexo"`
+	FechaN      string    `gorm:"not null" json:"fecha_n"`
+	CategoriaID uint      `json:"categoria_id"`           // Field to store
+	Categoria   Categoria `gorm:"foreignKey:CategoriaID"` // Relation with Attribute
+}

+ 28 - 0
routes/categoria.route.go

@@ -0,0 +1,28 @@
+package routes
+
+import (
+	"encoding/json"
+	"net/http"
+
+	"github.com/CesarSSH/api-estudiantes/db"
+	"github.com/CesarSSH/api-estudiantes/models"
+)
+
+func GetCategoriasHandler(w http.ResponseWriter, r *http.Request) {
+	var categorias []models.Categoria
+	db.DB.Find(&categorias)
+	json.NewEncoder(w).Encode(&categorias)
+}
+
+func PostCategoriaHandler(w http.ResponseWriter, r *http.Request) {
+	var categoria models.Categoria
+	json.NewDecoder(r.Body).Decode(&categoria)
+	createdAtt := db.DB.Create(&categoria)
+	err := createdAtt.Error
+	if err != nil {
+		w.WriteHeader(http.StatusBadRequest) //Error 400
+		w.Write([]byte(err.Error()))
+	}
+	json.NewEncoder(w).Encode(&categoria)
+
+}

+ 52 - 0
routes/estudiante.route.go

@@ -0,0 +1,52 @@
+package routes
+
+import (
+	"encoding/json"
+	"net/http"
+
+	"github.com/CesarSSH/api-estudiantes/db"
+	"github.com/CesarSSH/api-estudiantes/models"
+	"gorm.io/gorm"
+)
+
+func GetEstudiantesHandler(w http.ResponseWriter, r *http.Request) {
+	var estudiantes []models.Estudiante
+	db.DB.Find(&estudiantes)
+	json.NewEncoder(w).Encode(&estudiantes)
+}
+
+func PostEstudianteHandler(w http.ResponseWriter, r *http.Request) {
+	var estudiante models.Estudiante
+	err := json.NewDecoder(r.Body).Decode(&estudiante)
+	if err != nil {
+		w.WriteHeader(http.StatusBadRequest) // Error 400
+		w.Write([]byte("Error decoding JSON: " + err.Error()))
+		return
+	}
+
+	// Verifica si la CategoriaID existe
+	var categoria models.Categoria
+	result := db.DB.First(&categoria, estudiante.CategoriaID) // Busca la categoria por ID
+	if result.Error != nil {
+		if result.Error == gorm.ErrRecordNotFound {
+			w.WriteHeader(http.StatusNotFound) // Error 404
+			w.Write([]byte("El ID de esa categoria no existe"))
+			return
+		}
+		// Si hay un error diferente, maneja el error
+		w.WriteHeader(http.StatusInternalServerError) // Error 500
+		w.Write([]byte("Error en la query de la DB: " + result.Error.Error()))
+		return
+	}
+
+	// Si el AttributeID existe, crea el nuevo estudiante
+	estudianteCreado := db.DB.Create(&estudiante)
+	if estudianteCreado.Error != nil {
+		w.WriteHeader(http.StatusBadRequest) // Error 400
+		w.Write([]byte("Error al crear el estudiante: " + estudianteCreado.Error.Error()))
+		return
+	}
+
+	w.WriteHeader(http.StatusCreated)      // Código 201
+	json.NewEncoder(w).Encode(&estudiante) // Devuelve el estudiante creado
+}

+ 7 - 0
routes/index.route.go

@@ -0,0 +1,7 @@
+package routes
+
+import "net/http"
+
+func HomeHandler(w http.ResponseWriter, r *http.Request) {
+	w.Write([]byte("El servidor funciona"))
+}