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| %> +
<%= message %>
+ <% end %> +<% end %> diff --git a/app/views/languages/_form.html.erb b/app/views/languages/_form.html.erb new file mode 100644 index 0000000..e325c75 --- /dev/null +++ b/app/views/languages/_form.html.erb @@ -0,0 +1,6 @@ +<%= form_for language do |f| %> + <%= f.label :name %> + <%= f.text_field :name %>
+
+ <%= f.submit %> +<% end %> diff --git a/app/views/languages/create.html.erb b/app/views/languages/create.html.erb new file mode 100644 index 0000000..6c0f169 --- /dev/null +++ b/app/views/languages/create.html.erb @@ -0,0 +1,2 @@ +

Language#create

+

Find me in app/views/language/create.html.erb

diff --git a/app/views/languages/destroy.html.erb b/app/views/languages/destroy.html.erb new file mode 100644 index 0000000..a6e1d6b --- /dev/null +++ b/app/views/languages/destroy.html.erb @@ -0,0 +1,2 @@ +

Language#destroy

+

Find me in app/views/language/destroy.html.erb

diff --git a/app/views/languages/edit.html.erb b/app/views/languages/edit.html.erb new file mode 100644 index 0000000..13ba0c1 --- /dev/null +++ b/app/views/languages/edit.html.erb @@ -0,0 +1,5 @@ +<%= render "languages/errors", language: @language %> + +

Edit Language

+ +<%= render "languages/form", language: @language %> diff --git a/app/views/languages/index.html.erb b/app/views/languages/index.html.erb new file mode 100644 index 0000000..cc3a333 --- /dev/null +++ b/app/views/languages/index.html.erb @@ -0,0 +1,20 @@ +

Languages

+ + + + + +<% @languages.each do |language| %> + + + + + + +<% end %> +
Language
<%= language.name %><%= link_to "Edit", edit_language_path(language) %> | <%= link_to "Delete", language_path(language), data: { turbo_method: :delete, + turbo_confirm: "Are you sure?" } %>
+ +
+
+<%= link_to "New Language", new_language_path %> diff --git a/app/views/languages/new.html.erb b/app/views/languages/new.html.erb new file mode 100644 index 0000000..38ea897 --- /dev/null +++ b/app/views/languages/new.html.erb @@ -0,0 +1,5 @@ +<%= render "languages/errors", language: @language %> + +

New Language

+ +<%= render "languages/form", language: @language %> diff --git a/app/views/languages/show.html.erb b/app/views/languages/show.html.erb new file mode 100644 index 0000000..73256aa --- /dev/null +++ b/app/views/languages/show.html.erb @@ -0,0 +1,2 @@ +

Language#show

+

Find me in app/views/language/show.html.erb

diff --git a/app/views/languages/update.html.erb b/app/views/languages/update.html.erb new file mode 100644 index 0000000..cd217a0 --- /dev/null +++ b/app/views/languages/update.html.erb @@ -0,0 +1,2 @@ +

Language#update

+

Find me in app/views/language/update.html.erb

diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 9f286e6..13b5356 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -15,6 +15,10 @@
<%= 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