Skip to content

Instantly share code, notes, and snippets.

@RJNY
Created February 10, 2017 19:15
Show Gist options
  • Save RJNY/090422f03a49a1e21115879d2ce8d21f to your computer and use it in GitHub Desktop.
Save RJNY/090422f03a49a1e21115879d2ce8d21f to your computer and use it in GitHub Desktop.
code-sample-1
class Address < ActiveRecord::Base
include SmartyStreets
belongs_to :user
before_save :trim_zip_code, :activate
validates :line1, :zip_code, :user_id, presence: true
validate :validate_address
validates :city, :state, presence: true
after_commit :ensure_one_active_address, :update_user_location
scope :active_and_validated, where(active: true, validated: true)
RDI_LIMITS = { po_box: 1, residential: 2, commercial: 5 }.freeze
UNDELIVERABLE_STATES = %w(HI PR GU VI AS MP FM MH PW AK UM).freeze
VALID_STATES = %w(AL AZ AR CA CO CT DC DE FL GA ID IL IN IA KS KY LA ME MD MA MI MN MS MO
MT NE NV NH NJ NM NY NC ND OH OK OR PA RI SC SD TN TX UT VT VA WA WV WI WY).freeze
ERROR_MESSAGES = {
default: "Address validation failed, please try again.",
invalid_zip_code: "You have entered an invalid zip code.",
smarty_streets: "Address validation failed, please try again.",
blacklist: "This address has been blocked due to a breach of the PINCHme Terms & Conditions.",
undeliverable_state: "We are unable to deliver outside the 48 contiguous states.",
dpv_match_code: "Address could not be verified!",
po_box: "Sorry! We allow a maximum of one PINCHme box per PO Box. If you wish
to use this address for this account, please remove this address from any
other accounts registered to your po box, and then try again.",
residential: "Sorry! We allow for a maximum of two PINCHme members per household.
If you wish to use this address for this account, please remove this address
from any other accounts registered to your household, and then try again.",
commercial: "Sorry! We allow a maximum of five PINCHme boxes per office. If you wish to
use this address for this account, please remove this address from any other
accounts registered to your office, and then try again."
}.freeze
class << self
def deactivate_previous_addresses
ActiveRecord::Base.connection.execute <<-SQL
UPDATE addresses a
JOIN (SELECT max(id) AS id FROM addresses WHERE active = 1 GROUP BY user_id) b
SET a.active = 0
AND a.id NOT IN (b.id) ;
SQL
end
# Returns an two-dimensional array where each row is a tuple containing the following elements:
# 1. ZIP+4 code
# 2. Total number of addresses in the database with the given ZIP+4 code.
# The optional having_at_least param limits the returned rows to those that
# have at least the specified number of addresses. This helps cut down on the CPU expense
# of the undelying query, especially given that this method will mainly be called to
# discover which ZIP+4 codes have a large number of occurrences (e.g., for potential fraud detection).
def breakdown_by_zip_code(at_least = 5)
Address.group(:zip_code).having("count(*) >= ?", at_least).order("count(*) DESC").all
end
# Returns the number of addresses with the given post code that belong to blocked accounts
def count_belonging_to_blocked_accounts(zip_code)
Address.joins(:user).where("zip_code = ? AND block_reason IS NOT null", zip_code).count
end
def verify_and_save(params, user_id, bypass_validation = false)
params.keep_if { |k, v| v.present? && %w(line1 line2 city state zip_code user_id).include?(k.to_s) }
params[:zip_code] = params[:zip_code].try(:[], 0..4)
params[:user_id] = user_id
params[:line2] ||= nil # handle removing a line 2
# better way to do this without a redundant line 2 check?
address =
if !params[:line2].nil?
Address.where(params).first_or_initialize
else
Address.where(params).where("`addresses`.`line2` IS null").first_or_initialize
end
address.assign_attributes(validated: true, rdi: "admin-override") if bypass_validation
address.user_id = user_id
address.save
address
end
end
def to_s
line2.present? ? "#{line1}, #{line2}, #{city}, #{state}, #{zip_code}" : "#{line1}, #{city}, #{state}, #{zip_code}"
end
def blocked?
BlockedAddress.isBlocked?(self)
end
def city_and_state
city.present? && state.present? ? "#{city}, #{state}" : "No address yet..."
end
def validate_address
return if errors.any?
validate_with_smart_streets unless validated
errors.add(:base, ERROR_MESSAGES[:blacklist]) if blocked?
errors.add(:base, ERROR_MESSAGES[:undeliverable_state]) unless Address::VALID_STATES.include?(state)
errors.add(:base, ERROR_MESSAGES[rdi_as_symbol]) if changed? && reached_rdi_limit?
self
end
def reached_rdi_limit?
rdi != "admin-override" && rdi_count >= RDI_LIMITS[rdi_as_symbol] if rdi.present?
end
private
def activate
self.active = errors.blank?
end
def rdi_count
Address.where(line1: line1, zip_code: trim_zip_code, active: true, rdi: rdi).count
end
def update_address_from_smarty_streets(address)
rdi_type = address.metadata.record_type.eql?("P") ? "PO Box" : address.metadata.rdi
assign_attributes(rdi: rdi_type,
line1: address.delivery_line_1,
line2: address.delivery_line_2,
city: address.components.city_name,
state: address.components.state_abbreviation,
zip_code: address.components.zipcode,
validated: true)
end
def validate_with_smart_streets
verified_address = fetch_with_smart_streets
if verified_address.empty?
errors.add(:base, ERROR_MESSAGES[:smarty_streets])
else
verify_dpv_match_code(verified_address)
end
end
def verify_dpv_match_code(verified_address)
code = verified_address.first.analysis.dpv_match_code
if verified_address.blank? || code.eql?("N")
errors.add(:base, ERROR_MESSAGES[:dpv_match_code])
else
update_address_from_smarty_streets(verified_address.first)
end
end
# See smarty streets api "dpv_match_code": http://bit.ly/1WgFirK
def fetch_with_smart_streets
address = SmartyStreets::StreetAddressRequest.new(input_id: "1", street: line1, street2: line2,
city: city, state: state, zipcode: zip_code)
SmartyStreets::StreetAddressApi.call(address)
end
def trim_zip_code
assign_attributes(zip_code: zip_code.try(:[], 0..4))
end
def rdi_as_symbol
rdi.present? ? rdi.gsub(/\s/, "_").downcase.to_sym : :residential
end
def update_user_location
if active? && user.present? && user.user_profile.present?
user.user_profile.assign_attributes(zip_code: zip_code, state: state)
user.user_profile.save(validate: false)
end
end
def ensure_one_active_address
Address.where("user_id = ? AND active = ? AND id NOT IN (?)", user_id, active, id).update_all(active: 0) if active
end
end
class ProfilesController < AuthenticatedController
before_filter :validate_with_smart_streets, only: :update
def show
@surveys_completed = current_user.feedbacks.count(:survey_completed_at)
@orders_count = current_user.orders.count
@line_items_count = current_user.orders.collect(&:line_items).flatten.count
@facebook_connected = SocialConnection.exists?(user_id: current_user.id, provider: 'facebook')
end
def edit
@is_facebook_user = current_user.social_connections.any? { |sc| sc.provider == 'facebook' }
@ordered_in_interval = current_user.orders.in_box_interval.count > 0
@user_profile = current_user.user_profile ? current_user.user_profile : current_user.build_user_profile
@address = current_user.current_address
end
def destroy
current_user.destroy
experian_send_post(:update_user, resource_id: current_user.id)
redirect_to root_path
end
def update
current_user.assign_attributes(user_params)
if current_user.save
redirect_to edit_profile_path
else
@address = Address.new(user_params[:addresses_attributes]["0"])
render :edit
end
end
private
def validate_with_smart_streets
a_params = params[:user][:addresses_attributes]["0"]
unless a_params[:line1].blank? || a_params[:zip_code].blank?
a_params = Address.new(a_params.symbolize_keys).validate_address.as_json
end
a_params
end
def user_params
params.require(:user).permit(:id, :first_name, :last_name, :amazon_profile_url,
:referral_code, :access_code, :password,
user_profile_attributes: [:id, :birthdate, :gender],
addresses_attributes: [:id, :line1, :line2, :city, :state, :zip_code, :active,
:validated, :rdi]).reject { |_, v| v.blank? }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment