secret
Created

  • Download Gist
README
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
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")
invite.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
# 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
user_invites_controller.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
# 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

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.