Last active
August 29, 2015 13:56
-
-
Save soeffing/9276483 to your computer and use it in GitHub Desktop.
Pretty Model
This file contains hidden or 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
module Legacy | |
class User < ActiveRecord::Base | |
# Constants | |
SENIORITY = { | |
0 => 'fan', | |
1 => 'novice', | |
2 => 'creative', | |
3 => 'senior', | |
4 => 'pro' | |
} | |
SENIORITY_TO_STARS = { 0 => 5, 1 => 5, 2 => 10, 3 => 15, 4 => 20 } | |
SKILLS = [ "director", "writer", "editor", "cinematographer", "producer", "motion_graphics", "animator", "audio_engineer", "musician", "composer", "actor", "voice_talent", "fx_specialist", "lighting", "graphic_design" ] | |
SKILLS_MAX = 4 | |
WORK_EXPERIENCE_ITEM = { 'start_month' => Time.now.month, 'start_year' => Time.now.year, 'end_month' => Time.now.month, 'end_year' => 0, | |
'role' => "", 'project_or_client_name' => "", 'url' => "" } | |
WORK_EXPERIENCE_MAX = 5 | |
EDUCATION_ITEM = { 'start_year' => Time.now.year, 'end_year' => 0, 'school_name' => "", 'degree' => "", 'url' => "" } | |
EDUCATION_MAX = 5 | |
CONNECT_LINKS = %w(email facebook linkedin twitter vimeo youtube tumblr behance) | |
CONNECT_LINK_ITEM = { 'value' => '', 'selected' => 0 } | |
CONNECT_LINKS_MAX = 5 | |
CLIENTS_MAX = 5 | |
ENCODING_VIDEOS_JOBS_MAX = 15 | |
ENCODING_VIDEOS_JOBS_PER_UPLOAD = 3 | |
BLACK_LIST = %w!activate ads application atom bank banners blog blog_posts change_password comments community concepts contests convert corporate dashboard edit forum home platform invite login logout monitor myzooppa news ping prints awards radios sessions signup users videos votes works! | |
JOIN_ATTRIBUTES = %w!first_name last_name address zip_code country province city! | |
devise :database_authenticatable, :registerable, :trackable, :omniauthable, :recoverable, | |
:rememberable, :confirmable, :validatable, :encryptable, encryptor: :restful_authentication_sha1 | |
# Assignments and serialization | |
attr_accessible :login, :email, :secondary_email, :password, :password_confirmation, :privacy, :newsletter, :platform, :time_zome, | |
:wants_private_messages, :first_name, :last_name, :birthdate, :url, :about_me, :address, :city, :province, :zip_code, :country, :avatar, | |
:gender, :third_party_privacy, :birth_year, :coupons, :att_customer, :facebook_user_id, :promo_code, | |
:updated_it_terms_acceptance, :partner_id, :skills, :display_full_name, :display_location, :display_total_awards, :connect_links, | |
:work_experience, :education, :clients, :use_custom_featured_work, :phone_number, :encoding_videos_jobs_count, :phone_country_code, | |
:phone_area_code, :client_account, :tax_tin_number, :tax_tin_type, :whitelabel | |
serialize :coupons | |
serialize :att_customer | |
serialize :skills | |
serialize :work_experience | |
serialize :education | |
serialize :clients | |
serialize :connect_links, Hash | |
# Relations | |
belongs_to :partner, counter_cache: true | |
has_many :votes, dependent: :destroy | |
has_many :contests, through: :ads | |
has_many :awards, through: :ads, class_name: '::Award' | |
has_many :following_as_follower, foreign_key: :follower_id, class_name: 'Following' | |
has_many :following_as_followed, foreign_key: :followed_id, class_name: 'Following' | |
has_many :followed, through: :following_as_follower, source: :followed, conditions: { state: 'active' } | |
has_many :followers, through: :following_as_followed, source: :follower, conditions: { state: 'active' } | |
has_many :ads | |
has_many :ip_traces | |
has_many :comments, dependent: :destroy | |
has_many :posts, dependent: :destroy | |
has_many :money_transactions | |
has_many :transaction_points, class_name: 'MoneyTransaction', conditions: ['amount > 0'] | |
has_many :transaction_transfers, class_name: 'MoneyTransaction', conditions: ['amount < 0'] | |
has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner | |
has_many :user_downloads | |
has_many :downloads, through: :user_downloads, conditions: "file_type IS NOT NULL" | |
has_many :project_acceptances, through: :user_downloads, conditions: "file_type IS NULL" | |
has_many :service_authentications, dependent: :destroy | |
has_many :docusign_tax_forms, order: 'created_at DESC' | |
has_many :offline_tax_forms, order: 'created_at DESC' | |
has_one :featured_video, dependent: :destroy | |
has_many :user_ndas | |
has_many :accepted_ndas, through: :user_ndas, source: :contest | |
# Callbacks | |
before_validation :set_time_zone | |
# before_validation :assign_default_platform, on: :create | |
before_save :check_for_changed_partner | |
after_create :assign_featured_video | |
after_save :send_email_changed_notification | |
#Validations | |
validates_acceptance_of :privacy, accept: true, allow_nil: false, on: :create | |
validates_presence_of :platform, :state, :login | |
validates_length_of :password, within: 4..40, if: :password_required? | |
validates_length_of :login, within: 3..25 | |
validates_uniqueness_of :login #, case_sensitive: false | |
validates_format_of :login, with: %r{^[\w\d][\w\d\-]+?[\w\d]$}i, allow_blank: false | |
validates_exclusion_of :login, in: BLACK_LIST | |
validates_inclusion_of :gender, in: [ "", "male", "female" ], allow_blank: true | |
validates_format_of :email, with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, allow_blank: true | |
validates_uniqueness_of :email, case_sensitive: true | |
validates_format_of :url, with: %r{^(http|https)://.+$}i, allow_blank: true | |
validates_uniqueness_of :facebook_user_id, if: Proc.new { |u| !u.facebook_user_id.blank? } | |
validate :disposable_email, :skills_validation, :display_full_name_validation, | |
:connect_links_validation, :clients_validation, | |
:work_experience_validation, :education_validation, :encoding_videos_jobs_count_validation, if: Proc.new {|u| !u.has_attribute?(:whitelabel) } | |
validate :check_legal_age, on: :create, if: :birth_year? | |
acts_as_url :login, url_attribute: :permalink, sync_url: true | |
# Attachments | |
has_attached_file :avatar, | |
styles: { thumb: [ "50x50#", :jpg ], detail: [ "100x100#", :jpg ], original: [ "200x200#", :jpg ] }, | |
storage: :s3, | |
path: ':attachment/:id/:timestamp_:style.:extension', | |
s3_credentials: open( "#{Rails.root}/config/aws.yml", 'r' ), | |
s3_permissions: 'public-read', | |
s3_protocol: 'http', | |
url: ':s3_alias_url', | |
s3_host_alias: S3Buckets[:users][:url], | |
bucket: S3Buckets[:users][:bucket], | |
default_url: '/assets/missing/users/:style.png', | |
s3_headers: { 'Expires' => 10.year.from_now.httpdate } | |
# Scopes | |
scope :active, where(state: 'active') | |
scope :by_platform, lambda { |platform| where(platform: platform) unless platform.nil? } | |
def complete_name | |
"#{ first_name } #{ last_name }" | |
end | |
def display_name | |
( display_full_name? and first_name.present? and last_name.present? ) ? complete_name : login | |
end | |
def set_attributes(attributes, requester) | |
if requester.admin? | |
self.assign_attributes(attributes, without_protection: true) | |
elsif requester.id == self.id | |
self.attributes = attributes | |
end | |
end | |
def can_join_contest?( contest ) | |
contest.open_for_uploads? && ( contest.coupon.blank? || coupons.include?( contest.coupon ) ) | |
end | |
def contactable?( other_user ) | |
wants_private_messages? && active? && followed_ids.include?( other_user.id ) | |
end | |
def can_send_messages?( other_user ) | |
wants_private_messages? && other_user.contactable?( self ) | |
end | |
def can_vote?( ad ) | |
ad.contest.wants_votes? && (ad.contest.coupon.blank? || coupons.include?(ad.contest.coupon)) | |
end | |
def can_comment_contest?(contest) | |
contest.wants_comments? && (contest.coupon.blank? || coupons.include?(contest.coupon)) | |
end | |
def skills | |
read_attribute( :skills ) || [ ] | |
end | |
def make_activation_code(field) | |
self.update_attribute(field, Digest::SHA1.hexdigest(Time.now.to_s.split(//).sort_by {rand}.join)) | |
end | |
def change_email! | |
self.email = self.secondary_email | |
self.update_attribute(:secondary_email, nil) | |
self.email_activation_code = nil | |
save! | |
end | |
def stars(code = nil) | |
SENIORITY_TO_STARS.keys.each do |seniority_range| | |
if respond_to?("seniority_#{ code }") && seniority_range == self.send("seniority_#{ code }").to_i | |
return SENIORITY_TO_STARS[seniority_range] | |
end | |
end | |
return 5 | |
end | |
def stars_for_ad(ad) | |
stars_array = [] | |
ad.contest.platforms.each do |platform| | |
stars_array << self.stars(platform.code) | |
end | |
stars_array.max | |
end | |
def password_required? | |
(service_authentications.empty? || !password.blank?) && super | |
end | |
def service_authentication_with(provider) | |
service_authentications.find_by_provider(provider) | |
end | |
def role | |
if admin? | |
'zooppa_administrator' | |
else | |
'zooppa_user' | |
end | |
end | |
def seniority_level(platform) | |
return 5 if admin? | |
self.send("seniority_#{ platform }") rescue 0 | |
end | |
# OPTIMIZE This should be in a helper | |
def seniority_name(seniority_level = nil) | |
case seniority_level | |
when 0, nil | |
I18n.t( 'seniority.fan' ) | |
when 1 | |
I18n.t( 'seniority.novice' ) | |
when 2 | |
I18n.t( 'seniority.creative' ) | |
when 3 | |
I18n.t( 'seniority.senior' ) | |
when 4 | |
I18n.t( 'seniority.pro' ) | |
when 5 | |
I18n.t( 'seniority.zooppa' ) | |
end | |
end | |
def calculate_seniority(platform) | |
contests_count = contests.count(joins: :platforms, conditions: ['platforms.code = ?', platform]) | |
early_or_client_awards_count = awards.count(joins: { contest: :platforms }, | |
conditions: ["(awards.award_type = 'early_entry' OR awards.award_type = 'client') AND platforms.code = ?", platform]) | |
awards_count = awards.count(joins: { contest: :platforms }, conditions: ["platforms.code = ?", platform]) | |
# $15,000 or more in awards or 6+ (Client or Early Entry) awards => Pro | |
if (points >= 15000 || early_or_client_awards_count >= 6) | |
seniority = 4 | |
# 3+ (Client or Early Entry) awards => Senior | |
elsif (early_or_client_awards_count >= 3) | |
seniority = 3 | |
# 1+ Awards of any type or 1+ Submission to 10+ contests => Creative | |
elsif (awards_count > 0 || contests_count >= 10) | |
seniority = 2 | |
# 1+ Contest upload of any type => Novice | |
elsif (contests_count > 0) | |
seniority = 1 | |
# Nothing => Fan | |
else | |
seniority = 0 | |
end | |
seniority | |
end | |
def update_seniority(platform) | |
previous = self.send("seniority_#{ platform }") || 0 | |
seniority = calculate_seniority(platform) | |
if seniority != previous | |
self.send("seniority_#{ platform }=", seniority) | |
self.save(validate: false) | |
end | |
end | |
def purified_url | |
url.gsub(/^(http|https|ftp):\/\/(www\.)*/, '') | |
end | |
def profile_completion | |
total = 0 | |
total += 10 if skills.present? | |
total += 10 if first_name.present? and last_name.present? | |
total += 10 if address.present? and city.present? and province.present? and zip_code.present? and country.present? | |
total += 10 if url.present? | |
total += 20 if partner_id.present? | |
total += 10 if any_connect_links_provided? | |
total += 10 if work_experience.present? | |
total += 10 if work_experience.present? | |
total += 10 if avatar_file_name.present? | |
total | |
end | |
def profile_completion_suggestions | |
suggestions = [] | |
suggestions.push( | |
I18n.t('users.suggestions.skills') | |
) if skills.blank? | |
suggestions.push( | |
I18n.t('users.suggestions.full_name') | |
) if first_name.blank? || last_name.blank? | |
suggestions.push( | |
I18n.t('users.suggestions.address') | |
) if address.blank? || city.blank? || province.blank? || zip_code.blank? || country.blank? | |
suggestions.push( | |
I18n.t('users.suggestions.url') | |
) if url.blank? | |
suggestions.push( | |
I18n.t('users.suggestions.partner') | |
) if partner_id.blank? | |
suggestions.push( | |
I18n.t('users.suggestions.connect') | |
) unless any_connect_links_provided? | |
suggestions.push( | |
I18n.t('users.suggestions.work_experience') | |
) if work_experience.blank? | |
suggestions.push( | |
I18n.t('users.suggestions.education') | |
) if education.blank? | |
suggestions.push( | |
I18n.t('users.suggestions.avatar') | |
) if avatar_file_name.blank? | |
suggestions | |
end | |
def location | |
location_array = [] | |
location_array.push( city ) if city.present? | |
location_array.push( province ) if province.present? | |
location_array.push( I18n.t( country, scope: 'countries' ) ) if country.present? | |
# Replacing country with country code if too long | |
location_array[2] = country if location_array.join( ', ' ).size > 40 | |
# Removing province if still too long | |
location_array.delete_at(1) if location_array.join( ', ' ).size > 40 | |
location_array.join( ', ' ) | |
end | |
def connect_links | |
connect_links_hash = read_attribute( :connect_links ) || default_connect_links | |
connect_links_ordered_hash = ActiveSupport::OrderedHash.new | |
CONNECT_LINKS.each do |key| | |
connect_links_ordered_hash[ key ] = connect_links_hash[ key ] | |
end | |
connect_links_ordered_hash | |
end | |
def default_connect_links | |
connect_links_hash = {} | |
CONNECT_LINKS.each do |name| | |
connect_links_hash[ name ] = CONNECT_LINK_ITEM | |
end | |
connect_links_hash | |
end | |
def selected_connect_links | |
connect_links_hash = {} | |
connect_links.collect do |name, val| | |
connect_links_hash[ name ] = val if val && val['selected'].to_i == 1 | |
end | |
connect_links_hash | |
end | |
def any_connect_links_provided? | |
selected_connect_links.present? | |
end | |
def all_connect_links_provided? | |
selected_connect_links.size == connect_links.size | |
end | |
def phone_country_number | |
Country.new(@user.phone_country_code).country_code | |
rescue | |
nil | |
end | |
def credits(refresh = false) | |
refresh ? ( money_transactions.sum( :amount ).to_i ) : read_attribute( :credits ) | |
end | |
def points(refresh = false) | |
refresh ? (transaction_points.sum( :amount ).to_i ) : read_attribute( :points ) | |
end | |
def total_transferred(refresh = false) | |
if refresh | |
transaction_transfers.sum(:amount).to_i.abs | |
else | |
read_attribute(:total_transferred).blank? ? 0 : read_attribute(:total_transferred) | |
end | |
end | |
def update_credits | |
update_attribute :credits, credits( true ) | |
end | |
def update_points | |
update_attribute :points, points( true ) | |
end | |
def update_money_transfers | |
m = total_transferred(true) | |
update_attribute( :total_transferred, m ) if m | |
end | |
def check_legal_age | |
legal_age = birth_year.to_i > Date.today.year - ApplicationConfig['legal_age'][platform] | |
errors.add(:base, :birth_year) if legal_age | |
end | |
def can_join? | |
active? && completed_fields?( JOIN_ATTRIBUTES ) | |
end | |
protected | |
def self.by_permalink( login, options = {}, current_user = nil ) | |
find_by_permalink!( login, {conditions: ['state = "active"' ]}.merge( options ) ) | |
end | |
def completed_fields?( fields ) | |
!fields.any? { |field| self[ field ].blank? } | |
end | |
def should_change_email?(other) | |
!other.blank? && other != email && other =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i | |
end | |
def assign_featured_video | |
new_video = FeaturedVideo.new | |
new_video.user = self | |
new_video.save | |
end | |
private | |
def disposable_email | |
if self.new_record? | |
errors.add(:base, :disposable_email) if (self.email && self.email[/@.*$/] && DisposableEmails['providers'].include?(self.email[/@.*$/][1..-1])) | |
end | |
end | |
def set_time_zone | |
case self.platform | |
when 'it' | |
self.time_zone = 'Rome' | |
when 'eu' | |
self.time_zone = 'London' | |
else | |
self.time_zone = 'Pacific Time (US & Canada)' | |
end | |
end | |
def skills_validation | |
if skills.size > SKILLS_MAX | |
errors.add :skills, I18n.t('validation.user.skills.max_length', count: SKILLS_MAX) | |
end | |
end | |
def display_full_name_validation | |
if display_full_name? and ( first_name.blank? or last_name.blank? ) | |
errors.add :display_full_name, "You must fill out the first and last name fields in order to display your full name in your profile." | |
end | |
end | |
def connect_links_validation | |
if selected_connect_links.size > CONNECT_LINKS_MAX | |
errors.add :connect_links, I18n.t('validation.user.connect_links.max_length', count: CONNECT_LINKS_MAX) | |
end | |
end | |
def clients_validation | |
if clients.size > CLIENTS_MAX | |
errors.add :clients, I18n.t('validation.user.clients.max_length', count: CLIENTS_MAX) | |
end | |
end | |
def work_experience_validation | |
if work_experience.size > WORK_EXPERIENCE_MAX | |
errors.add :work_experience, I18n.t('validation.user.work_experience.max_length', count: WORK_EXPERIENCE_MAX) | |
end | |
end | |
def education_validation | |
if education.size > EDUCATION_MAX | |
errors.add :education, I18n.t('validation.user.education.max_length', count: EDUCATION_MAX) | |
end | |
end | |
def encoding_videos_jobs_count_validation | |
if ApplicationConfig[ 'video_upload' ][ 'limitation' ] and encoding_videos_jobs_count > ENCODING_VIDEOS_JOBS_MAX | |
errors.add :encoding_videos_jobs_count, I18n.t('validation.user.encoding_videos_jobs_count.max_length', count: ENCODING_VIDEOS_JOBS_MAX) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment