[deploy] Add optional fields to user (#7246)
* add optional fields to user - this provides the back-end implementation for #2365 * fix mistakes in schema.rb * renamed OptionalField to userOptionalField * rename field column in user_optional_fields to label * add uniqueness validation on user_optional_field labels * scope flag uniqueness to user_id * add indexing on label in user_optional_fields * add optional fields to user - this provides the back-end implementation for #2365 * fix mistakes in schema.rb * add index on user_id for user_optional_fields * Remove duplicate model * Fix schema * Re-add past indexes * Remove old index * Remove another old index * add `null:false` to columns in optional fields * add `null: false` to the migration - Updated test to account for the null constraint * add null:false to user_id on user_optional_tables Co-authored-by: rhymes <rhymesete@gmail.com> Co-authored-by: Ben Halpern <bendhalpern@gmail.com>
This commit is contained in:
parent
3311023163
commit
131d11aa73
8 changed files with 76 additions and 1 deletions
|
|
@ -73,6 +73,7 @@ class User < ApplicationRecord
|
|||
has_many :messages, dependent: :destroy
|
||||
has_many :notes, as: :noteable, inverse_of: :noteable
|
||||
has_many :notification_subscriptions, dependent: :destroy
|
||||
has_many :user_optional_fields, dependent: :destroy
|
||||
has_many :notifications, dependent: :destroy
|
||||
has_many :offender_feedback_messages, class_name: "FeedbackMessage", inverse_of: :offender, foreign_key: :offender_id, dependent: :nullify
|
||||
has_many :organization_memberships, dependent: :destroy
|
||||
|
|
|
|||
13
app/models/user_optional_field.rb
Normal file
13
app/models/user_optional_field.rb
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
class UserOptionalField < ApplicationRecord
|
||||
belongs_to :user
|
||||
|
||||
validates :label, presence: true, length: { maximum: 30 }, uniqueness: { scope: :user_id }
|
||||
validates :value, presence: true, length: { maximum: 128 }
|
||||
validate :validate_quota
|
||||
|
||||
def validate_quota
|
||||
return unless user
|
||||
|
||||
errors.add(:user_id, "already has the maximum allowable optional fields") unless user.user_optional_fields.count < 3
|
||||
end
|
||||
end
|
||||
13
db/migrate/20200412194408_create_user_optional_fields.rb
Normal file
13
db/migrate/20200412194408_create_user_optional_fields.rb
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
class CreateUserOptionalFields < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :user_optional_fields do |t|
|
||||
t.string :label, null: false
|
||||
t.string :value, null: false
|
||||
t.references :user, foreign_key: true, null: false
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :user_optional_fields, [:label, :user_id], unique: true
|
||||
end
|
||||
end
|
||||
11
db/schema.rb
11
db/schema.rb
|
|
@ -1086,6 +1086,16 @@ ActiveRecord::Schema.define(version: 2020_04_26_124118) do
|
|||
t.index ["user_id"], name: "index_user_counters_on_user_id", unique: true
|
||||
end
|
||||
|
||||
create_table "user_optional_fields", force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.string "label", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.bigint "user_id", null: false
|
||||
t.string "value", null: false
|
||||
t.index ["label", "user_id"], name: "index_user_optional_fields_on_label_and_user_id", unique: true
|
||||
t.index ["user_id"], name: "index_user_optional_fields_on_user_id"
|
||||
end
|
||||
|
||||
create_table "users", id: :serial, force: :cascade do |t|
|
||||
t.integer "articles_count", default: 0, null: false
|
||||
t.string "available_for"
|
||||
|
|
@ -1268,6 +1278,7 @@ ActiveRecord::Schema.define(version: 2020_04_26_124118) do
|
|||
add_foreign_key "user_blocks", "users", column: "blocked_id"
|
||||
add_foreign_key "user_blocks", "users", column: "blocker_id"
|
||||
add_foreign_key "user_counters", "users", on_delete: :cascade
|
||||
add_foreign_key "user_optional_fields", "users"
|
||||
add_foreign_key "users_roles", "users", on_delete: :cascade
|
||||
add_foreign_key "webhook_endpoints", "oauth_applications"
|
||||
add_foreign_key "webhook_endpoints", "users"
|
||||
|
|
|
|||
7
spec/factories/user_optional_fields.rb
Normal file
7
spec/factories/user_optional_fields.rb
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
FactoryBot.define do
|
||||
factory :user_optional_field do
|
||||
user
|
||||
label { "Pronoun" }
|
||||
value { "They/them" }
|
||||
end
|
||||
end
|
||||
|
|
@ -136,5 +136,13 @@ FactoryBot.define do
|
|||
user.add_role :tag_moderator, tag
|
||||
end
|
||||
end
|
||||
|
||||
trait :with_user_optional_fields do
|
||||
after(:create) do |user|
|
||||
create(:user_optional_field, user: user)
|
||||
create(:user_optional_field, user: user, label: "another field1", value: "another value1")
|
||||
create(:user_optional_field, user: user, label: "another field2", value: "another value2")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
14
spec/models/user_optional_field_spec.rb
Normal file
14
spec/models/user_optional_field_spec.rb
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe UserOptionalField, type: :model do
|
||||
subject { user_optional_field }
|
||||
|
||||
let(:user_optional_field) { create(:user_optional_field) }
|
||||
|
||||
it { is_expected.to belong_to(:user) }
|
||||
it { is_expected.to validate_presence_of(:label) }
|
||||
it { is_expected.to validate_uniqueness_of(:label).scoped_to(:user_id) }
|
||||
it { is_expected.to validate_length_of(:label).is_at_most(30) }
|
||||
it { is_expected.to validate_presence_of(:value) }
|
||||
it { is_expected.to validate_length_of(:value).is_at_most(128) }
|
||||
end
|
||||
|
|
@ -12,6 +12,7 @@ end
|
|||
RSpec.describe User, type: :model do
|
||||
let(:user) { create(:user) }
|
||||
let(:other_user) { create(:user) }
|
||||
let(:user_with_user_optional_fields) { create(:user, :with_user_optional_fields) }
|
||||
let(:org) { create(:organization) }
|
||||
|
||||
before { mock_auth_hash }
|
||||
|
|
@ -132,9 +133,16 @@ RSpec.describe User, type: :model do
|
|||
end
|
||||
# rubocop:enable RSpec/NamedSubject
|
||||
|
||||
it "has at most three optional fields" do
|
||||
expect(user_with_user_optional_fields).to have_many(:user_optional_fields).dependent(:destroy)
|
||||
fourth_field = user_with_user_optional_fields.user_optional_fields.create(label: "some field", value: "some value")
|
||||
expect(fourth_field).not_to be_valid
|
||||
end
|
||||
|
||||
it { is_expected.to have_many(:organization_memberships).dependent(:destroy) }
|
||||
it { is_expected.to have_one(:counters).class_name("UserCounter").dependent(:destroy) }
|
||||
it { is_expected.to have_one(:pro_membership).dependent(:destroy) }
|
||||
|
||||
it { is_expected.to validate_uniqueness_of(:username).case_insensitive }
|
||||
it { is_expected.not_to allow_value("#xyz").for(:bg_color_hex) }
|
||||
it { is_expected.not_to allow_value("#xyz").for(:text_color_hex) }
|
||||
it { is_expected.not_to allow_value("AcMe_1%").for(:username) }
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue