diff --git a/app/models/account.rb b/app/models/account.rb index 8048a92..c774283 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -15,6 +15,8 @@ class Account < ApplicationRecord has_one :user + has_many :sessions + ############# # Callbacks # ############# diff --git a/app/models/session.rb b/app/models/session.rb new file mode 100644 index 0000000..d0bfaed --- /dev/null +++ b/app/models/session.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class Session < ApplicationRecord + ################ + # Associations # + ################ + + belongs_to :account + + ############### + # Validations # + ############### + + validates :ip_address, presence: true +end diff --git a/db/migrate/20181129203927_initial_migration.rb b/db/migrate/20181129203927_initial_migration.rb index f034622..45036c4 100644 --- a/db/migrate/20181129203927_initial_migration.rb +++ b/db/migrate/20181129203927_initial_migration.rb @@ -266,6 +266,14 @@ private null: false, index: { unique: true }, foreign_key: true end + create_table :sessions do |t| + t.timestamps null: false + + t.references :account, null: false, index: true, foreign_key: true + + t.string :ip_address, null: false + end + create_table :person_comments do |t| t.timestamps null: false @@ -385,6 +393,10 @@ private end def change_constraints + constraint :sessions, :ip_address, <<~SQL + is_good_small_text(ip_address) + SQL + constraint :regional_offices, :name, <<~SQL is_good_small_text(name) SQL diff --git a/db/structure.sql b/db/structure.sql index 3e99dcc..0bacb32 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -728,6 +728,39 @@ CREATE TABLE public.schema_migrations ( ); +-- +-- Name: sessions; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.sessions ( + id bigint NOT NULL, + created_at timestamp(6) without time zone NOT NULL, + updated_at timestamp(6) without time zone NOT NULL, + account_id bigint NOT NULL, + ip_address character varying NOT NULL, + CONSTRAINT ip_address CHECK (public.is_good_small_text((ip_address)::text)) +); + + +-- +-- Name: sessions_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.sessions_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: sessions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.sessions_id_seq OWNED BY public.sessions.id; + + -- -- Name: user_omniauths; Type: TABLE; Schema: public; Owner: - -- @@ -894,6 +927,13 @@ ALTER TABLE ONLY public.regional_offices ALTER COLUMN id SET DEFAULT nextval('pu ALTER TABLE ONLY public.relationships ALTER COLUMN id SET DEFAULT nextval('public.relationships_id_seq'::regclass); +-- +-- Name: sessions id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.sessions ALTER COLUMN id SET DEFAULT nextval('public.sessions_id_seq'::regclass); + + -- -- Name: user_omniauths id; Type: DEFAULT; Schema: public; Owner: - -- @@ -1020,6 +1060,14 @@ ALTER TABLE ONLY public.schema_migrations ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version); +-- +-- Name: sessions sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.sessions + ADD CONSTRAINT sessions_pkey PRIMARY KEY (id); + + -- -- Name: user_omniauths user_omniauths_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -1239,6 +1287,13 @@ CREATE INDEX index_relationships_on_role ON public.relationships USING btree (ro CREATE INDEX index_relationships_on_status ON public.relationships USING btree (status); +-- +-- Name: index_sessions_on_account_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_sessions_on_account_id ON public.sessions USING btree (account_id); + + -- -- Name: index_user_omniauths_on_remote_id_and_provider; Type: INDEX; Schema: public; Owner: - -- @@ -1333,6 +1388,14 @@ ALTER TABLE ONLY public.people ADD CONSTRAINT fk_rails_4f02f930eb FOREIGN KEY (contact_list_id) REFERENCES public.contact_lists(id); +-- +-- Name: sessions fk_rails_5599381559; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.sessions + ADD CONSTRAINT fk_rails_5599381559 FOREIGN KEY (account_id) REFERENCES public.accounts(id); + + -- -- Name: passports fk_rails_5cdfa39dea; Type: FK CONSTRAINT; Schema: public; Owner: - -- diff --git a/factories/sessions.rb b/factories/sessions.rb new file mode 100644 index 0000000..0a9820e --- /dev/null +++ b/factories/sessions.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :some_session, class: Session do + association :account, factory: :usual_account + + ip_address { Faker::Internet.ip_v4_address } + + trait :with_ipv6_address do + ip_address { Faker::Internet.ip_v6_address } + end + end + + factory :some_session_with_ipv4_address, + parent: :some_session, + traits: %i[with_ipv6_address] +end diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index 622acfa..e4b180b 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -23,6 +23,14 @@ RSpec.describe Account do it { is_expected.not_to validate_presence_of :user } end + describe '#sessions' do + it do + is_expected.to \ + have_many(:sessions) + .dependent(:restrict_with_exception) + end + end + describe '#person' do it { is_expected.to belong_to(:person).optional } diff --git a/spec/models/session_spec.rb b/spec/models/session_spec.rb new file mode 100644 index 0000000..cb3c48f --- /dev/null +++ b/spec/models/session_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Session do + subject { create :some_session } + + describe '#account' do + it { is_expected.to belong_to(:account).required } + + it { is_expected.to validate_presence_of(:account).with_message(:required) } + end + + describe '#ip_address' do + it { is_expected.to validate_presence_of :ip_address } + end +end