diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 4224b2942..2dfccf0dd 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -97,7 +97,7 @@ def user_params :github_handle, :twitter_handle, :irc_handle, :name, :email, :homepage, :location, :bio, :tech_expertise_list, :tech_interest_list, - :tshirt_size, :tshirt_cut, :postal_address, :timezone, + :tshirt_size, :tshirt_cut, :timezone, :country, :hide_email, :is_company, :company_name, :company_info, @@ -107,7 +107,8 @@ def user_params :application_learning_history, :application_skills, :application_code_samples, :application_location, :application_minimum_money, :application_money, :application_goals, :application_code_background, interested_in: [], - roles_attributes: [:id, :name, :team_id, :_destroy] + roles_attributes: [:id, :name, :team_id, :_destroy], + postal_address_attributes: [:id, :line1, :line2, :city, :state, :zip, :country, :_destroy] ) end end diff --git a/app/models/postal_address.rb b/app/models/postal_address.rb new file mode 100644 index 000000000..58fa06d43 --- /dev/null +++ b/app/models/postal_address.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true +class PostalAddress < ApplicationRecord + belongs_to :user + + validates_presence_of :line1, :city, :zip, :country +end diff --git a/app/models/user.rb b/app/models/user.rb index 1d5732086..9d9691ce4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -65,6 +65,7 @@ def student has_many :applications, through: :teams has_many :todos, dependent: :destroy has_many :comments, dependent: :destroy + has_one :postal_address, dependent: :destroy validates :github_handle, presence: true, uniqueness: { case_sensitive: false } validates :homepage, format: { with: URL_PREFIX_PATTERN }, allow_blank: true @@ -73,6 +74,7 @@ def student validates :name, :email, :country, :location, presence: true, unless: :github_import accepts_nested_attributes_for :roles, allow_destroy: true + accepts_nested_attributes_for :postal_address, allow_destroy: true, reject_if: :all_blank before_save :normalize_location after_create :complete_from_github diff --git a/app/views/postal_addresses/_postal_address.html.slim b/app/views/postal_addresses/_postal_address.html.slim new file mode 100644 index 000000000..ab5f0ef82 --- /dev/null +++ b/app/views/postal_addresses/_postal_address.html.slim @@ -0,0 +1,3 @@ += @user.postal_address.line1.titlecase + " " + @user.postal_address.line2.titlecase + " " += @user.postal_address.city.titlecase + ", " + @user.postal_address.state.titlecase + " " += @user.postal_address.zip + " " +@user.postal_address.country diff --git a/app/views/users/edit.html.slim b/app/views/users/edit.html.slim index 28a1df06f..e712af174 100644 --- a/app/views/users/edit.html.slim +++ b/app/views/users/edit.html.slim @@ -107,7 +107,19 @@ p.help-block This information will only be visible to yourself and the organizers. = f.input :tshirt_size, as: :select, collection: User::TSHIRT_SIZES.map { |k| [k, k] }, label: 'T-Shirt size', blank: false, required: false, hint: 'For sponsor T-Shirts, in case they send some.' = f.input :tshirt_cut, as: :select, collection: User::TSHIRT_CUTS.map { |s| [s, s] }, label: 'T-Shirt cut', include_blank: true - = f.input :postal_address, hint: "Please give your postal address, including your full name, so we can send things we've received from our sponsors for you :)" + h4 Shipping Address + = f.simple_fields_for :postal_address_attributes, @user.postal_address do |pa| + - if @user.postal_address + = pa.input :id, as: :hidden, input_html: { value: @user.postal_address.id } + = pa.check_box '_destroy' + | Remove Address + = pa.input :line1, required: false + = pa.input :line2, required: false + = pa.input :city, required: false + = pa.input :state, required: false + = pa.input :zip, required: false + = pa.input :country, prompt: "Select your country", required: false, include_blank: true + - if admin? h3.page-header Roles diff --git a/app/views/users/show.html.slim b/app/views/users/show.html.slim index 36db984d6..25ca61d94 100644 --- a/app/views/users/show.html.slim +++ b/app/views/users/show.html.slim @@ -65,9 +65,13 @@ nav.actions p = @user.company_info - if can_see_private_info? - - fields = ['tshirt_size', 'tshirt_cut', 'postal_address'] .well.private-info h3 Private info + - if @user.postal_address + h4 Postal Address + p + = render @user.postal_address + - fields = ['tshirt_size', 'tshirt_cut'] - fields.each do |field| - if @user.send(field).present? p diff --git a/db/migrate/20181107171037_create_postal_addresses.rb b/db/migrate/20181107171037_create_postal_addresses.rb new file mode 100644 index 000000000..0606cbdb8 --- /dev/null +++ b/db/migrate/20181107171037_create_postal_addresses.rb @@ -0,0 +1,15 @@ +class CreatePostalAddresses < ActiveRecord::Migration[5.1] + def change + create_table :postal_addresses do |t| + t.string :address_line_1 + t.string :address_line_2 + t.string :city + t.string :state_or_province + t.string :postal_code + t.string :country + + t.references :user, foreign_key: true + t.timestamps + end + end +end diff --git a/db/migrate/20181107172409_remove_postal_address_from_users.rb b/db/migrate/20181107172409_remove_postal_address_from_users.rb new file mode 100644 index 000000000..0c1cf5ee2 --- /dev/null +++ b/db/migrate/20181107172409_remove_postal_address_from_users.rb @@ -0,0 +1,5 @@ +class RemovePostalAddressFromUsers < ActiveRecord::Migration[5.1] + def change + remove_column :users, :postal_address, :text + end +end diff --git a/db/migrate/20181113210909_fix_postal_address_column_names.rb b/db/migrate/20181113210909_fix_postal_address_column_names.rb new file mode 100644 index 000000000..2f22bcf78 --- /dev/null +++ b/db/migrate/20181113210909_fix_postal_address_column_names.rb @@ -0,0 +1,8 @@ +class FixPostalAddressColumnNames < ActiveRecord::Migration[5.1] + def change + rename_column :postal_addresses, :address_line_1, :line1 + rename_column :postal_addresses, :address_line_2, :line2 + rename_column :postal_addresses, :state_or_province, :state + rename_column :postal_addresses, :postal_code, :zip + end +end diff --git a/db/schema.rb b/db/schema.rb index 98eff50a1..902d6289b 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.define(version: 20180714153306) do +ActiveRecord::Schema.define(version: 20181113210909) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -173,6 +173,19 @@ t.index ["user_id"], name: "index_notes_on_user_id" end + create_table "postal_addresses", force: :cascade do |t| + t.string "line1" + t.string "line2" + t.string "city" + t.string "state" + t.string "zip" + t.string "country" + t.bigint "user_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["user_id"], name: "index_postal_addresses_on_user_id" + end + create_table "projects", id: :serial, force: :cascade do |t| t.string "name", limit: 255 t.datetime "created_at" @@ -296,7 +309,6 @@ t.string "twitter_handle", limit: 255 t.string "irc_handle", limit: 255 t.string "tshirt_size", limit: 255 - t.text "postal_address" t.string "timezone", limit: 255 t.string "interested_in", limit: 255, default: [], array: true t.boolean "hide_email" @@ -339,5 +351,6 @@ t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true end + add_foreign_key "postal_addresses", "users" add_foreign_key "teams", "projects" end diff --git a/spec/factories/postal_address.rb b/spec/factories/postal_address.rb new file mode 100644 index 000000000..74893f5cb --- /dev/null +++ b/spec/factories/postal_address.rb @@ -0,0 +1,11 @@ +FactoryBot.define do + factory :postal_address do + user + line1 { FFaker::AddressUS.street_address } + line2 { FFaker::AddressUS.secondary_address } + city { FFaker::AddressUS.city} + state { FFaker::AddressUS.state} + zip { FFaker::AddressUS.zip_code} + country { "United States" } + end +end diff --git a/spec/features/users/postal_address_spec.rb b/spec/features/users/postal_address_spec.rb new file mode 100644 index 000000000..a0c268aa2 --- /dev/null +++ b/spec/features/users/postal_address_spec.rb @@ -0,0 +1,69 @@ +require 'rails_helper' + +RSpec.describe 'Add Postal Address', type: :feature do + let(:user) { create(:user) } + let(:address) { create(:postal_address) } + + context 'signed in' do + before { sign_in user } + + context 'in the user edit page' do + before { visit edit_user_path(user) } + + it 'allows creation of postal address if all required address fields are entered' do + fill_in 'Line1', with: address.line1 + fill_in 'Line2', with: address.line2 + fill_in 'City', with: address.city + fill_in 'State', with: address.state + fill_in 'Zip', with: address.zip + select address.country, from: 'Country' + click_on 'Save' + + expect(current_path).to eq user_path(user) + + expect(page).to have_content address.line1 + expect(page).to have_content address.line2 + expect(page).to have_content address.city + expect(page).to have_content address.state + expect(page).to have_content address.zip + expect(page).to have_content 'US' + end + + it 'does not allow a postal address to be added if required fields are missing' do + fill_in 'Line1', with: address.line1 + fill_in 'Zip', with: address.zip + click_on 'Save' + + expect(page).to have_content "Postal address city can't be blank" + expect(page).to have_content "Postal address country can't be blank" + end + end + + context 'when the user already has a postal address set up' do + let!(:postal_address) { create(:postal_address, user: user) } + + it 'autofills saved postal address info on edit form if it exists' do + visit edit_user_path(user) + + expect(page).to have_selector("input[value='#{user.postal_address.line1}']") + expect(page).to have_selector("input[value='#{user.postal_address.city}']") + expect(page).to have_selector("input[value='#{user.postal_address.state}']") + expect(page).to have_selector("input[value='#{user.postal_address.zip}']") + end + + it 'allows to delete an existing postal address' do + visit edit_user_path(user) + + check 'user[postal_address_attributes][_destroy]' + click_on 'Save' + + expect(current_path).to eq user_path(user) + expect(page).to_not have_content postal_address.line1 + expect(page).to_not have_content postal_address.line2 + expect(page).to_not have_content postal_address.city + expect(page).to_not have_content postal_address.state + expect(page).to_not have_content postal_address.zip + end + end + end +end diff --git a/spec/models/postal_address_spec.rb b/spec/models/postal_address_spec.rb new file mode 100644 index 000000000..36a11336c --- /dev/null +++ b/spec/models/postal_address_spec.rb @@ -0,0 +1,14 @@ +require 'rails_helper' + +RSpec.describe PostalAddress, type: :model do + describe 'associations' do + it { is_expected.to belong_to(:user) } + end + + describe 'validations' do + it { is_expected.to validate_presence_of(:line1)} + it { is_expected.to validate_presence_of(:city)} + it { is_expected.to validate_presence_of(:zip)} + it { is_expected.to validate_presence_of(:country)} + end +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index b11c3378b..2b4cd878c 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -12,6 +12,7 @@ it { is_expected.to have_many(:applications).through(:teams) } it { is_expected.to have_many(:todos).dependent(:destroy) } it { is_expected.to have_many(:comments).dependent(:destroy) } + it { is_expected.to have_one(:postal_address).dependent(:destroy) } end describe 'validations' do