diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb index de94a48..beccce4 100644 --- a/app/controllers/tasks_controller.rb +++ b/app/controllers/tasks_controller.rb @@ -4,21 +4,56 @@ class TasksController < ApplicationController before_action :fetch_task, only: %w[show edit update delete] def index - if params[:project] - @project = Project.find_by!(code: params[:project]) - @tasks = @project.tasks - else - @tasks = Task.all - end + @project = fetch_project + @tasks = if @project + @project.tasks + else + Task.all + end @tasks = @tasks.includes(:project) end def show; end + def new + @form = Tasks::Create.new(project_id: fetch_project&.id) + end + + def create + @form = Tasks::Create.new(params.expect(task: %i[project_id title description])) + if @form.perform + redirect_to tasks_path(project: @form.project) + else + render :new, status: :unprocessable_entity + end + end + + def edit + @form = Tasks::Update.new(id: @task.id, title: @task.title, description: @task.description) + end + + def update + @form = Tasks::Update.new(params.expect(task: %i[title description])) + + if @form.perform(@task) + redirect_to task_path(@task) + else + render :edit, status: :unprocessable_entity + end + end + + def delete; end + private + def fetch_project + return nil if params[:project].blank? + + Project.find_by!(code: params[:project]) + end + def fetch_task - @task = Task.find_by_full_number_or_id!(params[:id]) + @task = Task.includes(:project).find_by_full_number_or_id!(params[:id]) end end diff --git a/app/models/task.rb b/app/models/task.rb index deefbb9..3f42f7b 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -19,7 +19,7 @@ class Task < ApplicationRecord end def self.find_by_full_number_or_id!(number_or_id) - return find!(number_or_id) if number_or_id.is_a?(Numeric) || number_or_id =~ /\A\d+\z/ + return find(number_or_id) if number_or_id.is_a?(Numeric) || number_or_id =~ /\A\d+\z/ project_code, number = number_or_id.split('-') project = Project.find_by!(code: project_code.downcase) diff --git a/app/services/application_service.rb b/app/services/application_service.rb new file mode 100644 index 0000000..8112289 --- /dev/null +++ b/app/services/application_service.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class ApplicationService + include ActiveModel::Model + include ActiveModel::Attributes + + attr_reader :errors + + def perform + # Override this + end + + private + + def save(model) + model.save.tap { @errors = model.errors } + end +end diff --git a/app/services/tasks/create.rb b/app/services/tasks/create.rb new file mode 100644 index 0000000..1ec07ed --- /dev/null +++ b/app/services/tasks/create.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module Tasks + class Create < ApplicationService + attribute :project_id, :integer + attribute :title, :string + attribute :description, :string + + validates :project_id, :title, presence: true + + delegate :model_name, to: Task + + attr_reader :project, :task + + def perform + @project = Project.find(project_id) + + @task = @project.tasks.build(title:, description:, number: @project.next_task_number) + @task.save.tap { @errors = @task.errors } + end + end +end diff --git a/app/services/tasks/update.rb b/app/services/tasks/update.rb new file mode 100644 index 0000000..f61f195 --- /dev/null +++ b/app/services/tasks/update.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module Tasks + class Update < ApplicationService + attribute :id, :integer + attribute :title, :string + attribute :description, :string + + validates :title, presence: true + + delegate :model_name, to: Task + + def persisted? = true + + def perform(task) + @task = task + @id = task.id + @task.assign_attributes(title:, description:) + save @task + end + end +end diff --git a/app/views/tasks/edit.html.slim b/app/views/tasks/edit.html.slim new file mode 100644 index 0000000..7b4f831 --- /dev/null +++ b/app/views/tasks/edit.html.slim @@ -0,0 +1,13 @@ +h1 + | Editing task + =< @task.full_number + += form_with model: @form do |form| + .field + = form.label :title + = form.text_field :title + .field + = form.label :description + = form.rich_textarea :description + .submit + = form.submit 'Update task' diff --git a/app/views/tasks/new.html.slim b/app/views/tasks/new.html.slim new file mode 100644 index 0000000..49c9465 --- /dev/null +++ b/app/views/tasks/new.html.slim @@ -0,0 +1,14 @@ +h1 New task + += form_with model: @form do |form| + .field + = form.label :project_id + = form.select :project_id, Project.order(:name).map { |p| [p.name, p.id] } + .field + = form.label :title + = form.text_field :title + .field + = form.label :description + = form.rich_textarea :description + .submit + = form.submit 'Create task'