From 3ef19093ad7a55975079541a528a078cd2debfda Mon Sep 17 00:00:00 2001 From: Sarah-Jeanne <> Date: Thu, 7 Mar 2024 21:11:24 -0500 Subject: [PATCH 1/4] created label model for files --- app/models/label.rb | 2 ++ db/migrate/20240308014217_create_labels.rb | 10 ++++++++++ db/schema.rb | 9 ++++++++- spec/factories/labels.rb | 5 +++++ spec/models/label_spec.rb | 5 +++++ 5 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 app/models/label.rb create mode 100644 db/migrate/20240308014217_create_labels.rb create mode 100644 spec/factories/labels.rb create mode 100644 spec/models/label_spec.rb diff --git a/app/models/label.rb b/app/models/label.rb new file mode 100644 index 00000000..73f1ac6e --- /dev/null +++ b/app/models/label.rb @@ -0,0 +1,2 @@ +class Label < ApplicationRecord +end diff --git a/db/migrate/20240308014217_create_labels.rb b/db/migrate/20240308014217_create_labels.rb new file mode 100644 index 00000000..be1687ef --- /dev/null +++ b/db/migrate/20240308014217_create_labels.rb @@ -0,0 +1,10 @@ +class CreateLabels < ActiveRecord::Migration[7.1] + def change + create_table :labels do |t| + t.string :name, null: false + t.string :color, null: false + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index ff309a73..2864c48a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_11_27_001950) do +ActiveRecord::Schema[7.1].define(version: 2024_03_08_014217) do create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "name", null: false t.string "record_type", null: false @@ -47,6 +47,13 @@ t.datetime "archived_at", precision: nil end + create_table "labels", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.string "name", null: false + t.string "color", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "printer_jobs", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "name" t.bigint "printer_id", null: false diff --git a/spec/factories/labels.rb b/spec/factories/labels.rb new file mode 100644 index 00000000..016c08c4 --- /dev/null +++ b/spec/factories/labels.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :label do + + end +end diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb new file mode 100644 index 00000000..399031db --- /dev/null +++ b/spec/models/label_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Label, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end From ebdcdbc88d8ae52a440e7663175cec8727497cbe Mon Sep 17 00:00:00 2001 From: Sarah-Jeanne <> Date: Mon, 11 Mar 2024 11:37:48 -0400 Subject: [PATCH 2/4] adding validation, factory and unit tests for labels --- app/models/label.rb | 2 ++ spec/factories/labels.rb | 3 ++- spec/models/label_spec.rb | 43 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/app/models/label.rb b/app/models/label.rb index 73f1ac6e..b51c33c2 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -1,2 +1,4 @@ class Label < ApplicationRecord + validates :name, presence: true, uniqueness: true + validates :color, presence: true, format: { with: /\A#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})\Z/, message: "color should be an hex" } end diff --git a/spec/factories/labels.rb b/spec/factories/labels.rb index 016c08c4..84c6cbc4 100644 --- a/spec/factories/labels.rb +++ b/spec/factories/labels.rb @@ -1,5 +1,6 @@ FactoryBot.define do factory :label do - + name { 'My red label' } + color { '#ff0000' } end end diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb index 399031db..84509940 100644 --- a/spec/models/label_spec.rb +++ b/spec/models/label_spec.rb @@ -1,5 +1,46 @@ require 'rails_helper' RSpec.describe Label, type: :model do - pending "add some examples to (or delete) #{__FILE__}" + let(:label) { build(:label) } + + it 'has a valid factory' do + expect(label).to be_valid + end + + describe '#name' do + subject { label.name } + + it { is_expected.to eq 'My red label' } + end + + describe '#color' do + subject { label.color } + + it { is_expected.to eq '#ff0000' } + end + + it 'has a valid name' do + expect(Label.new(name: nil, color: '#ffffff')).to_not be_valid + expect(Label.new(name: '', color: '#ffffff')).to_not be_valid + expect(Label.new(color: '#ffffff')).to_not be_valid + end + + it 'has a unique name' do + Label.create(name: 'My yellow label', color: '#0000ff') # same as create(:label, name: 'My yellow label', color: '#0000ff') + duplicate_label = Label.new(name: 'My yellow label', color: '#00f') + expect(duplicate_label).to_not be_valid + end + + it 'has a valid color format' do + expect(Label.new(name: 'my label')).to_not be_valid + expect(Label.new(name: 'my label', color: '')).to_not be_valid + expect(Label.new(name: 'my label', color: nil)).to_not be_valid + expect(Label.new(name: 'my label', color: 'green')).to_not be_valid + expect(Label.new(name: 'my label', color: '123456')).to_not be_valid + expect(Label.new(name: 'my label', color: '#1234')).to_not be_valid + expect(Label.new(name: 'my label', color: '#gg00gg')).to_not be_valid + expect(Label.new(name: 'my label', color: 'rgb(0, 155, 0)')).to_not be_valid + expect(Label.new(name: 'my label', color: '#ff00ff')).to be_valid + expect(Label.new(name: 'my label', color: '#f0f')).to be_valid + end end From 184b5960eb5f6b5bae5aa1768f61532b6b0a1dc7 Mon Sep 17 00:00:00 2001 From: Sarah-Jeanne <> Date: Tue, 12 Mar 2024 20:17:20 -0400 Subject: [PATCH 3/4] added unit tests for FileLabel --- app/models/file_label.rb | 8 ++++++++ app/models/file_record.rb | 2 ++ app/models/label.rb | 3 +++ db/migrate/20240311162807_create_file_labels.rb | 10 ++++++++++ db/schema.rb | 13 ++++++++++++- .../{file_manager/files.rb => file_records.rb} | 4 ++++ spec/factories/labels.rb | 4 ++++ .../file_spec.rb => file_record_spec.rb} | 15 +++++++++++++++ spec/models/label_spec.rb | 15 +++++++++++++++ 9 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 app/models/file_label.rb create mode 100644 db/migrate/20240311162807_create_file_labels.rb rename spec/factories/{file_manager/files.rb => file_records.rb} (89%) rename spec/models/{file_manager/file_spec.rb => file_record_spec.rb} (86%) diff --git a/app/models/file_label.rb b/app/models/file_label.rb new file mode 100644 index 00000000..b1e7125b --- /dev/null +++ b/app/models/file_label.rb @@ -0,0 +1,8 @@ +class FileLabel < ApplicationRecord + belongs_to :file_record + belongs_to :label + + validates :file_record, presence: true + validates :label, presence: true + validates :file_record_id, uniqueness: { scope: :label_id } +end diff --git a/app/models/file_record.rb b/app/models/file_record.rb index c4c72cc1..5567ef3e 100644 --- a/app/models/file_record.rb +++ b/app/models/file_record.rb @@ -3,6 +3,8 @@ class FileRecord < ApplicationRecord has_one_attached :file has_many :jobs, class_name: 'Printer::Job', as: :executable, dependent: :nullify + has_many :file_labels + has_many :labels, through: :file_labels validates :file, presence: true diff --git a/app/models/label.rb b/app/models/label.rb index b51c33c2..34832391 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -1,4 +1,7 @@ class Label < ApplicationRecord validates :name, presence: true, uniqueness: true validates :color, presence: true, format: { with: /\A#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})\Z/, message: "color should be an hex" } + + has_many :file_labels + has_many :file_records, through: :file_labels end diff --git a/db/migrate/20240311162807_create_file_labels.rb b/db/migrate/20240311162807_create_file_labels.rb new file mode 100644 index 00000000..9e2cdfdc --- /dev/null +++ b/db/migrate/20240311162807_create_file_labels.rb @@ -0,0 +1,10 @@ +class CreateFileLabels < ActiveRecord::Migration[7.1] + def change + create_table :file_labels do |t| + t.references :file_record, null: false, foreign_key: true + t.references :label, null: false, foreign_key: true + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 2864c48a..ca83645f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_03_08_014217) do +ActiveRecord::Schema[7.1].define(version: 2024_03_11_162807) do create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "name", null: false t.string "record_type", null: false @@ -39,6 +39,15 @@ t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true end + create_table "file_labels", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "file_record_id", null: false + t.bigint "label_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["file_record_id"], name: "index_file_labels_on_file_record_id" + t.index ["label_id"], name: "index_file_labels_on_label_id" + end + create_table "file_records", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "notes" t.datetime "created_at", null: false @@ -75,5 +84,7 @@ end add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" + add_foreign_key "file_labels", "file_records" + add_foreign_key "file_labels", "labels" add_foreign_key "printer_jobs", "printers" end diff --git a/spec/factories/file_manager/files.rb b/spec/factories/file_records.rb similarity index 89% rename from spec/factories/file_manager/files.rb rename to spec/factories/file_records.rb index 4d49290d..4b519504 100644 --- a/spec/factories/file_manager/files.rb +++ b/spec/factories/file_records.rb @@ -19,5 +19,9 @@ ) end end + + trait(:with_labels) { + labels { build_list :label, 1 } + } end end diff --git a/spec/factories/labels.rb b/spec/factories/labels.rb index 84c6cbc4..9a1d8821 100644 --- a/spec/factories/labels.rb +++ b/spec/factories/labels.rb @@ -2,5 +2,9 @@ factory :label do name { 'My red label' } color { '#ff0000' } + + trait(:with_files) { + file_records { build_list :file_record, 1 } + } end end diff --git a/spec/models/file_manager/file_spec.rb b/spec/models/file_record_spec.rb similarity index 86% rename from spec/models/file_manager/file_spec.rb rename to spec/models/file_record_spec.rb index aebbd01d..c8e0c18a 100644 --- a/spec/models/file_manager/file_spec.rb +++ b/spec/models/file_record_spec.rb @@ -7,6 +7,7 @@ it 'has a valid factory' do expect(file).to be_valid + expect(build(:file_record, :with_labels)).to be_valid end describe '#filename' do @@ -136,4 +137,18 @@ }.from(Rails.root.join('spec/fixture_files/test.gcode').read).to(content) end end + + describe '#labels' do + subject { build(:file_record, :with_labels).labels } + + it { is_expected.to_not be_nil } + it { is_expected.to_not be_empty } + + it 'does not have duplicate labels associated to a single file record' do + file_record = create(:file_record, :with_labels) + file_record.labels.build(file_records: [file_record]) + + expect(file_record).to be_invalid # (same as to_not be_valid) + end + end end diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb index 84509940..70f01e5c 100644 --- a/spec/models/label_spec.rb +++ b/spec/models/label_spec.rb @@ -5,6 +5,7 @@ it 'has a valid factory' do expect(label).to be_valid + expect(build(:label, :with_files)).to be_valid end describe '#name' do @@ -43,4 +44,18 @@ expect(Label.new(name: 'my label', color: '#ff00ff')).to be_valid expect(Label.new(name: 'my label', color: '#f0f')).to be_valid end + + describe '#file_records' do + subject { build(:label, :with_files).file_records } + + it { is_expected.to_not be_nil } + it { is_expected.to_not be_empty } + + it 'does not have duplicate files associated to a single label' do + label = create(:label, :with_files) + label.file_records.build(labels: [label]) + + expect(label).to be_invalid # (same as to_not be_valid) + end + end end From 6caf71ee5b693b44670da714e195afb8a574b8ff Mon Sep 17 00:00:00 2001 From: Sarah-Jeanne <> Date: Tue, 12 Mar 2024 21:04:09 -0400 Subject: [PATCH 4/4] fixed lint-ruby --- .rubocop.yml | 3 +++ app/models/file_label.rb | 4 ++-- app/models/file_record.rb | 3 ++- app/models/label.rb | 11 +++++++---- db/migrate/20240308014217_create_labels.rb | 2 ++ db/migrate/20240311162807_create_file_labels.rb | 2 ++ spec/factories/file_records.rb | 4 ++-- spec/factories/labels.rb | 6 ++++-- spec/models/label_spec.rb | 4 +++- 9 files changed, 27 insertions(+), 12 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 015de6ff..70fa522f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -32,3 +32,6 @@ Rails/Output: Exclude: - 'lib/spooler.rb' - 'lib/spooler/**/*' + +Rails/UniqueValidationWithoutIndex: + Enabled: false \ No newline at end of file diff --git a/app/models/file_label.rb b/app/models/file_label.rb index b1e7125b..208cb009 100644 --- a/app/models/file_label.rb +++ b/app/models/file_label.rb @@ -1,8 +1,8 @@ +# frozen_string_literal: true + class FileLabel < ApplicationRecord belongs_to :file_record belongs_to :label - validates :file_record, presence: true - validates :label, presence: true validates :file_record_id, uniqueness: { scope: :label_id } end diff --git a/app/models/file_record.rb b/app/models/file_record.rb index 5567ef3e..db2021fe 100644 --- a/app/models/file_record.rb +++ b/app/models/file_record.rb @@ -3,7 +3,8 @@ class FileRecord < ApplicationRecord has_one_attached :file has_many :jobs, class_name: 'Printer::Job', as: :executable, dependent: :nullify - has_many :file_labels + + has_many :file_labels, dependent: :destroy has_many :labels, through: :file_labels validates :file, presence: true diff --git a/app/models/label.rb b/app/models/label.rb index 34832391..984b5f06 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -1,7 +1,10 @@ +# frozen_string_literal: true + class Label < ApplicationRecord - validates :name, presence: true, uniqueness: true - validates :color, presence: true, format: { with: /\A#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})\Z/, message: "color should be an hex" } + validates :name, presence: true, uniqueness: true + validates :color, presence: true, + format: { with: /\A#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})\Z/ } - has_many :file_labels - has_many :file_records, through: :file_labels + has_many :file_labels, dependent: :destroy + has_many :file_records, through: :file_labels end diff --git a/db/migrate/20240308014217_create_labels.rb b/db/migrate/20240308014217_create_labels.rb index be1687ef..0885af07 100644 --- a/db/migrate/20240308014217_create_labels.rb +++ b/db/migrate/20240308014217_create_labels.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class CreateLabels < ActiveRecord::Migration[7.1] def change create_table :labels do |t| diff --git a/db/migrate/20240311162807_create_file_labels.rb b/db/migrate/20240311162807_create_file_labels.rb index 9e2cdfdc..5347a6f1 100644 --- a/db/migrate/20240311162807_create_file_labels.rb +++ b/db/migrate/20240311162807_create_file_labels.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class CreateFileLabels < ActiveRecord::Migration[7.1] def change create_table :file_labels do |t| diff --git a/spec/factories/file_records.rb b/spec/factories/file_records.rb index 4b519504..4a7e2fb0 100644 --- a/spec/factories/file_records.rb +++ b/spec/factories/file_records.rb @@ -20,8 +20,8 @@ end end - trait(:with_labels) { + trait(:with_labels) do labels { build_list :label, 1 } - } + end end end diff --git a/spec/factories/labels.rb b/spec/factories/labels.rb index 9a1d8821..dc0c2120 100644 --- a/spec/factories/labels.rb +++ b/spec/factories/labels.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + FactoryBot.define do factory :label do name { 'My red label' } color { '#ff0000' } - trait(:with_files) { + trait(:with_files) do file_records { build_list :file_record, 1 } - } + end end end diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb index 70f01e5c..17361eb2 100644 --- a/spec/models/label_spec.rb +++ b/spec/models/label_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' RSpec.describe Label, type: :model do @@ -27,7 +29,7 @@ end it 'has a unique name' do - Label.create(name: 'My yellow label', color: '#0000ff') # same as create(:label, name: 'My yellow label', color: '#0000ff') + Label.create(name: 'My yellow label', color: '#0000ff') duplicate_label = Label.new(name: 'My yellow label', color: '#00f') expect(duplicate_label).to_not be_valid end