diff --git a/app/controllers/languages_controller.rb b/app/controllers/languages_controller.rb
new file mode 100644
index 0000000..6e68bac
--- /dev/null
+++ b/app/controllers/languages_controller.rb
@@ -0,0 +1,50 @@
+class LanguagesController < ApplicationController
+
+ def index
+ @languages = Language.all
+ end
+
+ def new
+ @language = Language.new
+ end
+
+ def create
+ @language = Language.new(language_params)
+ if @language.save
+ flash[:notice] = "Language successfully created."
+ redirect_to languages_path
+ else
+ render :new, status: :unprocessable_entity
+ end
+ end
+
+ def edit
+ @language = Language.find_by_id(params[:id])
+ end
+
+ def update
+ @language = Language.find_by_id(params[:id])
+ if @language.update(language_params)
+ flash[:notice] = "Language successfully updated."
+ redirect_to languages_path
+ else
+ render :edit, status: :unprocessable_entity
+ end
+ end
+
+ def destroy
+ @language = Language.find_by_id(params[:id])
+ if @language.destroy
+ flash[:notice] = "Language successfully deleted."
+ redirect_to languages_path
+ else
+ render :index, status: :not_modified
+ end
+ end
+
+ private
+ def language_params
+ params.require(:language).permit(:name)
+ end
+
+end
diff --git a/app/helpers/language_helper.rb b/app/helpers/language_helper.rb
new file mode 100644
index 0000000..c2278c2
--- /dev/null
+++ b/app/helpers/language_helper.rb
@@ -0,0 +1,2 @@
+module LanguageHelper
+end
diff --git a/app/models/definition.rb b/app/models/definition.rb
index 26bd152..102c6c7 100644
--- a/app/models/definition.rb
+++ b/app/models/definition.rb
@@ -1,3 +1,4 @@
class Definition < ApplicationRecord
belongs_to :word
+ belongs_to :language
end
diff --git a/app/models/language.rb b/app/models/language.rb
new file mode 100644
index 0000000..2d2daf4
--- /dev/null
+++ b/app/models/language.rb
@@ -0,0 +1,6 @@
+class Language < ApplicationRecord
+ has_many :definitions
+ has_many :part_of_speeches
+
+ validates_presence_of :name
+end
diff --git a/app/models/part_of_speech.rb b/app/models/part_of_speech.rb
index a06a03d..2da3a7a 100644
--- a/app/models/part_of_speech.rb
+++ b/app/models/part_of_speech.rb
@@ -1,2 +1,3 @@
class PartOfSpeech < ApplicationRecord
+ belongs_to :language
end
diff --git a/app/views/languages/_errors.html.erb b/app/views/languages/_errors.html.erb
new file mode 100644
index 0000000..027da81
--- /dev/null
+++ b/app/views/languages/_errors.html.erb
@@ -0,0 +1,5 @@
+<% if language.errors.any? %>
+ <% language.errors.full_messages.each do |message| %>
+
<%= link_to "Dictionary", dictionary_index_path %>
+ <% if user_signed_in? %>
+
|
+ <%= link_to "Languages", languages_path %>
+ <% end %>
<% if user_signed_in? %>
diff --git a/config/routes.rb b/config/routes.rb
index c59451f..30c2433 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -3,6 +3,7 @@ Rails.application.routes.draw do
#get 'dictionary/index'
resources :dictionary, only: [:index, :show]
resources :words, only: [:index, :show]
+ resources :languages
# 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/20231025010204_create_languages.rb b/db/migrate/20231025010204_create_languages.rb
new file mode 100644
index 0000000..9fe2126
--- /dev/null
+++ b/db/migrate/20231025010204_create_languages.rb
@@ -0,0 +1,9 @@
+class CreateLanguages < ActiveRecord::Migration[7.1]
+ def change
+ create_table :languages do |t|
+ t.string :name
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20231025010226_add_language_fields.rb b/db/migrate/20231025010226_add_language_fields.rb
new file mode 100644
index 0000000..3fa7210
--- /dev/null
+++ b/db/migrate/20231025010226_add_language_fields.rb
@@ -0,0 +1,17 @@
+class AddLanguageFields < ActiveRecord::Migration[7.1]
+ def change
+ create_table :language do |t|
+ t.string :name
+
+ t.timestamps
+ end
+
+ change_table :definitions do |t|
+ t.references :language, null: false, foreign_key: true
+ end
+
+ change_table :part_of_speeches do |t|
+ t.references :language, null: false, foreign_key: true
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 54791b0..d907cd6 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,21 +10,37 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.1].define(version: 2023_10_13_214519) do
+ActiveRecord::Schema[7.1].define(version: 2023_10_25_010226) do
create_table "definitions", force: :cascade do |t|
t.string "pos"
t.string "definition"
t.integer "word_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.integer "language_id", null: false
+ t.index ["language_id"], name: "index_definitions_on_language_id"
t.index ["word_id"], name: "index_definitions_on_word_id"
end
+ create_table "language", force: :cascade do |t|
+ t.string "name"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
+ create_table "languages", force: :cascade do |t|
+ t.string "name"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
create_table "part_of_speeches", force: :cascade do |t|
t.string "pos"
t.string "definition"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.integer "language_id", null: false
+ t.index ["language_id"], name: "index_part_of_speeches_on_language_id"
end
create_table "users", force: :cascade do |t|
@@ -45,5 +61,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_10_13_214519) do
t.datetime "updated_at", null: false
end
+ add_foreign_key "definitions", "languages"
add_foreign_key "definitions", "words"
+ add_foreign_key "part_of_speeches", "languages"
end
diff --git a/lib/tasks/database.rake b/lib/tasks/database.rake
index 893c113..06f3628 100644
--- a/lib/tasks/database.rake
+++ b/lib/tasks/database.rake
@@ -1,14 +1,24 @@
namespace :dataset do
desc "TODO"
task ingest: :environment do
- ingest_pos
- ingest_dictionary
+ english = create_english_lang
+ ingest_pos(english)
+ ingest_dictionary(english)
puts "Ingest complete."
end
end
-def ingest_pos
+def create_english_lang
+ if Language.count > 0
+ puts "Language English already exists! Skipping step."
+ return
+ end
+
+ return Language.create(name: "English")
+end
+
+def ingest_pos(language)
if PartOfSpeech.count > 0
puts "Parts of speech data already exists in table! Aborting."
return
@@ -17,12 +27,12 @@ def ingest_pos
parts_of_speech = JSON.parse(File.read('db/dataset_en/toki-partsofspeech.json'))
parts_of_speech.each do |pos|
- PartOfSpeech.create(pos: pos['pos'], definition: pos['definition'])
+ PartOfSpeech.create(pos: pos['pos'], definition: pos['definition'], language_id: language.id)
end
puts "Parts of speech ingest complete."
end
-def ingest_dictionary
+def ingest_dictionary(language)
if Word.count > 0
puts "Dictionary data already exists in table! Aborting."
return
@@ -37,7 +47,7 @@ def ingest_dictionary
word = Word.create(word: entry['word'])
entry['definitions'].each do |definition|
- word.definitions.create(pos: definition['pos'], definition: definition['definition'])
+ word.definitions.create(pos: definition['pos'], definition: definition['definition'], language_id: language.id)
end
end
puts "Dictionary ingest complete."
diff --git a/spec/factories/definitions.rb b/spec/factories/definitions.rb
index 19046f3..eb78d10 100644
--- a/spec/factories/definitions.rb
+++ b/spec/factories/definitions.rb
@@ -2,6 +2,7 @@ FactoryBot.define do
factory :definition do
pos { "n" }
definition { "this is a definition" }
+ language_id { FactoryBot.create(:language).id }
word_id { FactoryBot.create(:word).id }
end
end
diff --git a/spec/factories/languages.rb b/spec/factories/languages.rb
new file mode 100644
index 0000000..24c2329
--- /dev/null
+++ b/spec/factories/languages.rb
@@ -0,0 +1,5 @@
+FactoryBot.define do
+ factory :language do
+ name { "MyString" }
+ end
+end
diff --git a/spec/factories/part_of_speech.rb b/spec/factories/part_of_speech.rb
index 4f47522..a38a5d7 100644
--- a/spec/factories/part_of_speech.rb
+++ b/spec/factories/part_of_speech.rb
@@ -1,6 +1,7 @@
FactoryBot.define do
factory :part_of_speech do
sequence(:pos) { |n| "test-#{n.to_s}" }
+ language_id { FactoryBot.create(:language).id }
definition { "test definition" }
end
end
diff --git a/spec/models/language_spec.rb b/spec/models/language_spec.rb
new file mode 100644
index 0000000..1e01a5c
--- /dev/null
+++ b/spec/models/language_spec.rb
@@ -0,0 +1,4 @@
+require 'rails_helper'
+
+RSpec.describe Language, type: :model do
+end
diff --git a/spec/requests/language_spec.rb b/spec/requests/language_spec.rb
new file mode 100644
index 0000000..847b2b3
--- /dev/null
+++ b/spec/requests/language_spec.rb
@@ -0,0 +1,106 @@
+require 'rails_helper'
+
+RSpec.describe "Languages", type: :request do
+
+ describe "GET :index" do
+ it "returns http success" do
+ get "/languages/"
+ expect(response).to have_http_status(:success)
+ end
+
+ it "lists all languages" do
+ language = FactoryBot.create(:language)
+ get "/languages/"
+ expect(response.body).to include(language.name)
+ end
+
+ it "has a new-language link" do
+ get "/languages/"
+ expect(response.body).to have_selector(%(a[href="#{new_language_path}"]))
+ end
+
+ it "has an edit button" do
+ language = FactoryBot.create(:language)
+ get "/languages/"
+ expect(response.body).to have_link("Edit")
+ end
+
+ it "has a delete button" do
+ language = FactoryBot.create(:language)
+ get "/languages/"
+ expect(response.body).to have_link("Delete")
+ end
+ end
+
+ describe "GET :new" do
+ it "returns http success" do
+ get "/languages/new"
+ expect(response).to have_http_status(:success)
+ end
+
+ it "has a form for a new language" do
+ get "/languages/new"
+ expect(response.body).to have_selector(%(input[name="language[name]"]))
+ end
+ end
+
+ describe "POST :create" do
+ it "redirect to languages_path on success" do
+ post "/languages", params: { language: { name: "Test Name" } }
+ expect(response).to redirect_to(languages_path)
+ end
+
+ it "creates a new language" do
+ post "/languages", params: { language: { name: "Test Name" } }
+ expect(Language.count).to eq(1)
+ end
+
+ it "requires a name for a new language" do
+ post "/languages", params: { language: { name: nil } }
+ expect(response).to have_http_status(:unprocessable_entity)
+ end
+ end
+
+ describe "GET :edit" do
+ before :each do
+ @language = FactoryBot.create(:language)
+ get "/languages/#{@language.id}/edit"
+ end
+
+ it "returns http success" do
+ expect(response).to have_http_status(:success)
+ end
+
+ it "has a form to edit language" do
+ expect(response.body).to have_selector(%(input[name="language[name]"]))
+ end
+ end
+
+ describe "PATCH :update" do
+ before :each do
+ @language = FactoryBot.create(:language)
+ @params = { language: { name: "Test Name Update" } }
+ end
+
+ it "updates a language" do
+ patch "/languages/#{@language.id}", params: @params
+ expect(response).to redirect_to(languages_path)
+ end
+
+ it "requires params to update a language" do
+ @params = { language: { name: nil, invalid: "oh no" } }
+ patch "/languages/#{@language.id}", params: @params
+ expect(response).to have_http_status(:unprocessable_entity)
+ end
+
+ end
+
+ describe "DELETE :destroy" do
+ it "deletes a language" do
+ language = FactoryBot.create(:language)
+ language2 = FactoryBot.create(:language)
+ delete "/languages/#{language.id}"
+ expect(Language.all).to eq([language2])
+ end
+ end
+end
diff --git a/spec/requests/root_spec.rb b/spec/requests/root_spec.rb
index a6dee99..810a364 100644
--- a/spec/requests/root_spec.rb
+++ b/spec/requests/root_spec.rb
@@ -27,6 +27,12 @@ RSpec.describe "Root path", type: :request do
expect(response.body).to include("Sign Out")
end
+ it "should have the 'Languages' link" do
+ sign_in FactoryBot.create(:user)
+ get root_path
+ expect(response.body).to have_selector(%(a[href="#{languages_path}"]))
+ end
+
it "should welcome user by username" do
user = FactoryBot.create(:user)
sign_in user
diff --git a/spec/requests/words_spec.rb b/spec/requests/words_spec.rb
deleted file mode 100644
index 99b807f..0000000
--- a/spec/requests/words_spec.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe "Words", type: :request do
- describe "GET /index" do
-
- it "renders the index template" do
- get "/words"
- expect(response).to render_template(:index)
- end
- end
-end
diff --git a/spec/views/.keep b/spec/views/.keep
new file mode 100644
index 0000000..e69de29