Skip to content

Instantly share code, notes, and snippets.

@foxweb

foxweb/README Secret

Created August 16, 2012 08:10
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 foxweb/485c6348e21e437862e7 to your computer and use it in GitHub Desktop.
Save foxweb/485c6348e21e437862e7 to your computer and use it in GitHub Desktop.
The logic looks like this:
Already have an Invite to this "email" from current_user?:
If not - create a new Invite, send an email (method deliver at model)
If he went there more than one day ago
then update Invite and send a new mail AGAIN
otherwise, notice: "Invite has been sent. Check the spam folder or wait for another day".
Model Invite works OK.
Please, check 'create' method. It's not work right.
I use "find_or_create_by_email".
If find exists Invite, I need "save" this and notice user.
If create new Invite, I dont need "save", but user must be notice also!
How to be notice condition? How to use find_or_create withModel validation for updated_at? (validator "ensure_user_can_resend_invites")
# encoding: utf-8
require 'digest/sha1'
class Invite < ActiveRecord::Base
acts_as_archive :class => 'Invite::Archive', :table => 'archived_invites'
USER_ORIGIN = 'user'.freeze
API_ORIGIN = 'api'.freeze
DEDUCED_USER_ORIGIN = 'deduced user'.freeze
SPAM_ORIGIN = 'spam'.freeze
QUEUE_ORIGIN = 'queue'.freeze
DIRECT_ORIGIN = 'direct'.freeze
attr_accessor :skip_email_notify
attr_accessor :from_partner
belongs_to :user
belongs_to :partner_link
belongs_to :venture
before_validation :set_user_from_partner, :on => :create
before_validation :set_free_days_count, :on => :create
before_validation :set_default_origin, :on => :create
before_validation :set_partner_link, :on => :create
validates :user_id, :email, :venture, :presence => true
validate :ensure_email_not_registered
validate :ensure_user_can_send_invites, :on => :create
validate :ensure_user_can_resend_invites, :on => :update
validates_as_email_address :email
validates :email, :uniqueness => { :scope => :user_id, :case_sensitive => false }
before_create :create_token
after_create :deliver
after_update :deliver
scope :including_partner, includes(:partner_link => [ :partner, :email_branding ])
scope :from_ventures, lambda { |v_ids|
if v_ids.blank?
scoped
else
where(:venture_id => v_ids.split(','))
end
}
scope :search_by, lambda { |t|
if t =~ /^[0-9a-f]{40}$/i
where('invites.token LIKE ?', "#{t}")
else
where('invites.email LIKE ? or users.email LIKE ?', "#{t}", "#{t}").includes(:user)
end
}
scope :created_after, lambda { |m|
where('invites.created_at > ?', Time.zone.at(m.to_i))
}
scope :created_before, lambda { |m|
where('invites.created_at < ?', Time.zone.at(m.to_i))
}
def deliver
unless skip_email_notify
InvitesMailer.invite(user, self).deliver
end
end
def to_param
token
end
def email=(e)
super(e.strip.gsub(/^</,'').gsub(/>$/,''))
end
def new_user
@new_user ||= SiteUser.new do |u|
u.email = email
u.origin_kind = origin_kind
u.origin_details = origin_details
u.invite = self
u.partner_link = partner_link
u.registered_by_invitation_code = token
u.free_period_days = free_days_count || 0
u.email_confirmed = true
end
end
def user_email=(v) # Stub для симметрии.
end
def user_email
@user_email ||= user.try(:email)
end
def as_json(options = {})
options ||= {}
options = options.merge(:methods => [:user_email, :link],
:include => { :partner_link => { :include => :partner } })
super(options)
end
def link
# XXX Bit hairy.
"#{partner_link.email_branding.link_site.root}/invites/#{token}"
end
protected
def create_token
loop {
self.token = Digest::SHA1.hexdigest("--#{Time.now}--#{rand}--")
break unless Invite.find_by_token(token)
}
end
def set_user_from_partner
if user.blank? && user_id.blank? && from_partner.present?
self.user = Partner.find_by_name(from_partner).try(:api_invites_owner)
self.origin_kind = API_ORIGIN
end
end
def set_free_days_count
if user
self.free_days_count = user.have_trusted_invites? ? 3 : 0
end
end
def set_default_origin
if origin_kind.blank? && user
self.origin_kind = USER_ORIGIN
self.origin_details = user.login
end
end
def set_partner_link
self.partner_link = user.partner_link if user
self.venture = user.venture if user
end
def ensure_email_not_registered
errors.add(:email, :already_registered) if email && venture.users.find_by_email(email)
end
def ensure_user_can_send_invites
errors.add(:user, :cant_send_invites) if user && !user.can_invite_friends?
errors.add(:user, :email_not_confirmed) if user && !user.email_confirmed?
end
def ensure_user_can_resend_invites
if updated_at > 1.day.ago
errors.add(:email, :taken)
else
message_will_change!
end
end
end
# encoding: utf-8
class UserInvitesController < ApplicationController
skip_before_filter :verify_authenticity_token
before_filter :authenticate_from_pc
def index
@invite = current_user.invites.build
@invites = current_user.invites.all
@invited_users, @payed_invited_users = current_user.invited_users.all.inject [[],[]] do |arr, u|
u.subscription.successful_receipts_sum.blank? ? arr[0] << u : arr[1] << u
arr
end
end
def create
#@invite = current_user.invites.build(params[:invite]) # work if Invite new, but not update exists Invite
@invite = current_user.invites.find_or_create_by_email(params[:invite]) #work ok if new and if exists, but...
respond_to do |format|
if @invite.save # hmmm... if find exists - ok. if create new - save error (Invite was taken)
format.html { redirect_to account_invites_path, notice: "Invite was sent to #{@invite.email}" }
format.mobile { redirect_to account_invites_path }
else
format.html { render action: 'index' }
format.mobile { render action: 'index' }
end
end
end
def update
redirect_to account_invites_path
end
def destroy
@invite = Invite.find(params[:id])
@invite.destroy
respond_to do |format|
format.html { redirect_to account_invites_path }
format.mobile { redirect_to account_invites_path }
end
end
protected
def end_of_association_chain
current_user.invites
end
def resource_request_name
:invite
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment