Skip to content

Instantly share code, notes, and snippets.

@Amitesh
Created April 20, 2015 18:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Amitesh/6503c4986c690e86a6dd to your computer and use it in GitHub Desktop.
Save Amitesh/6503c4986c690e86a6dd to your computer and use it in GitHub Desktop.
sample-code-snippets
/**
* Module for QHash Application
* @author : Amitesh Kumar
*
*/
window.QHash = window.QHash || {};
( function ( QHash ) {
/**
* Answer Model
* @param {[type]} answer [description]
* @return {[type]} [description]
*/
var Answer = function(answer){
answer = answer || {};
this.content = answer["content"];
this.id = answer["id"] || (new Date().getTime());
this.is_correct = answer["is_correct"];
this.order_no = answer["order_no"];
this.question_id = answer["question_id"];
this.updated_at = answer["updated_at"];
this.created_at = answer["created_at"];
this.answerType = answer["answer_type"] || 1;
this.isNew = !!!answer["id"];
};
Answer.prototype = {
isSingleChoice: function(){
return this.answerType() == 1;
},
isMultipleChoice: function(){
return this.answerType() == 2;
},
isSubjective: function(){
return this.answerType() == 3;
},
remove: function(){
alert("removed...")
}
};
/**
* Question handler class
* @return {[type]} [description]
*/
QHash.QuestionRender = (function(){
var answers = {};
var answerTypeSelect = "#question_answer_type";
var answerType = function(){ return $( answerTypeSelect ).val(); }
var answersCont;
return {
init: function(){
answersCont = $("#answers")
this.refreshAnswers();
this.initUI();
},
refreshAnswers: function(){
answers = {};
for (var i = 0; i < answers_data.length; i++) {
this.setAnswer(answers_data[i]);
};
this.render();
},
initUI: function(){
var me = this;
$( answerTypeSelect ).change(function(){
me.render();
});
$(answersCont).on('change', 'input:radio', function(){
$(".answer-hd", answersCont).val(false);
$(this).parent().find(':hidden').val( $(this).is(':checked') ? true : false );
});
$(answersCont).on('change', 'input:radio, input:checkbox, input:text', function(){
var id = $(this).data('answer-id');
var answer = answers[id];
if(answer){
if($(this).is(':text')){
answer.content = $(this).val();
}else if($(this).is(':radio')){
$.each(answers, function(key, value) {
value.is_correct = false;
answers[key] = value;
});
answer.is_correct = $(this).is(':checked') ? true : false;
}else{
answer.is_correct = $(this).is(':checked') ? true : false;
}
answers[id] = answer;
} // if end
});
$(answersCont).on('click', '.remove-answer-btn', function(event){
return me.removeAnswer(event)
});
$('.add-new-answer').on('click', function(){
return me.addNewAnswer();
});
},
setAnswer: function(answer){
var ans = new Answer( answer );
ans.answerType = answerType;
answers[ans.id] = ans;
},
getAnswers: function(){
var answrs = [];
$.each(answers, function(key, value) { answrs.push(value) });
return answrs
},
render: function(){
var template = Handlebars.compile( $("#answer-template").html() );
answersCont.html( template({answers: this.getAnswers()}));
$('input:radio', answersCont).each(function(){
$(this).parent().find(':hidden').val($(this).is(':checked')? true : false);
})
},
addNewAnswer: function(){
var ans = new Answer();
ans.answerType = answerType;
answers[ans.id] = ans;
this.render();
return false;
},
removeAnswer: function(event){
var me = this;
var elem = $(event.target);
var id = elem.data('answer-id');
var answer = answers[id];
if(answer){
if(answer.isNew){
delete answers[id];
this.render();
}else{
$.post( elem.attr('href'), function() {
delete answers[id];
me.render();
}).fail(function( jqXHR, textStatus, error) {
// console.log( arguments );
alert( jqXHR.responseJSON.error );
}).always(function() {
});
}
}
return false;
}
};
})();
} )( window.QHash );
# User model
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# email :string(255) default(""), not null
# encrypted_password :string(255) default(""), not null
# reset_password_token :string(255)
# reset_password_sent_at :datetime
# remember_created_at :datetime
# sign_in_count :integer default(0), not null
# current_sign_in_at :datetime
# last_sign_in_at :datetime
# current_sign_in_ip :string(255)
# last_sign_in_ip :string(255)
# confirmation_token :string(255)
# confirmed_at :datetime
# confirmation_sent_at :datetime
# unconfirmed_email :string(255)
# failed_attempts :integer default(0), not null
# unlock_token :string(255)
# locked_at :datetime
# created_at :datetime
# updated_at :datetime
# username :text
# username_lowercase :text
# admin :boolean default(FALSE), not null
# show_app_caveat :boolean default(TRUE), not null
# apps_count :integer default(0), not null
# app_families_count :integer default(0), not null
# payments_count :integer default(0), not null
#
# A user of the app. Uses [Devise](https://github.com/plataformatec/devise) for
# authentication.
class User < ActiveRecord::Base
# 1. Configuration
devise :database_authenticatable, :registerable, :recoverable, :rememberable,
:trackable, :validatable, :timeoutable, :confirmable
include FriendlyId
friendly_id :username_lowercase
# 2. Attributes
# @private
attr_accessor :login
attr_readonly :username_lowercase
def to_s; username; end
def has_unidentified_apps?
# Filter out any unidentified apps which have no app identifiers. There
# shouldn't be any anyway, but stay on the safe side, because if they do
# find their way into the DB, the user will receive the 'you have orphaned
# data' message, but won't be able to do anything about it.
self.apps.unidentified.select { |a| a.app_identifiers.any? }.any?
end
# Note regarding show_app_caveat: This boolean determines whether the 'app
# caveat' notification should be displayed on an app's show page. It's true
# when the user is first created, then they set it to false by clicking
# "don't show this again". This is a very simple implementation and is NOT a
# good idea if the app grows to the point where users have lots of
# dismissable notifications. I'm doing it this way for now just because
# there's only one notification for the time being so it's not worth the
# effort of a more complicated system.
# 3. Validations
VALID_USERNAME_REGEX ||= /\A[A-Za-z][A-Za-z0-9_]*\z/
DISALLOWED_USERNAMES ||= YAML::load_file("config/disallowed_names.yml")
validates_presence_of :username
validates :username, uniqueness: { case_sensitive: false },
length: { minimum: 5, maximum: 20 },
format: {
with: VALID_USERNAME_REGEX,
message: "can only contain letters, numbers and underscores"
}, :if => "self.username.present?"
validate :username_cant_be_a_reserved_word, :if => "self.username?"
# 4. Associations
include User::PaymentAssociations
has_many :app_families, dependent: :destroy
has_many :apps, dependent: :destroy
has_many :app_problems, through: :apps, source: :problems,
:class_name => Diagnostics::AppProblem
has_many :metric_time_slices, through: :apps
has_many :app_identifiers, through: :apps, dependent: :destroy
has_many :connections, dependent: :destroy
has_many :data_sources, through: :connections
has_many :ad_networks, -> { merge(DataSource.ad_networks) }, through: :connections, source: :data_source
has_many :marketplaces, -> { merge(DataSource.marketplaces) }, through: :connections, source: :data_source
# @param data_source [DataSource] a data source.
# @return [Boolean] whether the user has added credentials for the given data
# source.
def connected_to?(data_source)
data_sources.include?(data_source)
end
# The user's apps which aren't connected to a specified data source. Used
# to identify unidentified apps. A user might have not yet identified one
# of their apps for a particular data source. When we receive unidentified data
# for that data source, we want to know which apps don't already have an
# identifier for that data source, because the unidentified data might belong
# to one of them.
#
# @option opts [DataSource] :data_source A data source. (required)
# @return [ActiveRecord::Relation<App>] All of the user's apps which are **a)**
# not unidentified and **b)** don't already have an `AppIdentifier` connecting
# them to the given data source.
def mergeable_apps(opts={})
data_source = opts.fetch(:data_source)
data_source.apps.missing.where(user_id: self.id).identified
# Note that this first attempt doesn't work:
#
# self.apps.includes(:data_sources).identified
# .where.not(app_identifiers: { data_source_id: data_source.id })
#
# because if an app is connected to ANY data_source other than the given one
# , then the condition `data_source.id != (excluded data source).id` will
# be true for that row of the left outer join, so the app will be returned
# even if it's not connected to the specified data source.
end
# 5. Scopes
# 6. Callbacks
before_save { |u| u.username = u.username.downcase }
before_save { |u| u.username_lowercase = u.username.downcase }
# Override the Devise method so that Users can log in using either their
# email or username. goo.gl/yXDJd3
def self.find_first_by_auth_conditions(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:login)
where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
else
where(conditions).first
end
end
def to_param
self.username.downcase
end
private
# Can't use validates_exclusion_of because it needs to be case-insensitive
def username_cant_be_a_reserved_word
if DISALLOWED_USERNAMES.include? self.username.downcase
errors[:username] << "is not an allowed username"
end
end
end
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# email :string(255) default(""), not null
# encrypted_password :string(255) default(""), not null
# reset_password_token :string(255)
# reset_password_sent_at :datetime
# remember_created_at :datetime
# sign_in_count :integer default(0), not null
# current_sign_in_at :datetime
# last_sign_in_at :datetime
# current_sign_in_ip :string(255)
# last_sign_in_ip :string(255)
# confirmation_token :string(255)
# confirmed_at :datetime
# confirmation_sent_at :datetime
# unconfirmed_email :string(255)
# failed_attempts :integer default(0), not null
# unlock_token :string(255)
# locked_at :datetime
# created_at :datetime
# updated_at :datetime
# username :text
# username_lowercase :text
# admin :boolean default(FALSE), not null
# show_app_caveat :boolean default(TRUE), not null
# apps_count :integer default(0), not null
# app_families_count :integer default(0), not null
# payments_count :integer default(0), not null
#
require 'spec_helper'
describe User do
let(:email) { "user@example.com" }
let(:pw) { "foobar123" }
let(:username) { "ExampleUser"}
let(:user) do
User.new(email: email,
password: pw,
password_confirmation: pw,
username: username
)
end
subject { user }
# 1. Configuration
# 2. Attributes
it { should have_readonly_attribute :username_lowercase }
describe "#paid?" do
before { user.save! }
# Reload user so that it registers the update to payments_count
subject { user.reload.paid? }
context "when user has no Payments" do
it { should be_false }
end
context "when user's most recent payment" do
before { create(:payment, user: user, date: date) }
context "is more than than 1 month + Payment::GRACE_PERIOD ago" do
let(:date) { Payment.cutoff_date - 1.day }
it { should be_false }
end
context "is less than than 1 month + Payments::GRACE_PERIOD ago" do
let(:date) { Payment.cutoff_date + 1.day }
it { should be_true }
end
end
end
describe "#date_of_most_recent_payment" do
subject { user.date_of_most_recent_payment }
context "when the user" do
context "has no payments" do
it { should be_nil }
end
context "has payments" do
before do
user.save!
create(:payment, user: user, date: "2014-05-02")
create(:payment, user: user, date: "2014-05-01")
end
it "returns the date of the most recent payment" do
expect(subject).to eq Date.parse("2014-05-02")
end
end
end
end
# 3. Validations
it { should validate_uniqueness_of(:username).case_insensitive }
it { should validate_presence_of(:username) }
it do
disallowed_usernames = YAML::load_file("config/disallowed_names.yml")
should ensure_exclusion_of(:username).\
in_array(disallowed_usernames).with_message("is not an allowed username")
end
it { should ensure_length_of(:username).is_at_least(5).is_at_most(20) }
it do
should allow_value(
"john", "john1234", "abcdefghijklmnop"
).for(:username)
end
it do
should_not allow_value(
"shrt", "long5678901234568901", "3startswithnumber", "specialchar!"
).for(:username)
end
it { should be_valid }
# 4. Associations
it { should have_many(:apps).dependent(:destroy) }
it { should have_many(:app_problems).through(:apps) }
it { should have_many(:app_families).dependent(:destroy) }
it { should have_many(:data_sources) }
it { should have_many(:connections).dependent(:destroy) }
it { should have_many(:app_families) }
it { should have_many(:app_identifiers) }
it { should have_many(:marketplaces) }
it { should have_many(:ad_networks) }
it { should have_many(:payments).dependent(:destroy) }
describe "#connected_to?(data_source)" do
let(:ds) { create(:data_source) }
before { user.save! }
subject { user.connected_to?(ds) }
context "when the user is connected to the data source" do
it "returns true" do
user.connections.create(data_source: ds, credential_1: "xxxx")
should be_true
end
end
context "when the user is not connected to the data source" do
it "returns false" do
should be_false
end
end
end
# 5. Scopes
# 6. Callbacks
describe "username_lowercase" do
it "is set to username.downcase before save" do
user.save!
expect(user.username_lowercase).to eq username.downcase
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment