Skip to content

Instantly share code, notes, and snippets.

@boriscy
Created January 22, 2015 18:16
Show Gist options
  • Save boriscy/a8715801b0abf02aaf41 to your computer and use it in GitHub Desktop.
Save boriscy/a8715801b0abf02aaf41 to your computer and use it in GitHub Desktop.
Models for polla
module Authentication
extend ActiveSupport::Concern
mattr_accessor :pepper, :stretches
attr_accessor :password, :password_confirmation
included do
validates_uniqueness_of :email, :if => "email.present?", :message => I18n.t("activerecord.errors.messages.existing_email"),
:allow_blank => true
with_options :if => :should_validate? do |valid|
valid.validates_presence_of :email
valid.validates_email_format_of :email
valid.validates_length_of :password, :in => 6..32, :on => :create
valid.validates_confirmation_of :password, :on => :create, :message => I18n.t("activerecord.errors.messages.email")
end
end
def self.authenticate(email, pass)
user = User.find_by_email()
end
# Setter for password
def password=(unencrypted_password)
instance_variable_set(:@password, unencrypted_password)
self.password_salt = ::BCrypt::Engine.generate_salt
peppered_password = [unencrypted_password, pepper].join
self.encrypted_password = ::BCrypt::Engine.hash_secret(peppered_password, password_salt, stretches)
end
def valid_password?(unencrypted_password)
peppered_password = [unencrypted_password, pepper].join
::BCrypt::Engine.hash_secret(peppered_password, password_salt, stretches) === self.encrypted_password
end
def confirmated?
confirmed_at.present?
end
def should_validate?
true
end
def confirm_token(token)
return true if confirmated?
if confirmation_token === token
self.confirmed_at = Time.zone.now
self.save(:validate => false)
else
false
end
end
def reset_password
self.reset_password_token = SecureRandom.urlsafe_base64(32)
UserMailer.reset_password(self).deliver
self.save!
end
def valid_password_token?(token)
u = User.find_by_reset_password_token(token)
if u
if u.updated_at < (Time.zone.now - 1.hour)
else
true
end
else
false
end
end
def update_password(params)
unless params[:password] === params[:password_confirmation]
self.errors[:password] << I18n.t("activerecord.errors.messages.confirmation")
return false
end
pass = params[:password].to_s.strip
if pass.size < 8
self.errors[:password] << I18n.t("activerecord.errors.messages.too_short", :count => 8)
return false
elsif pass.size > 32
self.errors[:password] << I18n.t("activerecord.errors.messages.too_long", :count => 32)
return false
end
self.password = params[:password]
self.save
end
def verify_token_and_update_password(params)
unless params[:password] === params[:password_confirmation]
self.errors[:password] << I18n.t("activerecord.errors.messages.confirmation")
return false
end
pass = params[:password].to_s.strip
if pass.size < 8
self.errors[:password] << I18n.t("activerecord.errors.messages.too_short", :count => 8)
return false
elsif pass.size > 32
self.errors[:password] << I18n.t("activerecord.errors.messages.too_long", :count => 32)
return false
end
self.password = params[:password]
self.reset_password_token = nil
self.save
end
def can_update_password?
self.updated_at > (Time.zone.now - 1.hour)
end
protected
def pepper
"1bb32a5f17805f422bce80df3b76d5e1fca182be6524b78b8366282cc6d6888fb9789f374ee94efa713719e90f880ee3232c7e3b0e4610a4594d8cc960fc4f28"
end
def stretches; 10; end
end
class Forecast < ActiveRecord::Base
# Associations
belongs_to :user, dependent: :destroy
belongs_to :match, dependent: :destroy
# Validations
validates_numericality_of :home_goals, :away_goals, greater_than_or_equal_to: 0
validates_presence_of :user, :user_id
def to_api
{
id: id,
user_id: user_id,
match_id: match_id,
home_goals: home_goals,
away_goals: away_goals
}
end
end
class Goal < ActiveRecord::Base
belongs_to :match
belongs_to :player
enum goal_type: I18n.t('goal.types')
validates_presence_of :goal_type
delegate :team, to: :player, prefix: true
def to_api
{ id: id, match_id: match_id,
goal_type: self[:goal_type],
player_id: player_id, minute: minute }
end
end
class Match < ActiveRecord::Base
# Relationships
belongs_to :home_team, class_name: 'Team'
belongs_to :away_team, class_name: 'Team'
has_many :forecasts, dependent: :destroy
has_many :goals, dependent: :destroy
enum match_type: I18n.t('match.types')
# Validations
validates_presence_of :date, :home_team, :home_team_id, :away_team, :away_team_id, :match_type
scope :published, -> { where(published: true).where("date > ?", time_now) }
scope :played, -> { where(played: true) }
scope :playing, -> { where(playing: true) }
delegate :flag, to: :home_team, prefix: true
delegate :flag, to: :away_team, prefix: true
def to_api
{
id: id,
home_team_id: home_team_id, away_team_id: away_team_id,
home_goals: home_goals, away_goals: away_goals,
date: date, location: location, match_type: match_type
}
end
def self.time_now
Time.now + 1.hour
end
def self.started?
date = Match.order(:date).pluck(:date).first
date < time_now
end
end
# encoding: utf-8
class Player < ActiveRecord::Base
before_destroy :delete_players_users
# Relationships
belongs_to :team
has_many :made_goals, -> { joins(:match).where("matches.played = ? ", true) }, class_name: 'Goal'
has_and_belongs_to_many :users
# Validations
validates_presence_of :name, :team_id, :team
def to_s
name
end
def to_api
{ id: id, name: name, team_id: team_id }
end
def update_goals
update(goals: made_goals.count)
end
private
def delete_players_users
transaction do
users.update_all(step: 'step1')
self.user_ids = []
end
end
end
# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20140605190534) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "admins", force: true do |t|
t.string "name"
t.string "email"
t.string "encrypted_password"
t.string "password_salt"
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "reseted_password_at"
t.integer "signin_count", default: 0
t.datetime "last_signin_at"
t.boolean "active", default: true
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "admins", ["active"], name: "index_admins_on_active", using: :btree
add_index "admins", ["email"], name: "index_admins_on_email", unique: true, using: :btree
add_index "admins", ["reset_password_token"], name: "index_admins_on_reset_password_token", unique: true, using: :btree
create_table "forecasts", force: true do |t|
t.integer "match_id"
t.integer "user_id"
t.integer "home_goals"
t.integer "away_goals"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "forecasts", ["match_id"], name: "index_forecasts_on_match_id", using: :btree
add_index "forecasts", ["user_id"], name: "index_forecasts_on_user_id", using: :btree
create_table "goals", force: true do |t|
t.integer "minute"
t.integer "player_id"
t.integer "match_id"
t.integer "goal_type"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "goals", ["match_id"], name: "index_goals_on_match_id", using: :btree
add_index "goals", ["player_id"], name: "index_goals_on_player_id", using: :btree
create_table "matches", force: true do |t|
t.integer "home_team_id"
t.integer "away_team_id"
t.integer "home_goals", default: 0
t.integer "away_goals", default: 0
t.string "location"
t.datetime "date"
t.integer "match_type"
t.boolean "played", default: false
t.boolean "published", default: false
t.boolean "playing", default: false
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "penalties", default: false
end
add_index "matches", ["away_team_id"], name: "index_matches_on_away_team_id", using: :btree
add_index "matches", ["home_team_id"], name: "index_matches_on_home_team_id", using: :btree
add_index "matches", ["played"], name: "index_matches_on_played", using: :btree
add_index "matches", ["playing"], name: "index_matches_on_playing", using: :btree
add_index "matches", ["published"], name: "index_matches_on_published", using: :btree
create_table "players", force: true do |t|
t.integer "team_id"
t.string "name"
t.integer "number"
t.string "player_type"
t.integer "goals", default: 0
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "players", ["team_id"], name: "index_players_on_team_id", using: :btree
create_table "players_users", id: false, force: true do |t|
t.integer "player_id"
t.integer "user_id"
end
add_index "players_users", ["player_id", "user_id"], name: "index_players_users_on_player_id_and_user_id", unique: true, using: :btree
create_table "teams", force: true do |t|
t.integer "group"
t.string "name"
t.string "abbreviation"
t.boolean "champion", default: false
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "teams_users", id: false, force: true do |t|
t.integer "team_id"
t.integer "user_id"
end
add_index "teams_users", ["team_id", "user_id"], name: "index_teams_users_on_team_id_and_user_id", unique: true, using: :btree
create_table "users", force: true do |t|
t.string "name"
t.string "email", null: false
t.string "encrypted_password"
t.string "password_salt"
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "reseted_password_at"
t.integer "signin_count", default: 0
t.datetime "last_signin_at"
t.string "alias"
t.string "phone"
t.string "mobile"
t.integer "champion_id", default: 0
t.integer "scorer_id", default: 0
t.integer "shutout_id", default: 0
t.boolean "completed", default: false
t.string "step", default: "step1"
t.decimal "payed", precision: 14, scale: 2
t.string "in_charge"
t.boolean "active", default: true
t.datetime "created_at"
t.datetime "updated_at"
t.string "stored_password"
t.string "identification_number"
t.string "address"
end
add_index "users", ["active"], name: "index_users_on_active", using: :btree
add_index "users", ["champion_id"], name: "index_users_on_champion_id", using: :btree
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
add_index "users", ["scorer_id"], name: "index_users_on_scorer_id", using: :btree
add_index "users", ["shutout_id"], name: "index_users_on_shutout_id", using: :btree
end
# encoding: utf-8
class Team < ActiveRecord::Base
# Relationships
has_many :players, inverse_of: :team
has_many :home_matches, class_name: 'Match', foreign_key: :home_team_id
has_many :away_matches, class_name: 'Match', foreign_key: :away_team_id
enum group: I18n.t('match.types')
# Validations
validates :name, presence: true, uniqueness: true
validates :group, presence: true
def to_s
name
end
def flag
"flags/#{abbreviation}.png"
end
end
class User < ActiveRecord::Base
include Models::Authentication
LAST_STEP = 'step4'
# Relationships
belongs_to :champion, :class_name => 'Team'
belongs_to :scorer, :class_name => 'Player'
belongs_to :shutout, :class_name => 'Team'
has_and_belongs_to_many :players
has_and_belongs_to_many :teams
has_many :forecasts
before_save :store_password
# Validations
validates :name, presence: true
validates :email, presence: true, uniqueness: true, email_format: true
validates_presence_of :password, on: :create
validates_length_of :password, within: 8..60, on: :create
validates_presence_of :encrypted_password, :identification_number, :address
alias_method :captains, :players
alias_method :captain_ids, :player_ids
delegate :team_id, to: :scorer, prefix: true, allow_nil: true
delegate :encrypt, :decrypt, to: :encryptor
# Scopes
scope :active, -> { where(active: true) }
scope :search, -> (s) { where('name ILIKE :s OR email ILIKE :s', s: "%#{s}%") }
def to_s
name.present? ? name : email
end
def update_step
return true if step == LAST_STEP
self.step = step.next
self.save
end
def to_api
{ email: email, step: step, name: name,
shutout_id: shutout_id, champion_id: champion_id,
scorer_id: scorer_id
}
end
def decrypted_password
decrypt(stored_password)
rescue
''
end
private
# Stores encrypted password not hahed password that is stored
# on encrypted_password
def store_password
self.stored_password = encrypt(password) if encrypted_password_changed?
end
def encryptor
@encryptor ||= EncryptorService.new
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment