diff --git a/app/controllers/expenses_controller.rb b/app/controllers/expenses_controller.rb new file mode 100644 index 0000000..2692f74 --- /dev/null +++ b/app/controllers/expenses_controller.rb @@ -0,0 +1,70 @@ +class ExpensesController < ApplicationController + before_action :set_expense, only: %i[ show edit update destroy ] + + # GET /expenses or /expenses.json + def index + @expenses = Expense.all + end + + # GET /expenses/1 or /expenses/1.json + def show + end + + # GET /expenses/new + def new + @expense = Expense.new + end + + # GET /expenses/1/edit + def edit + end + + # POST /expenses or /expenses.json + def create + @expense = Expense.new(expense_params) + + respond_to do |format| + if @expense.save + format.html { redirect_to expense_url(@expense), notice: "Expense was successfully created." } + format.json { render :show, status: :created, location: @expense } + else + format.html { render :new, status: :unprocessable_entity } + format.json { render json: @expense.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /expenses/1 or /expenses/1.json + def update + respond_to do |format| + if @expense.update(expense_params) + format.html { redirect_to expense_url(@expense), notice: "Expense was successfully updated." } + format.json { render :show, status: :ok, location: @expense } + else + format.html { render :edit, status: :unprocessable_entity } + format.json { render json: @expense.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /expenses/1 or /expenses/1.json + def destroy + @expense.destroy! + + respond_to do |format| + format.html { redirect_to expenses_url, notice: "Expense was successfully destroyed." } + format.json { head :no_content } + end + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_expense + @expense = Expense.find(params[:id]) + end + + # Only allow a list of trusted parameters through. + def expense_params + params.require(:expense).permit(:name, :amount, :pricing_type) + end +end diff --git a/app/helpers/expenses_helper.rb b/app/helpers/expenses_helper.rb new file mode 100644 index 0000000..1d50062 --- /dev/null +++ b/app/helpers/expenses_helper.rb @@ -0,0 +1,2 @@ +module ExpensesHelper +end diff --git a/app/models/expense.rb b/app/models/expense.rb new file mode 100644 index 0000000..15a9560 --- /dev/null +++ b/app/models/expense.rb @@ -0,0 +1,2 @@ +class Expense < ApplicationRecord +end diff --git a/app/views/expenses/_expense.html.erb b/app/views/expenses/_expense.html.erb new file mode 100644 index 0000000..6581cb7 --- /dev/null +++ b/app/views/expenses/_expense.html.erb @@ -0,0 +1,17 @@ +
+

+ Name: + <%= expense.name %> +

+ +

+ Amount: + <%= expense.amount %> +

+ +

+ Pricing type: + <%= expense.pricing_type %> +

+ +
diff --git a/app/views/expenses/_form.html.erb b/app/views/expenses/_form.html.erb new file mode 100644 index 0000000..543a3ef --- /dev/null +++ b/app/views/expenses/_form.html.erb @@ -0,0 +1,32 @@ +<%= form_with(model: expense) do |form| %> + <% if expense.errors.any? %> +
+

<%= pluralize(expense.errors.count, "error") %> prohibited this expense from being saved:

+ + +
+ <% end %> + +
+ <%= form.label :name, style: "display: block" %> + <%= form.text_field :name %> +
+ +
+ <%= form.label :amount, style: "display: block" %> + <%= form.text_field :amount %> +
+ +
+ <%= form.label :pricing_type, style: "display: block" %> + <%= form.text_field :pricing_type %> +
+ +
+ <%= form.submit %> +
+<% end %> diff --git a/app/views/expenses/edit.html.erb b/app/views/expenses/edit.html.erb new file mode 100644 index 0000000..75bab6f --- /dev/null +++ b/app/views/expenses/edit.html.erb @@ -0,0 +1,10 @@ +

Editing expense

+ +<%= render "form", expense: @expense %> + +
+ +
+ <%= link_to "Show this expense", @expense %> | + <%= link_to "Back to expenses", expenses_path %> +
diff --git a/app/views/expenses/index.html.erb b/app/views/expenses/index.html.erb new file mode 100644 index 0000000..a25f060 --- /dev/null +++ b/app/views/expenses/index.html.erb @@ -0,0 +1,14 @@ +

<%= notice %>

+ +

Expenses

+ +
+ <% @expenses.each do |expense| %> + <%= render expense %> +

+ <%= link_to "Show this expense", expense %> +

+ <% end %> +
+ +<%= link_to "New expense", new_expense_path %> diff --git a/app/views/expenses/new.html.erb b/app/views/expenses/new.html.erb new file mode 100644 index 0000000..17d6299 --- /dev/null +++ b/app/views/expenses/new.html.erb @@ -0,0 +1,9 @@ +

New expense

+ +<%= render "form", expense: @expense %> + +
+ +
+ <%= link_to "Back to expenses", expenses_path %> +
diff --git a/app/views/expenses/show.html.erb b/app/views/expenses/show.html.erb new file mode 100644 index 0000000..2262a0e --- /dev/null +++ b/app/views/expenses/show.html.erb @@ -0,0 +1,10 @@ +

<%= notice %>

+ +<%= render @expense %> + +
+ <%= link_to "Edit this expense", edit_expense_path(@expense) %> | + <%= link_to "Back to expenses", expenses_path %> + + <%= button_to "Destroy this expense", @expense, method: :delete %> +
diff --git a/config/routes.rb b/config/routes.rb index a125ef0..8a4ea4a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,5 @@ Rails.application.routes.draw do + resources :expenses # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. diff --git a/db/migrate/20240711175425_create_expenses.rb b/db/migrate/20240711175425_create_expenses.rb new file mode 100644 index 0000000..63d0f2b --- /dev/null +++ b/db/migrate/20240711175425_create_expenses.rb @@ -0,0 +1,12 @@ +class CreateExpenses < ActiveRecord::Migration[7.1] + def change + create_enum :pricing_types, ["fixed", "per_person"] + create_table :expenses, id: :uuid do |t| + t.string :name + t.decimal :amount + t.enum :pricing_type, enum_type: :pricing_types, default: "fixed", null: false + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index f913998..7774eec 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,8 +10,20 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 0) do +ActiveRecord::Schema[7.1].define(version: 2024_07_11_175425) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" + # Custom types defined in this database. + # Note that some types may not work with other database engines. Be careful if changing database. + create_enum "pricing_types", ["fixed", "per_person"] + + create_table "expenses", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "name" + t.decimal "amount" + t.enum "pricing_type", default: "fixed", null: false, enum_type: "pricing_types" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + end diff --git a/spec/models/expense_spec.rb b/spec/models/expense_spec.rb new file mode 100644 index 0000000..5ad50a3 --- /dev/null +++ b/spec/models/expense_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Expense, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end