diff --git a/app/controllers/clips_controller.rb b/app/controllers/clips_controller.rb
index 6fceeff..81b4ece 100644
--- a/app/controllers/clips_controller.rb
+++ b/app/controllers/clips_controller.rb
@@ -15,6 +15,13 @@ class ClipsController < ApplicationController
def create
@clip = Clip.new(clip_params)
if @clip.save
+ params[:clip][:tag_ids].each do |tag_id|
+ unless tag_id.empty?
+ tag = Tag.find(tag_id)
+ @clip.tags << tag
+ end
+ end
+
redirect_to @clip
else
render :new, status: :unprocessable_entity
@@ -24,8 +31,25 @@ class ClipsController < ApplicationController
def edit
end
- def update
+ def update
if @clip.update(clip_params)
+ newtags = []
+ params[:clip][:tag_ids].each do |tag_id|
+ unless tag_id.empty?
+ tag = Tag.find(tag_id)
+ newtags.push(tag)
+ unless @clip.tags.include? tag
+ @clip.tags << tag
+ end
+ end
+ end
+
+ @clip.tags.each do |tag|
+ unless newtags.include? tag
+ @clip.tags.delete tag
+ end
+ end
+
redirect_to @clip
else
render :edit, status: :unprocessable_entity
diff --git a/app/helpers/tag_to_clips_helper.rb b/app/helpers/tag_to_clips_helper.rb
new file mode 100644
index 0000000..48c849c
--- /dev/null
+++ b/app/helpers/tag_to_clips_helper.rb
@@ -0,0 +1,2 @@
+module TagToClipsHelper
+end
diff --git a/app/models/clip.rb b/app/models/clip.rb
index 005bbea..1588fe7 100644
--- a/app/models/clip.rb
+++ b/app/models/clip.rb
@@ -1,5 +1,7 @@
class Clip < ApplicationRecord
has_one_attached :video
belongs_to :category
+ has_many :tag_to_clips
+ has_many :tags, through: :tag_to_clips
validates :title, presence: true
end
diff --git a/app/models/tag.rb b/app/models/tag.rb
new file mode 100644
index 0000000..f0ac3f0
--- /dev/null
+++ b/app/models/tag.rb
@@ -0,0 +1,4 @@
+class Tag < ApplicationRecord
+ has_many :tag_to_clips
+ has_many :clips, through: :tag_to_clips
+end
diff --git a/app/models/tag_to_clip.rb b/app/models/tag_to_clip.rb
new file mode 100644
index 0000000..0313a65
--- /dev/null
+++ b/app/models/tag_to_clip.rb
@@ -0,0 +1,4 @@
+class TagToClip < ApplicationRecord
+ belongs_to :clip
+ belongs_to :tag
+end
diff --git a/app/views/clips/_form.html.erb b/app/views/clips/_form.html.erb
index 43ccea0..b0aa46b 100644
--- a/app/views/clips/_form.html.erb
+++ b/app/views/clips/_form.html.erb
@@ -4,6 +4,7 @@
<%= form.text_field :title %>
<%= form.file_field :video, :accept => 'video/quicktime,video/mp4' %>
<%= form.select :category_id, Category.all.collect{ |t| [ t.name, t.id ] }%>
+ <%= collection_select(:clip, :tag_ids, Tag.all, :id, :name, {}, { :multiple => true } )%>
diff --git a/app/views/clips/show.html.erb b/app/views/clips/show.html.erb
index 00498c7..7bd66ef 100644
--- a/app/views/clips/show.html.erb
+++ b/app/views/clips/show.html.erb
@@ -2,6 +2,7 @@
<%= @clip.title %>
<% end %>
Category: <%= link_to @clip.category.name, @clip.category %>
+Tags: <%= @clip.tags.map(&:name).join(', ') %>
<% if @clip.video.attached? %>
<%= video_tag @clip.video, :controls => true%>
<% end %>
diff --git a/config/routes.rb b/config/routes.rb
index 68e0863..c6a7087 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,4 +1,5 @@
Rails.application.routes.draw do
+ resources :tag_to_clips
resource :session
resources :passwords, param: :token
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
diff --git a/db/migrate/20250910022523_create_tags.rb b/db/migrate/20250910022523_create_tags.rb
new file mode 100644
index 0000000..3337e26
--- /dev/null
+++ b/db/migrate/20250910022523_create_tags.rb
@@ -0,0 +1,9 @@
+class CreateTags < ActiveRecord::Migration[8.0]
+ def change
+ create_table :tags do |t|
+ t.string :name
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20250910022600_create_tag_to_clips.rb b/db/migrate/20250910022600_create_tag_to_clips.rb
new file mode 100644
index 0000000..b4d47e1
--- /dev/null
+++ b/db/migrate/20250910022600_create_tag_to_clips.rb
@@ -0,0 +1,10 @@
+class CreateTagToClips < ActiveRecord::Migration[8.0]
+ def change
+ create_table :tag_to_clips do |t|
+ t.references :clip, null: false, foreign_key: true
+ t.references :tag, null: false, foreign_key: true
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index c7b1d60..fd62891 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[8.0].define(version: 2025_09_09_013509) do
+ActiveRecord::Schema[8.0].define(version: 2025_09_10_022600) do
create_table "active_storage_attachments", force: :cascade do |t|
t.string "name", null: false
t.string "record_type", null: false
@@ -62,6 +62,21 @@ ActiveRecord::Schema[8.0].define(version: 2025_09_09_013509) do
t.index ["user_id"], name: "index_sessions_on_user_id"
end
+ create_table "tag_to_clips", force: :cascade do |t|
+ t.integer "clip_id", null: false
+ t.integer "tag_id", null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["clip_id"], name: "index_tag_to_clips_on_clip_id"
+ t.index ["tag_id"], name: "index_tag_to_clips_on_tag_id"
+ end
+
+ create_table "tags", force: :cascade do |t|
+ t.string "name"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
create_table "users", force: :cascade do |t|
t.string "email_address", null: false
t.string "password_digest", null: false
@@ -74,4 +89,6 @@ ActiveRecord::Schema[8.0].define(version: 2025_09_09_013509) do
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
add_foreign_key "clips", "categories"
add_foreign_key "sessions", "users"
+ add_foreign_key "tag_to_clips", "clips"
+ add_foreign_key "tag_to_clips", "tags"
end
diff --git a/test/controllers/tag_to_clips_controller_test.rb b/test/controllers/tag_to_clips_controller_test.rb
new file mode 100644
index 0000000..a1fa563
--- /dev/null
+++ b/test/controllers/tag_to_clips_controller_test.rb
@@ -0,0 +1,48 @@
+require "test_helper"
+
+class TagToClipsControllerTest < ActionDispatch::IntegrationTest
+ setup do
+ @tag_to_clip = tag_to_clips(:one)
+ end
+
+ test "should get index" do
+ get tag_to_clips_url
+ assert_response :success
+ end
+
+ test "should get new" do
+ get new_tag_to_clip_url
+ assert_response :success
+ end
+
+ test "should create tag_to_clip" do
+ assert_difference("TagToClip.count") do
+ post tag_to_clips_url, params: { tag_to_clip: { clip_id: @tag_to_clip.clip_id, tag_id: @tag_to_clip.tag_id } }
+ end
+
+ assert_redirected_to tag_to_clip_url(TagToClip.last)
+ end
+
+ test "should show tag_to_clip" do
+ get tag_to_clip_url(@tag_to_clip)
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get edit_tag_to_clip_url(@tag_to_clip)
+ assert_response :success
+ end
+
+ test "should update tag_to_clip" do
+ patch tag_to_clip_url(@tag_to_clip), params: { tag_to_clip: { clip_id: @tag_to_clip.clip_id, tag_id: @tag_to_clip.tag_id } }
+ assert_redirected_to tag_to_clip_url(@tag_to_clip)
+ end
+
+ test "should destroy tag_to_clip" do
+ assert_difference("TagToClip.count", -1) do
+ delete tag_to_clip_url(@tag_to_clip)
+ end
+
+ assert_redirected_to tag_to_clips_url
+ end
+end
diff --git a/test/fixtures/tag_to_clips.yml b/test/fixtures/tag_to_clips.yml
new file mode 100644
index 0000000..0105b24
--- /dev/null
+++ b/test/fixtures/tag_to_clips.yml
@@ -0,0 +1,9 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ clip: one
+ tag: one
+
+two:
+ clip: two
+ tag: two
diff --git a/test/fixtures/tags.yml b/test/fixtures/tags.yml
new file mode 100644
index 0000000..7d41224
--- /dev/null
+++ b/test/fixtures/tags.yml
@@ -0,0 +1,7 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ name: MyString
+
+two:
+ name: MyString
diff --git a/test/models/tag_test.rb b/test/models/tag_test.rb
new file mode 100644
index 0000000..1846cdb
--- /dev/null
+++ b/test/models/tag_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class TagTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/models/tag_to_clip_test.rb b/test/models/tag_to_clip_test.rb
new file mode 100644
index 0000000..d841e0e
--- /dev/null
+++ b/test/models/tag_to_clip_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class TagToClipTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end