Home Posts Post Search Tag Search

Game Site Journal - 01
Published on: 2025-04-07 Tags: elixir, Blog, Side Project, LiveView, Game Site, Ecto

This will be a project that will use LiveView and Ecto to store data for each game that I create. Right off the bat I created Accounts, Games, Scores Ecto tables. These at the moment will store:

mix phx.gen.auth Accounts User users

Accounts: User account info, password, etc

mix phx.gen.live Games Game games name:text

Games: Names of all the games

mix phx.gen.live Scores Score scores score:integer

Scores: All the scores for a user with key references to Accounts:id and Games:id

defmodule GameSite.Repo.Migrations.CreateScores do
  use Ecto.Migration

  def change do
    create table(:scores) do
      add :score, :integer
      add :user_id, references(:users, on_delete: :delete_all)
      add :game_id, references(:games, on_delete: :delete_all)

      timestamps(type: :utc_datetime)
    end
  end
end

This should be enough to be sure that I can store game data. This might need to change later if I find that I’m storing too much or not enough.

We now need to set all the schema for the tables.

Scores:

defmodule GameSite.Scores.Score do
  use Ecto.Schema
  import Ecto.Changeset

  schema "scores" do
    field :score, :integer
    belongs_to :game, GameSite.Games.Game
    belongs_to :user, GameSite.Accounts.User

    timestamps(type: :utc_datetime)
  end

  @doc false
  def changeset(score, attrs) do
    score
    |> cast(attrs, [:score, :user_id, :game_id])
    |> validate_required([:score, :user_id, :game_id])
    |> foreign_key_constraint(:game_id)
    |> foreign_key_constraint(:user_id)
  end
end

Games:

defmodule GameSite.Games.Game do
  use Ecto.Schema
  import Ecto.Changeset

  schema "games" do
    field :name, :string

    has_many :scores, GameSite.Scores.Score
    timestamps(type: :utc_datetime)
  end

  @doc false
  def changeset(game, attrs) do
    game
    |> cast(attrs, [:name])
    |> validate_required([:name])
  end
end

This will ensure that we set all the relationships as needed. This doesn’t, however, set the needed values for User.id in all the Score forms. For this to be implemented, I need to be sure to mount the current user. To do so we need to add the following to the router.ex:

scope "/", GameSiteWeb do
  ...
  live_session :scores, on_mount: [{GameSiteWeb.UserAuth, :mount_current_user}] do
    # all your routes
  end
end

This allows you to add current_user={@current_user} to the <.modal ...> at the bottom of all the forms that will need a user.id for a changeset.

Now that is done we can start to work on a few games.