Created
February 10, 2017 19:15
-
-
Save RJNY/090422f03a49a1e21115879d2ce8d21f to your computer and use it in GitHub Desktop.
code-sample-1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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