From 5674e6b21a4ed6c9f23f9a2d73331a75b261b42e Mon Sep 17 00:00:00 2001 From: Runar Ingebrigtsen Date: Thu, 22 Jan 2026 14:40:31 +0100 Subject: [PATCH] fix attribute name conflict, add seeds from original document --- Gemfile | 2 + Gemfile.lock | 9 ++- README.md | 6 +- app/models/entry.rb | 9 +-- db/migrate/20260122123818_create_entries.rb | 2 +- db/seeds.rb | 81 ++++++++++++++++++--- 6 files changed, 86 insertions(+), 23 deletions(-) diff --git a/Gemfile b/Gemfile index 9834d78..11f447a 100644 --- a/Gemfile +++ b/Gemfile @@ -2,6 +2,8 @@ source "https://rubygems.org" # Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main" gem "rails", "~> 8.1.2" +# Excel import for seeds +gem "roo", "~> 2.10" # The modern asset pipeline for Rails [https://github.com/rails/propshaft] gem "propshaft" # Use sqlite3 as the database for Active Record diff --git a/Gemfile.lock b/Gemfile.lock index 158c137..969c472 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -255,6 +255,9 @@ GEM reline (0.6.3) io-console (~> 0.5) rexml (3.4.4) + roo (2.10.1) + nokogiri (~> 1) + rubyzip (>= 1.3.0, < 3.0.0) rubocop (1.82.1) json (~> 2.3) language_server-protocol (~> 3.17.0.2) @@ -287,7 +290,7 @@ GEM ruby-vips (2.3.0) ffi (~> 1.12) logger - rubyzip (3.2.2) + rubyzip (2.4.1) securerandom (0.4.1) selenium-webdriver (4.40.0) base64 (~> 0.2) @@ -367,6 +370,7 @@ DEPENDENCIES propshaft puma (>= 5.0) rails (~> 8.1.2) + roo (~> 2.10) rubocop-rails-omakase selenium-webdriver solid_cable @@ -472,6 +476,7 @@ CHECKSUMS regexp_parser (2.11.3) sha256=ca13f381a173b7a93450e53459075c9b76a10433caadcb2f1180f2c741fc55a4 reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835 rexml (3.4.4) sha256=19e0a2c3425dfbf2d4fc1189747bdb2f849b6c5e74180401b15734bc97b5d142 + roo (2.10.1) sha256=cbb43bc955f9c110e74b721c835fb9bd3515b63af88ec709ac87fbf30f8be70e rubocop (1.82.1) sha256=09f1a6a654a960eda767aebea33e47603080f8e9c9a3f019bf9b94c9cab5e273 rubocop-ast (1.49.0) sha256=49c3676d3123a0923d333e20c6c2dbaaae2d2287b475273fddee0c61da9f71fd rubocop-performance (1.26.1) sha256=cd19b936ff196df85829d264b522fd4f98b6c89ad271fa52744a8c11b8f71834 @@ -479,7 +484,7 @@ CHECKSUMS rubocop-rails-omakase (1.1.0) sha256=2af73ac8ee5852de2919abbd2618af9c15c19b512c4cfc1f9a5d3b6ef009109d ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33 ruby-vips (2.3.0) sha256=e685ec02c13969912debbd98019e50492e12989282da5f37d05f5471442f5374 - rubyzip (3.2.2) sha256=c0ed99385f0625415c8f05bcae33fe649ed2952894a95ff8b08f26ca57ea5b3c + rubyzip (2.4.1) sha256=8577c88edc1fde8935eb91064c5cb1aef9ad5494b940cf19c775ee833e075615 securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1 selenium-webdriver (4.40.0) sha256=16ef7aa9853c1d4b9d52eac45aafa916e3934c5c83cb4facb03f250adfd15e5b solid_cable (3.0.12) sha256=a168a54731a455d5627af48d8441ea3b554b8c1f6e6cd6074109de493e6b0460 diff --git a/README.md b/README.md index 9566e1f..d40c583 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ An entry represents a translatable unit which may be: - `word` — Single word - `phrase` — Multi-word expression or idiom, sentence -- `name` — Person's name (for consistent transliteration) +- `proper_name` — Person's name (for consistent transliteration) - `title` — Book, publication, or hymn title - `reference` — Biblical or doctrinal term - `other` — Any other translatable text unit @@ -46,7 +46,7 @@ When translators disagree on a translation or want to suggest alternatives (regi ActiveRecord::Schema[8.0].define(version: 2025_01_22_100000) do create_table "entries", force: :cascade do |t| - t.integer "category", null: false # word, phrase, name, title, reference, other + t.integer "category", null: false # word, phrase, proper_name, title, reference, other # Language columns t.string "fi" # Finnish @@ -152,7 +152,7 @@ end ## Initial Data -Found in 'Kristillisyyden sanasto ver 23.5.2013.xlsx' +See 'public/Kristillisyyden sanasto ver 23.5.2013.xlsx' --- diff --git a/app/models/entry.rb b/app/models/entry.rb index a2d0c87..96f5a8c 100644 --- a/app/models/entry.rb +++ b/app/models/entry.rb @@ -6,14 +6,7 @@ class Entry < ApplicationRecord has_many :comments, as: :commentable, dependent: :destroy has_many :entry_versions, dependent: :destroy - enum category: { - word: 0, - phrase: 1, - name: 2, - title: 3, - reference: 4, - other: 5 - } + enum :category, %i[word phrase proper_name title reference other] validates :category, presence: true end diff --git a/db/migrate/20260122123818_create_entries.rb b/db/migrate/20260122123818_create_entries.rb index 13ddfb9..c3e3857 100644 --- a/db/migrate/20260122123818_create_entries.rb +++ b/db/migrate/20260122123818_create_entries.rb @@ -1,7 +1,7 @@ class CreateEntries < ActiveRecord::Migration[8.1] def change create_table :entries do |t| - t.integer :category, null: false + t.integer :category, null: false, default: 0 t.string :fi t.string :en t.string :sv diff --git a/db/seeds.rb b/db/seeds.rb index 4fbd6ed..f428dd1 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1,9 +1,72 @@ -# This file should ensure the existence of records required to run the application in every environment (production, -# development, test). The code here should be idempotent so that it can be executed at any point in every environment. -# The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup). -# -# Example: -# -# ["Action", "Comedy", "Drama", "Horror"].each do |genre_name| -# MovieGenre.find_or_create_by!(name: genre_name) -# end +require "roo" + +# Seed supported languages +SUPPORTED_LANGUAGES = [ + { code: "fi", name: "Finnish", native_name: "Suomi", sort_order: 1 }, + { code: "en", name: "English", native_name: "English", sort_order: 2 }, + { code: "sv", name: "Swedish", native_name: "Svenska", sort_order: 3 }, + { code: "no", name: "Norwegian", native_name: "Norsk", sort_order: 4 }, + { code: "de", name: "German", native_name: "Deutsch", sort_order: 5 }, + { code: "ru", name: "Russian", native_name: "Русский", sort_order: 6 } +].freeze + +SUPPORTED_LANGUAGES.each do |lang| + SupportedLanguage.find_or_create_by!(code: lang[:code]) do |record| + record.assign_attributes(lang.except(:code)) + end +end + +puts "Seeded #{SupportedLanguage.count} languages" + +# Import entries from Excel +HEADER_TO_LANG = { + "Finnish" => :fi, + "English" => :en, + "Swedish" => :sv, + "Norwegian" => :no, + "German" => :de, + "Russian" => :ru +}.freeze + +source_path = Rails.root.join("public", "Kristillisyyden sanasto ver 23.5.2013.xlsx") + +unless source_path.exist? + abort "Seed file not found: #{source_path}" +end + +sheet = Roo::Excelx.new(source_path.to_s).sheet(0) +headers = sheet.row(1).map { |cell| cell.to_s.strip } + +column_map = headers.each_with_index.filter_map do |header, index| + lang = HEADER_TO_LANG[header] + [ lang, index ] if lang +end.to_h + +if column_map.empty? + abort "No language columns found in headers: #{headers.inspect}" +end + +puts "Found columns: #{column_map.keys.join(', ')}" +puts "Importing entries..." + +imported = 0 +skipped = 0 + +sheet.each_row_streaming(offset: 1) do |row| + translations = column_map.transform_values do |index| + row[index]&.value.to_s.strip.presence + end + + if translations.values.none? + skipped += 1 + next + end + + Entry.find_or_create_by!(translations) do |entry| + entry.category = :word + end + + imported += 1 +end + +puts "Imported #{imported} entries, skipped #{skipped} empty rows"