<commit_before>module Vanity
  module Rails #:nodoc:
    def self.load!
      Vanity.playground.load_path = ::Rails.root + Vanity.playground.load_path
      Vanity.playground.logger ||= ::Rails.logger

      # Do this at the very end of initialization, allowing you to change
      # connection adapter, turn collection on/off, etc.
      ::Rails.configuration.after_initialize do
        Vanity.playground.load!
      end
    end

    # The use_vanity method will setup the controller to allow testing and
    # tracking of the current user.
    module UseVanity
      # Defines the vanity_identity method and the set_identity_context filter.
      #
      # Call with the name of a method that returns an object whose identity
      # will be used as the Vanity identity.  Confusing?  Let's try by example:
      #
      #   class ApplicationController < ActionController::Base
      #     use_vanity :current_user
      #
      #     def current_user
      #       User.find(session[:user_id])
      #     end
      #   end
      #
      # If that method (current_user in this example) returns nil, Vanity will
      # set the identity for you (using a cookie to remember it across
      # requests).  It also uses this mechanism if you don't provide an
      # identity object, by calling use_vanity with no arguments.
      #
      # Of course you can also use a block:
      #   class ProjectController < ApplicationController
      #     use_vanity { |controller| controller.params[:project_id] }
      #   end
      def use_vanity(symbol = nil, &block)
        if block
          define_method(:vanity_identity) { block.call(self) }
        else
          define_method :vanity_identity do
            return @vanity_identity if @vanity_identity
            if symbol && object = send(symbol)
              @vanity_identity = object.id
            elsif response # everyday use
              @vanity_identity = cookies["vanity_id"] || ActiveSupport::SecureRandom.hex(16)
              cookies["vanity_id"] = { :value=>@vanity_identity, :expires=>1.month.from_now }
              @vanity_identity
            else # during functional testing
              @vanity_identity = "test"
            end
          end
        end
        around_filter :vanity_context_filter
        before_filter :vanity_reload_filter unless ::Rails.configuration.cache_classes
        before_filter :vanity_query_parameter_filter
      end
      protected :use_vanity
    end


    # Vanity needs these filters.  They are includes in ActionController and
    # automatically added when you use #use_vanity in your controller.
    module Filters
      # Around filter that sets Vanity.context to controller.
      def vanity_context_filter
        previous, Vanity.context = Vanity.context, self
        yield
      ensure
        Vanity.context = previous
      end

      # This filter allows user to choose alternative in experiment using query
      # parameter.
      #
      # Each alternative has a unique fingerprint (run vanity list command to
      # see them all).  A request with the _vanity query parameter is
      # intercepted, the alternative is chosen, and the user redirected to the
      # same request URL sans _vanity parameter.  This only works for GET
      # requests.
      #
      # For example, if the user requests the page
      # http://example.com/?_vanity=2907dac4de, the first alternative of the
      # :null_abc experiment is chosen and the user redirected to
      # http://example.com/.
      def vanity_query_parameter_filter
        if request.get? && params[:_vanity]
          hashes = Array(params.delete(:_vanity))
          Vanity.playground.experiments.each do |id, experiment|
            if experiment.respond_to?(:alternatives)
              experiment.alternatives.each do |alt|
                if hash = hashes.delete(experiment.fingerprint(alt))
                  experiment.chooses alt.value
                  break
                end
              end
            end
            break if hashes.empty?
          end
          redirect_to url_for(params)
        end
      end

      # Before filter to reload Vanity experiments/metrics.  Enabled when
      # cache_classes is false (typically, testing environment).
      def vanity_reload_filter
        Vanity.playground.reload!
      end

      protected :vanity_context_filter, :vanity_query_parameter_filter, :vanity_reload_filter
    end


    # Introduces ab_test helper (controllers and views).  Similar to the generic
    # ab_test method, with the ability to capture content (applicable to views,
    # see examples).
    module Helpers
      # This method returns one of the alternative values in the named A/B test.
      #
      # @example A/B two alternatives for a page
      #   def index
      #     if ab_test(:new_page) # true/false test
      #       render action: "new_page"
      #     else
      #       render action: "index"
      #     end
      #   end
      # @example Similar, alternative value is page name
      #   def index
      #     render action: ab_test(:new_page)
      #   end
      # @example A/B test inside ERB template (condition)
      #   <%= if ab_test(:banner) %>100% less complexity!<% end %>
      # @example A/B test inside ERB template (value)
      #   <%= ab_test(:greeting) %> <%= current_user.name %>
      # @example A/B test inside ERB template (capture)
      #   <% ab_test :features do |count| %>
      #     <%= count %> features to choose from!
      #   <% end %>
      def ab_test(name, &block)
        value = Vanity.playground.experiment(name).choose
        if block
          content = capture(value, &block)
          block_called_from_erb?(block) ? concat(content) : content
        else
          value
        end
      end

      def vanity_h(text)
        h(text)
      end

      def vanity_html_safe(text)
        if text.respond_to?(:html_safe!)
          text.html_safe!
        else
          text
        end
      end

      def vanity_simple_format(text, html_options={})
        vanity_html_safe(simple_format(text, html_options))
      end
    end


    # Step 1: Add a new resource in config/routes.rb:
    #   map.vanity "/vanity/:action/:id", :controller=>:vanity
    #
    # Step 2: Create a new experiments controller:
    #   class VanityController < ApplicationController
    #     include Vanity::Rails::Dashboard
    #   end
    #
    # Step 3: Open your browser to http://localhost:3000/vanity
    module Dashboard
      def index
        render :file=>Vanity.template("_report"), :content_type=>Mime::HTML, :layout=>false
      end

      def chooses
        exp = Vanity.playground.experiment(params[:e])
        exp.chooses(exp.alternatives[params[:a].to_i].value)
        render :file=>Vanity.template("_experiment"), :locals=>{:experiment=>exp}
      end
    end
  end
end


# Enhance ActionController with use_vanity, filters and helper methods.
if defined?(ActionController)
  # Include in controller, add view helper methods.
  ActionController::Base.class_eval do
    extend Vanity::Rails::UseVanity
    include Vanity::Rails::Filters
    helper Vanity::Rails::Helpers
  end

  module ActionController
    class TestCase
      alias :setup_controller_request_and_response_without_vanity :setup_controller_request_and_response
      # Sets Vanity.context to the current controller, so you can do things like:
      #   experiment(:simple).chooses(:green)
      def setup_controller_request_and_response
        setup_controller_request_and_response_without_vanity
        Vanity.context = @controller
      end
    end
  end
end


# Automatically configure Vanity.
if defined?(Rails)
  if Rails.const_defined?(:Railtie) # Rails 3
    class Plugin < Rails::Railtie # :nodoc:
      initializer "vanity.require" do |app|
        Vanity::Rails.load!
      end
    end
  else
    Rails.configuration.after_initialize do
      Vanity::Rails.load!
    end
  end
end


# Reconnect whenever we fork under Passenger.
if defined?(PhusionPassenger)
  PhusionPassenger.on_event(:starting_worker_process) do |forked|
    if forked
      begin
        Vanity.playground.establish_connection if Vanity.playground.collecting?
      rescue Exception=>ex
        Rails.logger.error "Error reconnecting: #{ex.to_s}"
      end
    end
  end
end
<commit_msg>Can't call html_safe! on a string, call html_safe instead.<commit_after>module Vanity
  module Rails #:nodoc:
    def self.load!
      Vanity.playground.load_path = ::Rails.root + Vanity.playground.load_path
      Vanity.playground.logger ||= ::Rails.logger

      # Do this at the very end of initialization, allowing you to change
      # connection adapter, turn collection on/off, etc.
      ::Rails.configuration.after_initialize do
        Vanity.playground.load!
      end
    end

    # The use_vanity method will setup the controller to allow testing and
    # tracking of the current user.
    module UseVanity
      # Defines the vanity_identity method and the set_identity_context filter.
      #
      # Call with the name of a method that returns an object whose identity
      # will be used as the Vanity identity.  Confusing?  Let's try by example:
      #
      #   class ApplicationController < ActionController::Base
      #     use_vanity :current_user
      #
      #     def current_user
      #       User.find(session[:user_id])
      #     end
      #   end
      #
      # If that method (current_user in this example) returns nil, Vanity will
      # set the identity for you (using a cookie to remember it across
      # requests).  It also uses this mechanism if you don't provide an
      # identity object, by calling use_vanity with no arguments.
      #
      # Of course you can also use a block:
      #   class ProjectController < ApplicationController
      #     use_vanity { |controller| controller.params[:project_id] }
      #   end
      def use_vanity(symbol = nil, &block)
        if block
          define_method(:vanity_identity) { block.call(self) }
        else
          define_method :vanity_identity do
            return @vanity_identity if @vanity_identity
            if symbol && object = send(symbol)
              @vanity_identity = object.id
            elsif response # everyday use
              @vanity_identity = cookies["vanity_id"] || ActiveSupport::SecureRandom.hex(16)
              cookies["vanity_id"] = { :value=>@vanity_identity, :expires=>1.month.from_now }
              @vanity_identity
            else # during functional testing
              @vanity_identity = "test"
            end
          end
        end
        around_filter :vanity_context_filter
        before_filter :vanity_reload_filter unless ::Rails.configuration.cache_classes
        before_filter :vanity_query_parameter_filter
      end
      protected :use_vanity
    end


    # Vanity needs these filters.  They are includes in ActionController and
    # automatically added when you use #use_vanity in your controller.
    module Filters
      # Around filter that sets Vanity.context to controller.
      def vanity_context_filter
        previous, Vanity.context = Vanity.context, self
        yield
      ensure
        Vanity.context = previous
      end

      # This filter allows user to choose alternative in experiment using query
      # parameter.
      #
      # Each alternative has a unique fingerprint (run vanity list command to
      # see them all).  A request with the _vanity query parameter is
      # intercepted, the alternative is chosen, and the user redirected to the
      # same request URL sans _vanity parameter.  This only works for GET
      # requests.
      #
      # For example, if the user requests the page
      # http://example.com/?_vanity=2907dac4de, the first alternative of the
      # :null_abc experiment is chosen and the user redirected to
      # http://example.com/.
      def vanity_query_parameter_filter
        if request.get? && params[:_vanity]
          hashes = Array(params.delete(:_vanity))
          Vanity.playground.experiments.each do |id, experiment|
            if experiment.respond_to?(:alternatives)
              experiment.alternatives.each do |alt|
                if hash = hashes.delete(experiment.fingerprint(alt))
                  experiment.chooses alt.value
                  break
                end
              end
            end
            break if hashes.empty?
          end
          redirect_to url_for(params)
        end
      end

      # Before filter to reload Vanity experiments/metrics.  Enabled when
      # cache_classes is false (typically, testing environment).
      def vanity_reload_filter
        Vanity.playground.reload!
      end

      protected :vanity_context_filter, :vanity_query_parameter_filter, :vanity_reload_filter
    end


    # Introduces ab_test helper (controllers and views).  Similar to the generic
    # ab_test method, with the ability to capture content (applicable to views,
    # see examples).
    module Helpers
      # This method returns one of the alternative values in the named A/B test.
      #
      # @example A/B two alternatives for a page
      #   def index
      #     if ab_test(:new_page) # true/false test
      #       render action: "new_page"
      #     else
      #       render action: "index"
      #     end
      #   end
      # @example Similar, alternative value is page name
      #   def index
      #     render action: ab_test(:new_page)
      #   end
      # @example A/B test inside ERB template (condition)
      #   <%= if ab_test(:banner) %>100% less complexity!<% end %>
      # @example A/B test inside ERB template (value)
      #   <%= ab_test(:greeting) %> <%= current_user.name %>
      # @example A/B test inside ERB template (capture)
      #   <% ab_test :features do |count| %>
      #     <%= count %> features to choose from!
      #   <% end %>
      def ab_test(name, &block)
        value = Vanity.playground.experiment(name).choose
        if block
          content = capture(value, &block)
          block_called_from_erb?(block) ? concat(content) : content
        else
          value
        end
      end

      def vanity_h(text)
        h(text)
      end

      def vanity_html_safe(text)
        if text.respond_to?(:html_safe)
          text.html_safe
        else
          text
        end
      end

      def vanity_simple_format(text, html_options={})
        vanity_html_safe(simple_format(text, html_options))
      end
    end


    # Step 1: Add a new resource in config/routes.rb:
    #   map.vanity "/vanity/:action/:id", :controller=>:vanity
    #
    # Step 2: Create a new experiments controller:
    #   class VanityController < ApplicationController
    #     include Vanity::Rails::Dashboard
    #   end
    #
    # Step 3: Open your browser to http://localhost:3000/vanity
    module Dashboard
      def index
        render :file=>Vanity.template("_report"), :content_type=>Mime::HTML, :layout=>false
      end

      def chooses
        exp = Vanity.playground.experiment(params[:e])
        exp.chooses(exp.alternatives[params[:a].to_i].value)
        render :file=>Vanity.template("_experiment"), :locals=>{:experiment=>exp}
      end
    end
  end
end


# Enhance ActionController with use_vanity, filters and helper methods.
if defined?(ActionController)
  # Include in controller, add view helper methods.
  ActionController::Base.class_eval do
    extend Vanity::Rails::UseVanity
    include Vanity::Rails::Filters
    helper Vanity::Rails::Helpers
  end

  module ActionController
    class TestCase
      alias :setup_controller_request_and_response_without_vanity :setup_controller_request_and_response
      # Sets Vanity.context to the current controller, so you can do things like:
      #   experiment(:simple).chooses(:green)
      def setup_controller_request_and_response
        setup_controller_request_and_response_without_vanity
        Vanity.context = @controller
      end
    end
  end
end


# Automatically configure Vanity.
if defined?(Rails)
  if Rails.const_defined?(:Railtie) # Rails 3
    class Plugin < Rails::Railtie # :nodoc:
      initializer "vanity.require" do |app|
        Vanity::Rails.load!
      end
    end
  else
    Rails.configuration.after_initialize do
      Vanity::Rails.load!
    end
  end
end


# Reconnect whenever we fork under Passenger.
if defined?(PhusionPassenger)
  PhusionPassenger.on_event(:starting_worker_process) do |forked|
    if forked
      begin
        Vanity.playground.establish_connection if Vanity.playground.collecting?
      rescue Exception=>ex
        Rails.logger.error "Error reconnecting: #{ex.to_s}"
      end
    end
  end
end

{'fraction_non_alphanumeric': 0.07530679437294223, 'fraction_numerical': 0.0022747680335228975, 'mean_word_length': 2.3763136620856913, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4867553', 'n_tokens_mistral': 4752, 'n_tokens_neox': 4602, 'n_words': 1394}