Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HER- 66 creating address controller #58

Merged
merged 8 commits into from
Jan 14, 2025
41 changes: 41 additions & 0 deletions app/controllers/api/v1/addresses_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
class Api::V1::AddressesController < ApplicationController
before_action :set_addressable

def create
@address = @addressable.addresses.build(address_params)
if @address.save
render json: @address, status: :created
else
render json: @address.errors, status: :unprocessable_entity
end
end

def update
@address = @addressable.addresses.find(params[:id])
if @address.update(address_params)
render json: @address, status: :ok
else
render json: @address.errors, status: :unprocessable_entity
end
end

def destroy
@address = @addressable.addresses.find(params[:id])
@address.destroy
head :no_content
end

private

def set_addressable
@addressable = if params[:user_id]
User.find(params[:user_id])
elsif params[:organization_id]
Organization.find(params[:organization_id])
end
end

def address_params
params.require(:address).permit(:street_address, :city, :state, :postal_code, :save_to_user)
end
end
21 changes: 19 additions & 2 deletions app/controllers/api/v1/orders_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ def index

# POST /api/v1/orders
def create
@order.user = current_user # Automatically associate user

@order = Order.new(order_params)
@order.user = current_user
if @order.save
associate_address_with_user(@order)
render json: @order, status: :created
else
render json: { errors: @order.errors.full_messages }, status: :unprocessable_entity
Expand All @@ -25,6 +26,7 @@ def show
# PATCH/PUT /api/v1/orders/:id
def update
if @order.update(order_params)
associate_address_with_user(@order)
render json: @order, status: :ok
else
render json: { errors: @order.errors.full_messages }, status: :unprocessable_entity
Expand All @@ -40,7 +42,22 @@ def destroy

private

def set_order
@order = Order.find(params[:id])
end

def order_params
params.require(:order).permit(:phone, :address_id, :school_year, :comments, :product_id, :product_type)
end

def associate_address_with_user(order)
if order.address && order.user
# Add a condition to check if the address should be saved to user
if order.address.save_to_user
unless order.user.addresses.exists?(order.address.id)
order.user.addresses << order.address
end
end
end
end
end
2 changes: 2 additions & 0 deletions app/models/address.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ class Address < ApplicationRecord
belongs_to :addressable, polymorphic: true
has_many :orders

attribute :save_to_user, :boolean, default: false

validates :street_address, :city, :state, :postal_code, :addressable, presence: true
validates :postal_code, format: { with: /\A\d{5}(-\d{4})?\z/, message: "must be a valid postal code" }
end
1 change: 1 addition & 0 deletions app/models/order.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ class Order < ApplicationRecord
belongs_to :product, polymorphic: true
belongs_to :address

accepts_nested_attributes_for :address, allow_destroy: true
before_validation :normalize_phone_number

# Validates that phone number is in the right 10 digit format
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
post "kit_items_only", to: "kit_items#create_kit_items_only"
patch "kit_items_only/:id", to: "kit_items#update_kit_items_only"
resources :users do
resources :addresses, only: [ :create, :update, :destroy ]
member do
get "profile"
end
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20250110130617_add_save_to_user_to_addresses.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddSaveToUserToAddresses < ActiveRecord::Migration[7.2]
def change
add_column :addresses, :save_to_user, :boolean
end
end
3 changes: 2 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions spec/factories/addresses.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
city { Faker::Address.city }
state { Faker::Address.state_abbr }
postal_code { Faker::Address.zip_code }
save_to_user { true }
association :addressable, factory: :user # Default polymorphic association
end
end
181 changes: 181 additions & 0 deletions spec/requests/addresses_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
require 'rails_helper'

RSpec.describe "Addresses", type: :request do
let(:admin_user) { create(:user, :admin_user) }
let(:regular_user) { create(:user, :regular_user) }
let(:teacher_user) { create(:user, :teacher_user) }
let(:speaker_user) { create(:user, :speaker_user) }
let(:address) { create(:address, addressable: regular_user) }

describe "POST /create" do
let(:address) { create(:address, addressable: regular_user) }

context "when the user is regular user" do
it "creates new address" do
sign_in regular_user
address_params = {
address: {
street_address: "123 St",
city: "City1",
state: "State1",
postal_code: "12345",
save_to_user: true
}
}
expect {
post "/api/v1/users/#{regular_user.id}/addresses", params: address_params, headers: { 'Authorization': "Bearer #{@auth_token}" }
}.to change(Address, :count).by(1)
expect(response).to have_http_status(:created)
end
end

context "when the user is admin user" do
it "can create new address for user" do
sign_in admin_user
address_params = {
address: {
street_address: "123 St",
city: "City1",
state: "State1",
postal_code: "12345",
save_to_user: true
}
}

expect {
post "/api/v1/users/#{admin_user.id}/addresses", params: address_params, headers: { 'Authorization': "Bearer #{@auth_token}" }
}.to change(Address, :count).by(1)
expect(response).to have_http_status(:created)
end
end

context "when the user is teacher_user" do
it "can create new address for teacher user" do
sign_in teacher_user
address_params = {
address: {
street_address: "123 St",
city: "City1",
state: "State1",
postal_code: "12345",
save_to_user: true
}
}

expect {
post "/api/v1/users/#{teacher_user.id}/addresses", params: address_params, headers: { 'Authorization': "Bearer #{@auth_token}" }
}.to change(Address, :count).by(1)
expect(response).to have_http_status(:created)
end
end

context "when the user is speaker user" do
it "can create new address for speaker user" do
sign_in speaker_user
address_params = {
address: {
street_address: "123 St",
city: "City1",
state: "State1",
postal_code: "12345",
save_to_user: true
}
}

expect {
post "/api/v1/users/#{speaker_user.id}/addresses", params: address_params, headers: { 'Authorization': "Bearer #{@auth_token}" }
}.to change(Address, :count).by(1)
expect(response).to have_http_status(:created)
end
end
end

describe "PUT /update" do
let(:address) { create(:address, addressable: regular_user) }
let(:updated_address_params) {
{ address: {
street_address: "456 St",
city: "City1",
state: "State1",
postal_code: "12345",
save_to_user: true
} }
}

context "when the user is regular user" do
it "can update their own address" do
sign_in regular_user
put "/api/v1/users/#{regular_user.id}/addresses/#{address.id}", params: updated_address_params, headers: { 'Authorization': "Bearer #{@auth_token}" }
expect(response).to have_http_status(:ok)
end
end

context "when the user is admin user" do
it "can update an address" do
sign_in admin_user
put "/api/v1/users/#{regular_user.id}/addresses/#{address.id}", params: updated_address_params, headers: { 'Authorization': "Bearer #{@auth_token}" }
expect(response).to have_http_status(:ok)
end
end

context "when the user is teacher user" do
it "can update an address" do
sign_in teacher_user
put "/api/v1/users/#{regular_user.id}/addresses/#{address.id}", params: updated_address_params, headers: { 'Authorization': "Bearer #{@auth_token}" }
expect(response).to have_http_status(:ok)
end
end

context "when the user is speaker user" do
it "can update an address" do
sign_in speaker_user
put "/api/v1/users/#{regular_user.id}/addresses/#{address.id}", params: updated_address_params, headers: { 'Authorization': "Bearer #{@auth_token}" }
expect(response).to have_http_status(:ok)
end
end
end

describe "DELETE /destroy" do
let!(:address) { create(:address, addressable: regular_user) }

context "when the user is regular user" do
it "can delete their own address" do
sign_in regular_user
expect {
delete "/api/v1/users/#{regular_user.id}/addresses/#{address.id}", headers: { 'Authorization': "Bearer #{@auth_token}" }
}.to change(Address, :count).by(-1)
expect(response).to have_http_status(:no_content)
end
end

context "when the user is admin user" do
it "can delete any address" do
sign_in admin_user
expect {
delete "/api/v1/users/#{regular_user.id}/addresses/#{address.id}", headers: { 'Authorization': "Bearer #{@auth_token}" }
}.to change(Address, :count).by(-1)
expect(response).to have_http_status(:no_content)
end
end

context "when the user is teacher user" do
it "can delete an address" do
sign_in teacher_user
expect {
delete "/api/v1/users/#{regular_user.id}/addresses/#{address.id}", headers: { 'Authorization': "Bearer #{@auth_token}" }
}.to change(Address, :count).by(-1)
expect(response).to have_http_status(:no_content)
end
end

context "when the user is speaker user" do
it "can delete an address" do
sign_in speaker_user
expect {
delete "/api/v1/users/#{regular_user.id}/addresses/#{address.id}", headers: { 'Authorization': "Bearer #{@auth_token}" }
}.to change(Address, :count).by(-1)
expect(response).to have_http_status(:no_content)
end
end
end
end
Loading