104 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Ruby
		
	
	
	
		
		
			
		
	
	
			104 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Ruby
		
	
	
	
| 
								 | 
							
								require 'digest/sha2'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module ImpressionistController
							 | 
						||
| 
								 | 
							
								  module ClassMethods
							 | 
						||
| 
								 | 
							
								    def impressionist(opts={})
							 | 
						||
| 
								 | 
							
								      before_filter { |c| c.impressionist_subapp_filter(opts[:actions], opts[:unique])}
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								  end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  module InstanceMethods
							 | 
						||
| 
								 | 
							
								    def self.included(base)
							 | 
						||
| 
								 | 
							
								      base.before_filter :impressionist_app_filter
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def impressionist(obj,message=nil,opts={})
							 | 
						||
| 
								 | 
							
								      unless bypass
							 | 
						||
| 
								 | 
							
								        if obj.respond_to?("impressionable?")
							 | 
						||
| 
								 | 
							
								          if unique_instance?(obj, opts[:unique])
							 | 
						||
| 
								 | 
							
								            obj.impressions.create(associative_create_statement({:message => message}))
							 | 
						||
| 
								 | 
							
								          end
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								          # we could create an impression anyway. for classes, too. why not?
							 | 
						||
| 
								 | 
							
								          raise "#{obj.class.to_s} is not impressionable!"
							 | 
						||
| 
								 | 
							
								        end
							 | 
						||
| 
								 | 
							
								      end
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def impressionist_app_filter
							 | 
						||
| 
								 | 
							
								      @impressionist_hash = Digest::SHA2.hexdigest(Time.now.to_f.to_s+rand(10000).to_s)
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def impressionist_subapp_filter(actions=nil,unique_opts=nil)
							 | 
						||
| 
								 | 
							
								      unless bypass
							 | 
						||
| 
								 | 
							
								        actions.collect!{|a|a.to_s} unless actions.blank?
							 | 
						||
| 
								 | 
							
								        if (actions.blank? || actions.include?(action_name)) && unique?(unique_opts)
							 | 
						||
| 
								 | 
							
								          Impression.create(direct_create_statement)
							 | 
						||
| 
								 | 
							
								        end
							 | 
						||
| 
								 | 
							
								      end
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    private
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def bypass
							 | 
						||
| 
								 | 
							
								      Impressionist::Bots.bot?(request.user_agent)
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def unique_instance?(impressionable, unique_opts)
							 | 
						||
| 
								 | 
							
								      return unique_opts.blank? || !impressionable.impressions.where(unique_query(unique_opts)).exists?
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def unique?(unique_opts)
							 | 
						||
| 
								 | 
							
								      return unique_opts.blank? || !Impression.where(unique_query(unique_opts)).exists?
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # creates the query to check for uniqueness
							 | 
						||
| 
								 | 
							
								    def unique_query(unique_opts)
							 | 
						||
| 
								 | 
							
								      full_statement = direct_create_statement
							 | 
						||
| 
								 | 
							
								      # reduce the full statement to the params we need for the specified unique options
							 | 
						||
| 
								 | 
							
								      unique_opts.reduce({}) do |query, param|
							 | 
						||
| 
								 | 
							
								        query[param] = full_statement[param]
							 | 
						||
| 
								 | 
							
								        query
							 | 
						||
| 
								 | 
							
								      end
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # creates a statment hash that contains default values for creating an impression via an AR relation.
							 | 
						||
| 
								 | 
							
								    def associative_create_statement(query_params={})
							 | 
						||
| 
								 | 
							
								      query_params.reverse_merge!(
							 | 
						||
| 
								 | 
							
								        :controller_name => controller_name,
							 | 
						||
| 
								 | 
							
								        :action_name => action_name,
							 | 
						||
| 
								 | 
							
								        :user_id => user_id,
							 | 
						||
| 
								 | 
							
								        :request_hash => @impressionist_hash,
							 | 
						||
| 
								 | 
							
								        :session_hash => session_hash,
							 | 
						||
| 
								 | 
							
								        :ip_address => request.remote_ip,
							 | 
						||
| 
								 | 
							
								        :referrer => request.referer
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # creates a statment hash that contains default values for creating an impression.
							 | 
						||
| 
								 | 
							
								    def direct_create_statement(query_params={})
							 | 
						||
| 
								 | 
							
								      query_params.reverse_merge!(
							 | 
						||
| 
								 | 
							
								        :impressionable_type => controller_name.singularize.camelize,
							 | 
						||
| 
								 | 
							
								        :impressionable_id=> params[:id]
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								      associative_create_statement(query_params)
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def session_hash
							 | 
						||
| 
								 | 
							
								      # # careful: request.session_options[:id] encoding in rspec test was ASCII-8BIT
							 | 
						||
| 
								 | 
							
								      # # that broke the database query for uniqueness. not sure if this is a testing only issue.
							 | 
						||
| 
								 | 
							
								      # str = request.session_options[:id]
							 | 
						||
| 
								 | 
							
								      # logger.debug "Encoding: #{str.encoding.inspect}"
							 | 
						||
| 
								 | 
							
								      # # request.session_options[:id].encode("ISO-8859-1")
							 | 
						||
| 
								 | 
							
								      request.session_options[:id]
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    #use both @current_user and current_user helper
							 | 
						||
| 
								 | 
							
								    def user_id
							 | 
						||
| 
								 | 
							
								      user_id = @current_user ? @current_user.id : nil rescue nil
							 | 
						||
| 
								 | 
							
								      user_id = current_user ? current_user.id : nil rescue nil if user_id.blank?
							 | 
						||
| 
								 | 
							
								      user_id
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								  end
							 | 
						||
| 
								 | 
							
								end
							 |