From 5ebbf32c884f7f518020fd66489d4835b59667b5 Mon Sep 17 00:00:00 2001 From: Dmitry Proskurekov Date: Mon, 25 Sep 2023 22:51:38 +0700 Subject: [PATCH 01/12] add policy for vacancy_controller, add spec --- app/controllers/application_controller.rb | 4 +++ app/controllers/vacancies_controller.rb | 16 ++++++----- app/policies/application_policy.rb | 25 ++++++++-------- app/policies/vacancy_policy.rb | 7 +++++ spec/factories/users.rb | 8 ++++++ spec/policies/vacancies_policy_spec.rb | 35 +++++++++++++++++++++++ spec/rails_helper.rb | 1 + 7 files changed, 76 insertions(+), 20 deletions(-) create mode 100644 app/policies/vacancy_policy.rb create mode 100644 spec/policies/vacancies_policy_spec.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1c0dc94..3867e28 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,6 +1,10 @@ class ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? + rescue_from ActionPolicy::Unauthorized do |_e| + redirect_to root_path + end + private def configure_permitted_parameters diff --git a/app/controllers/vacancies_controller.rb b/app/controllers/vacancies_controller.rb index 9290073..ec32664 100644 --- a/app/controllers/vacancies_controller.rb +++ b/app/controllers/vacancies_controller.rb @@ -1,4 +1,7 @@ class VacanciesController < ApplicationController + before_action :load_vacancy, only: %i[edit update destroy] + verify_authorized only: %i[edit update destroy] + def index @vacancies = Vacancy.all end @@ -11,9 +14,7 @@ def new @vacancy = Vacancy.new end - def edit - @vacancy = Vacancy.find(params[:id]) - end + def edit; end def create @vacancy = current_user.vacancies.build(vacancy_params) @@ -26,8 +27,6 @@ def create end def update - @vacancy = Vacancy.find(params[:id]) - if @vacancy.update(vacancy_params) redirect_to vacancy_path(@vacancy) else @@ -36,14 +35,17 @@ def update end def destroy - @vacancy = Vacancy.find(params[:id]) @vacancy.destroy - redirect_to vacancies_path end private + def load_vacancy + @vacancy = Vacancy.find(params[:id]) + authorize!(@vacancy) + end + def vacancy_params params.require(:vacancy).permit(:title, :body) end diff --git a/app/policies/application_policy.rb b/app/policies/application_policy.rb index 3cbb463..a238c02 100644 --- a/app/policies/application_policy.rb +++ b/app/policies/application_policy.rb @@ -1,16 +1,15 @@ -# Base class for application policies class ApplicationPolicy < ActionPolicy::Base - # Configure additional authorization contexts here - # (`user` is added by default). - # - # authorize :account, optional: true - # - # Read more about authorization context: https://actionpolicy.evilmartians.io/#/authorization_context + def allow_record + allow! if current_admin? || owner_record? + end - # Define shared methods useful for most policies. - # For example: - # - # def owner? - # record.user_id == user.id - # end + private + + def current_admin? + user.admin? + end + + def owner_record? + user.id == record.user_id + end end diff --git a/app/policies/vacancy_policy.rb b/app/policies/vacancy_policy.rb new file mode 100644 index 0000000..b00b04c --- /dev/null +++ b/app/policies/vacancy_policy.rb @@ -0,0 +1,7 @@ +class VacancyPolicy < ApplicationPolicy + alias_rule :edit?, :destroy?, :update?, to: :manage? + + def manage? + allow_record + end +end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 2a8d1fa..3834cbc 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -20,4 +20,12 @@ password { "password" } role { User.roles.keys.sample } end + + trait :admin do + role { "admin" } + end + + trait :skip_admin_role do + role { User.roles.keys.reject { |key| key == "admin" }.sample } + end end diff --git a/spec/policies/vacancies_policy_spec.rb b/spec/policies/vacancies_policy_spec.rb new file mode 100644 index 0000000..bd0aa62 --- /dev/null +++ b/spec/policies/vacancies_policy_spec.rb @@ -0,0 +1,35 @@ +require "rails_helper" + +RSpec.describe VacancyPolicy, type: :policy do + let(:user) { build_stubbed(:user, :skip_admin_role) } + let(:vacancy) { build_stubbed(:vacancy, user:) } + + let(:policy) { described_class.new(vacancy, user:) } + + describe "#manage?" do + subject(:policy_result) { policy.apply(:manage?) } + + let(:rules) { %i[edit? update? destroy?] } + + it "is an alias of :edit, :update, :destroy rules" do + expect(rules).to all be_an_alias_of(policy, :manage?) + end + + context "when user is owner vacancy" do + it { expect(policy_result).to be_present } + end + + context "when vacancy doesn`t belong user and he isn`t an admin" do + let(:vacancy) { build_stubbed(:vacancy) } + + it { expect(policy_result).not_to be_present } + end + + context "when vacancy doesn`t belong user but user is admin" do + let(:vacancy) { build_stubbed(:vacancy) } + let(:user) { build_stubbed(:user, :admin) } + + it { expect(policy_result).to be_present } + end + end +end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index a5c4205..bd8f593 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -3,6 +3,7 @@ require_relative '../config/environment' abort("The Rails environment is running in production mode!") if Rails.env.production? require 'rspec/rails' +require "action_policy/rspec" begin ActiveRecord::Migration.maintain_test_schema! rescue ActiveRecord::PendingMigrationError => e From 16689a7a291e1c236824acab53dcec21dc16205d Mon Sep 17 00:00:00 2001 From: Dmitry Proskurekov Date: Mon, 25 Sep 2023 23:02:27 +0700 Subject: [PATCH 02/12] rename spec file --- .../policies/{vacancies_policy_spec.rb => vacancy_policy_spec.rb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename spec/policies/{vacancies_policy_spec.rb => vacancy_policy_spec.rb} (100%) diff --git a/spec/policies/vacancies_policy_spec.rb b/spec/policies/vacancy_policy_spec.rb similarity index 100% rename from spec/policies/vacancies_policy_spec.rb rename to spec/policies/vacancy_policy_spec.rb From 950ba2c974b03f7612df084a3c65aae4b96d2f1c Mon Sep 17 00:00:00 2001 From: Dmitry Proskurekov Date: Thu, 28 Sep 2023 22:08:08 +0700 Subject: [PATCH 03/12] remove load_vacancy method, add allowed_to check, add action_policy/rspec/dsl --- app/controllers/vacancies_controller.rb | 17 +++++++----- app/policies/application_policy.rb | 2 +- app/policies/vacancy_policy.rb | 2 +- spec/policies/vacancy_policy_spec.rb | 37 ++++++++----------------- spec/rails_helper.rb | 2 ++ 5 files changed, 25 insertions(+), 35 deletions(-) diff --git a/app/controllers/vacancies_controller.rb b/app/controllers/vacancies_controller.rb index ec32664..d76a6a5 100644 --- a/app/controllers/vacancies_controller.rb +++ b/app/controllers/vacancies_controller.rb @@ -1,5 +1,4 @@ class VacanciesController < ApplicationController - before_action :load_vacancy, only: %i[edit update destroy] verify_authorized only: %i[edit update destroy] def index @@ -14,7 +13,10 @@ def new @vacancy = Vacancy.new end - def edit; end + def edit + @vacancy = Vacancy.find(params[:id]) + authorize!(@vacancy) + end def create @vacancy = current_user.vacancies.build(vacancy_params) @@ -27,6 +29,9 @@ def create end def update + @vacancy = Vacancy.find(params[:id]) + authorize!(@vacancy) + if @vacancy.update(vacancy_params) redirect_to vacancy_path(@vacancy) else @@ -35,17 +40,15 @@ def update end def destroy + @vacancy = Vacancy.find(params[:id]) + authorize!(@vacancy) + @vacancy.destroy redirect_to vacancies_path end private - def load_vacancy - @vacancy = Vacancy.find(params[:id]) - authorize!(@vacancy) - end - def vacancy_params params.require(:vacancy).permit(:title, :body) end diff --git a/app/policies/application_policy.rb b/app/policies/application_policy.rb index a238c02..5508b43 100644 --- a/app/policies/application_policy.rb +++ b/app/policies/application_policy.rb @@ -1,6 +1,6 @@ class ApplicationPolicy < ActionPolicy::Base def allow_record - allow! if current_admin? || owner_record? + current_admin? || owner_record? end private diff --git a/app/policies/vacancy_policy.rb b/app/policies/vacancy_policy.rb index b00b04c..c3f57c8 100644 --- a/app/policies/vacancy_policy.rb +++ b/app/policies/vacancy_policy.rb @@ -2,6 +2,6 @@ class VacancyPolicy < ApplicationPolicy alias_rule :edit?, :destroy?, :update?, to: :manage? def manage? - allow_record + allowed_to?(:allow_record) end end diff --git a/spec/policies/vacancy_policy_spec.rb b/spec/policies/vacancy_policy_spec.rb index bd0aa62..07f14dc 100644 --- a/spec/policies/vacancy_policy_spec.rb +++ b/spec/policies/vacancy_policy_spec.rb @@ -1,35 +1,20 @@ require "rails_helper" -RSpec.describe VacancyPolicy, type: :policy do - let(:user) { build_stubbed(:user, :skip_admin_role) } - let(:vacancy) { build_stubbed(:vacancy, user:) } +RSpec.describe VacancyPolicy do + let(:user) { build_stubbed(:user, :skip_admin_role) } + let(:record) { build_stubbed(:vacancy, user:) } + let(:context) { { user: } } - let(:policy) { described_class.new(vacancy, user:) } + describe_rule :manage? do + succeed "when user is owner vacancy" - describe "#manage?" do - subject(:policy_result) { policy.apply(:manage?) } - - let(:rules) { %i[edit? update? destroy?] } - - it "is an alias of :edit, :update, :destroy rules" do - expect(rules).to all be_an_alias_of(policy, :manage?) - end - - context "when user is owner vacancy" do - it { expect(policy_result).to be_present } + succeed "when user is admin" do + let(:user) { build_stubbed(:user, :admin) } + let(:record) { build_stubbed(:vacancy) } end - context "when vacancy doesn`t belong user and he isn`t an admin" do - let(:vacancy) { build_stubbed(:vacancy) } - - it { expect(policy_result).not_to be_present } - end - - context "when vacancy doesn`t belong user but user is admin" do - let(:vacancy) { build_stubbed(:vacancy) } - let(:user) { build_stubbed(:user, :admin) } - - it { expect(policy_result).to be_present } + failed "when vacancy doesn`t belong user and he isn`t an admin" do + let(:record) { build_stubbed(:vacancy) } end end end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index bd8f593..87f7927 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -4,6 +4,8 @@ abort("The Rails environment is running in production mode!") if Rails.env.production? require 'rspec/rails' require "action_policy/rspec" +require "action_policy/rspec/dsl" + begin ActiveRecord::Migration.maintain_test_schema! rescue ActiveRecord::PendingMigrationError => e From 7533c0b603b46a5f3a320a5ca1aa02988b09436c Mon Sep 17 00:00:00 2001 From: Dmitry Proskurekov Date: Sun, 1 Oct 2023 21:24:44 +0700 Subject: [PATCH 04/12] remove callback verify_authorized, add action policy spec config --- .rubocop.yml | 3 +++ app/controllers/vacancies_controller.rb | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index ea6daab..8979311 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -3,6 +3,9 @@ require: - "rubocop-rspec" - "rubocop-factory_bot" +inherit_gem: + action_policy: config/rubocop-rspec.yml + AllCops: NewCops: enable TargetRubyVersion: 3.2 diff --git a/app/controllers/vacancies_controller.rb b/app/controllers/vacancies_controller.rb index d76a6a5..9c4583a 100644 --- a/app/controllers/vacancies_controller.rb +++ b/app/controllers/vacancies_controller.rb @@ -1,6 +1,4 @@ class VacanciesController < ApplicationController - verify_authorized only: %i[edit update destroy] - def index @vacancies = Vacancy.all end From e77268b3401bfbfb2a01bb1004bcd5e0165aac24 Mon Sep 17 00:00:00 2001 From: odanetpro Date: Mon, 2 Oct 2023 12:21:38 +0900 Subject: [PATCH 05/12] add default value for title --- app/controllers/vacancies_controller.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/controllers/vacancies_controller.rb b/app/controllers/vacancies_controller.rb index 9c4583a..6f96d1d 100644 --- a/app/controllers/vacancies_controller.rb +++ b/app/controllers/vacancies_controller.rb @@ -8,7 +8,9 @@ def show end def new - @vacancy = Vacancy.new + default_values = { title: current_user.name } + + @vacancy = Vacancy.new(default_values) end def edit From f0739c8ef8f71d39d3fbe4fe7db55ee95a5f6359 Mon Sep 17 00:00:00 2001 From: Alexander Abramov Date: Wed, 4 Oct 2023 15:58:18 +0700 Subject: [PATCH 06/12] added `locales` column for `users` --- app/models/user.rb | 1 + db/migrate/20231004085402_add_locales_to_users.rb | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 db/migrate/20231004085402_add_locales_to_users.rb diff --git a/app/models/user.rb b/app/models/user.rb index 3028027..e07ab20 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -27,4 +27,5 @@ class User < ApplicationRecord foreign_key: :recipient_id, dependent: :destroy, inverse_of: :recipient enum :role, %i[applicant company moderator admin] + enum :locale, %i[eng ru] end diff --git a/db/migrate/20231004085402_add_locales_to_users.rb b/db/migrate/20231004085402_add_locales_to_users.rb new file mode 100644 index 0000000..67937fb --- /dev/null +++ b/db/migrate/20231004085402_add_locales_to_users.rb @@ -0,0 +1,5 @@ +class AddLocalesToUsers < ActiveRecord::Migration[7.0] + def change + add_column :users, :locale, :integer, default: 0 + end +end From bfb009f5cd042ff4544737f0a6d709425ce45631 Mon Sep 17 00:00:00 2001 From: Alexander Abramov Date: Wed, 4 Oct 2023 16:32:37 +0700 Subject: [PATCH 07/12] updated user factory, added test for locale column --- spec/factories/users.rb | 1 + spec/models/user_spec.rb | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 3834cbc..ea188ca 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -19,6 +19,7 @@ name { Faker::Name.name } password { "password" } role { User.roles.keys.sample } + locale { User.locales.keys.sample } end trait :admin do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 10609ba..c7ad060 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -16,5 +16,10 @@ require "rails_helper" RSpec.describe User, type: :model do - pending "add some examples to (or delete) #{__FILE__}" + context "locales" do + it "defines the default locale is 'eng'" do + user = FactoryBot.build(:user) + expect(user.locale).to eq("eng") + end + end end From 0f7220bbdc945df011c50e890740047676c8f0e7 Mon Sep 17 00:00:00 2001 From: Alexander Abramov Date: Wed, 4 Oct 2023 17:44:16 +0700 Subject: [PATCH 08/12] fix eng to en in enum --- app/models/user.rb | 2 +- spec/models/user_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index e07ab20..2d91609 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -27,5 +27,5 @@ class User < ApplicationRecord foreign_key: :recipient_id, dependent: :destroy, inverse_of: :recipient enum :role, %i[applicant company moderator admin] - enum :locale, %i[eng ru] + enum :locale, %i[en ru] end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index c7ad060..9301482 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -17,9 +17,9 @@ RSpec.describe User, type: :model do context "locales" do - it "defines the default locale is 'eng'" do + it "defines by default english" do user = FactoryBot.build(:user) - expect(user.locale).to eq("eng") + expect(user.locale).to eq("en") end end end From 057ab58f20c2169f5f4780ff30a53807c896e414 Mon Sep 17 00:00:00 2001 From: Alexander Abramov Date: Wed, 4 Oct 2023 17:45:16 +0700 Subject: [PATCH 09/12] installed `rails-i18n` gem --- Gemfile | 1 + Gemfile.lock | 4 + config/application.rb | 4 + config/locales/ru.yml | 271 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 280 insertions(+) create mode 100644 config/locales/ru.yml diff --git a/Gemfile b/Gemfile index 8b51844..4de7049 100644 --- a/Gemfile +++ b/Gemfile @@ -14,6 +14,7 @@ gem "jbuilder" gem "kaminari", "~> 1.2", ">= 1.2.2" gem "puma", "~> 5.0" gem "rails", "~> 7.0.7", ">= 7.0.7.2" +gem "rails-i18n", "~> 7.0" gem "ransack", "~> 4.0.0" gem "redis", "~> 4.0" gem "slim-rails" diff --git a/Gemfile.lock b/Gemfile.lock index 7bb9ed2..5f93136 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -229,6 +229,9 @@ GEM rails-html-sanitizer (1.6.0) loofah (~> 2.21) nokogiri (~> 1.14) + rails-i18n (7.0.8) + i18n (>= 0.7, < 2) + railties (>= 6.0.0, < 8) railties (7.0.7.2) actionpack (= 7.0.7.2) activesupport (= 7.0.7.2) @@ -394,6 +397,7 @@ DEPENDENCIES kaminari (~> 1.2, >= 1.2.2) puma (~> 5.0) rails (~> 7.0.7, >= 7.0.7.2) + rails-i18n (~> 7.0) ransack (~> 4.0.0) redis (~> 4.0) rspec (~> 3.12) diff --git a/config/application.rb b/config/application.rb index fea3eca..f010c31 100644 --- a/config/application.rb +++ b/config/application.rb @@ -20,5 +20,9 @@ class Application < Rails::Application # config.eager_load_paths << Rails.root.join("extras") config.generators.test_framework = :rspec + + # i18n + config.i18n.available_locales = %i[en ru] + config.i18n.default_locale = :en end end diff --git a/config/locales/ru.yml b/config/locales/ru.yml new file mode 100644 index 0000000..81161ed --- /dev/null +++ b/config/locales/ru.yml @@ -0,0 +1,271 @@ +--- +ru: + activerecord: + errors: + messages: + record_invalid: 'Возникли ошибки: %{errors}' + restrict_dependent_destroy: + has_one: 'Невозможно удалить запись, так как существует зависимость: %{record}' + has_many: 'Невозможно удалить запись, так как существуют зависимости: %{record}' + date: + abbr_day_names: + - Вс + - Пн + - Вт + - Ср + - Чт + - Пт + - Сб + abbr_month_names: + - + - янв. + - февр. + - марта + - апр. + - мая + - июня + - июля + - авг. + - сент. + - окт. + - нояб. + - дек. + day_names: + - воскресенье + - понедельник + - вторник + - среда + - четверг + - пятница + - суббота + formats: + default: "%d.%m.%Y" + long: "%-d %B %Y" + short: "%-d %b" + month_names: + - + - января + - февраля + - марта + - апреля + - мая + - июня + - июля + - августа + - сентября + - октября + - ноября + - декабря + order: + - :day + - :month + - :year + datetime: + distance_in_words: + about_x_hours: + one: около %{count} часа + few: около %{count} часов + many: около %{count} часов + other: около %{count} часов + about_x_months: + one: около %{count} месяца + few: около %{count} месяцев + many: около %{count} месяцев + other: около %{count} месяцев + about_x_years: + one: около %{count} года + few: около %{count} лет + many: около %{count} лет + other: около %{count} лет + almost_x_years: + one: почти %{count} год + few: почти %{count} года + many: почти %{count} лет + other: почти %{count} лет + half_a_minute: полминуты + less_than_x_seconds: + one: меньше %{count} секунды + few: меньше %{count} секунд + many: меньше %{count} секунд + other: меньше %{count} секунд + less_than_x_minutes: + one: меньше %{count} минуты + few: меньше %{count} минут + many: меньше %{count} минут + other: меньше %{count} минут + over_x_years: + one: больше %{count} года + few: больше %{count} лет + many: больше %{count} лет + other: больше %{count} лет + x_seconds: + one: "%{count} секунда" + few: "%{count} секунды" + many: "%{count} секунд" + other: "%{count} секунд" + x_minutes: + one: "%{count} минута" + few: "%{count} минуты" + many: "%{count} минут" + other: "%{count} минут" + x_days: + one: "%{count} день" + few: "%{count} дня" + many: "%{count} дней" + other: "%{count} дней" + x_months: + one: "%{count} месяц" + few: "%{count} месяца" + many: "%{count} месяцев" + other: "%{count} месяцев" + x_years: + one: "%{count} год" + few: "%{count} года" + many: "%{count} лет" + other: "%{count} лет" + prompts: + second: Секунда + minute: Минута + hour: Час + day: День + month: Месяц + year: Год + errors: + format: "%{attribute} %{message}" + messages: + accepted: нужно подтвердить + blank: не может быть пустым + confirmation: не совпадает со значением поля %{attribute} + empty: не может быть пустым + equal_to: может иметь лишь значение, равное %{count} + even: может иметь лишь четное значение + exclusion: имеет зарезервированное значение + greater_than: может иметь значение большее %{count} + greater_than_or_equal_to: может иметь значение большее или равное %{count} + in: должно быть в диапазоне %{count} + inclusion: имеет непредусмотренное значение + invalid: имеет неверное значение + less_than: может иметь значение меньшее чем %{count} + less_than_or_equal_to: может иметь значение меньшее или равное %{count} + model_invalid: 'Возникли ошибки: %{errors}' + not_a_number: не является числом + not_an_integer: не является целым числом + odd: может иметь лишь нечетное значение + other_than: должно отличаться от %{count} + present: нужно оставить пустым + required: не может отсутствовать + taken: уже существует + too_long: + one: слишком большой длины (не может быть больше чем %{count} символ) + few: слишком большой длины (не может быть больше чем %{count} символа) + many: слишком большой длины (не может быть больше чем %{count} символов) + other: слишком большой длины (не может быть больше чем %{count} символа) + too_short: + one: недостаточной длины (не может быть меньше %{count} символа) + few: недостаточной длины (не может быть меньше %{count} символов) + many: недостаточной длины (не может быть меньше %{count} символов) + other: недостаточной длины (не может быть меньше %{count} символа) + wrong_length: + one: неверной длины (может быть длиной ровно %{count} символ) + few: неверной длины (может быть длиной ровно %{count} символа) + many: неверной длины (может быть длиной ровно %{count} символов) + other: неверной длины (может быть длиной ровно %{count} символа) + template: + body: 'Проблемы возникли со следующими полями:' + header: + one: "%{model}: сохранение не удалось из-за %{count} ошибки" + few: "%{model}: сохранение не удалось из-за %{count} ошибок" + many: "%{model}: сохранение не удалось из-за %{count} ошибок" + other: "%{model}: сохранение не удалось из-за %{count} ошибки" + helpers: + select: + prompt: 'Выберите: ' + submit: + create: Создать %{model} + submit: Сохранить %{model} + update: Сохранить %{model} + number: + currency: + format: + delimiter: " " + format: "%n %u" + precision: 2 + separator: "," + significant: false + strip_insignificant_zeros: false + unit: руб. + format: + delimiter: " " + precision: 3 + round_mode: default + separator: "," + significant: false + strip_insignificant_zeros: false + human: + decimal_units: + format: "%n %u" + units: + billion: + one: миллиард + few: миллиардов + many: миллиардов + other: миллиардов + million: + one: миллион + few: миллионов + many: миллионов + other: миллионов + quadrillion: + one: квадриллион + few: квадриллионов + many: квадриллионов + other: квадриллионов + thousand: + one: тысяча + few: тысяч + many: тысяч + other: тысяч + trillion: + one: триллион + few: триллионов + many: триллионов + other: триллионов + unit: '' + format: + delimiter: '' + precision: 1 + significant: false + strip_insignificant_zeros: false + storage_units: + format: "%n %u" + units: + byte: + one: байт + few: байта + many: байт + other: байта + eb: ЭБ + gb: ГБ + kb: КБ + mb: МБ + pb: ПБ + tb: ТБ + percentage: + format: + delimiter: '' + format: "%n%" + precision: + format: + delimiter: '' + support: + array: + last_word_connector: " и " + two_words_connector: " и " + words_connector: ", " + time: + am: утра + formats: + default: "%a, %d %b %Y, %H:%M:%S %z" + long: "%d %B %Y, %H:%M" + short: "%d %b, %H:%M" + pm: вечера From 6ac98bd31eba78214b810ed724cbeb0ca980a4ea Mon Sep 17 00:00:00 2001 From: Alexander Abramov Date: Wed, 4 Oct 2023 17:57:10 +0700 Subject: [PATCH 10/12] rubocop code --- spec/models/user_spec.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 9301482..04f4aae 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -16,10 +16,8 @@ require "rails_helper" RSpec.describe User, type: :model do - context "locales" do - it "defines by default english" do - user = FactoryBot.build(:user) - expect(user.locale).to eq("en") - end + it "defines by default english" do + user = build(:user) + expect(user.locale).to eq("en") end end From f3a201d6e5252f969223e42de8e676d0d48d4607 Mon Sep 17 00:00:00 2001 From: Alexander Abramov Date: Wed, 4 Oct 2023 17:58:20 +0700 Subject: [PATCH 11/12] db was migrated --- db/schema.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index d56a53a..7bc7e21 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_10_01_053615) do +ActiveRecord::Schema[7.0].define(version: 2023_10_04_085402) do create_table "action_text_rich_texts", force: :cascade do |t| t.string "name", null: false t.text "body" @@ -24,8 +24,8 @@ create_table "active_storage_attachments", force: :cascade do |t| t.string "name", null: false t.string "record_type", null: false - t.bigint "record_id", null: false - t.bigint "blob_id", null: false + t.integer "record_id", null: false + t.integer "blob_id", null: false t.datetime "created_at", null: false t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true @@ -44,7 +44,7 @@ end create_table "active_storage_variant_records", force: :cascade do |t| - t.bigint "blob_id", null: false + t.integer "blob_id", null: false t.string "variation_digest", null: false t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true end @@ -91,7 +91,7 @@ t.datetime "created_at", null: false t.datetime "updated_at", null: false t.integer "status", default: 0 - t.string "name", null: false + t.string "name", default: "", null: false t.index ["user_id"], name: "index_resumes_on_user_id" end @@ -105,6 +105,7 @@ t.datetime "updated_at", null: false t.integer "role", default: 0 t.string "name" + t.integer "locale", default: 0 t.index ["email"], name: "index_users_on_email", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true end From 0c521481f4264cfe845c6d593f7e95559fc65c56 Mon Sep 17 00:00:00 2001 From: Alexander Abramov Date: Mon, 9 Oct 2023 14:01:09 +0700 Subject: [PATCH 12/12] changed enum column to default string value, added validation --- app/models/user.rb | 4 +++- db/migrate/20231004085402_add_locales_to_users.rb | 2 +- db/schema.rb | 8 ++++---- spec/factories/users.rb | 3 ++- spec/models/user_spec.rb | 1 + 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index 2d91609..ad7aec1 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -12,6 +12,7 @@ # updated_at :datetime not null # role :integer default("applicant") # name :string +# locale :string default("en") # class User < ApplicationRecord devise :database_authenticatable, :registerable, @@ -27,5 +28,6 @@ class User < ApplicationRecord foreign_key: :recipient_id, dependent: :destroy, inverse_of: :recipient enum :role, %i[applicant company moderator admin] - enum :locale, %i[en ru] + + validates :locale, presence: true end diff --git a/db/migrate/20231004085402_add_locales_to_users.rb b/db/migrate/20231004085402_add_locales_to_users.rb index 67937fb..3ef30cc 100644 --- a/db/migrate/20231004085402_add_locales_to_users.rb +++ b/db/migrate/20231004085402_add_locales_to_users.rb @@ -1,5 +1,5 @@ class AddLocalesToUsers < ActiveRecord::Migration[7.0] def change - add_column :users, :locale, :integer, default: 0 + add_column :users, :locale, :string, default: "en" end end diff --git a/db/schema.rb b/db/schema.rb index 7bc7e21..95d3326 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -24,8 +24,8 @@ create_table "active_storage_attachments", force: :cascade do |t| t.string "name", null: false t.string "record_type", null: false - t.integer "record_id", null: false - t.integer "blob_id", null: false + t.bigint "record_id", null: false + t.bigint "blob_id", null: false t.datetime "created_at", null: false t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true @@ -44,7 +44,7 @@ end create_table "active_storage_variant_records", force: :cascade do |t| - t.integer "blob_id", null: false + t.bigint "blob_id", null: false t.string "variation_digest", null: false t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true end @@ -105,7 +105,7 @@ t.datetime "updated_at", null: false t.integer "role", default: 0 t.string "name" - t.integer "locale", default: 0 + t.string "locale", default: "en" t.index ["email"], name: "index_users_on_email", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index ea188ca..14d9b98 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -12,6 +12,7 @@ # updated_at :datetime not null # role :integer default("applicant") # name :string +# locale :string default("en") # FactoryBot.define do factory :user do @@ -19,7 +20,7 @@ name { Faker::Name.name } password { "password" } role { User.roles.keys.sample } - locale { User.locales.keys.sample } + locale { "en" } end trait :admin do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 04f4aae..071b294 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -12,6 +12,7 @@ # updated_at :datetime not null # role :integer default("applicant") # name :string +# locale :string default("en") # require "rails_helper"