ahoy_matey 2.0.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +112 -37
- data/CONTRIBUTING.md +9 -7
- data/LICENSE.txt +1 -1
- data/README.md +377 -63
- data/app/controllers/ahoy/base_controller.rb +14 -10
- data/app/controllers/ahoy/events_controller.rb +1 -1
- data/app/controllers/ahoy/visits_controller.rb +1 -0
- data/app/jobs/ahoy/geocode_v2_job.rb +3 -4
- data/lib/ahoy.rb +57 -2
- data/lib/ahoy/base_store.rb +32 -3
- data/lib/ahoy/controller.rb +21 -8
- data/lib/ahoy/database_store.rb +33 -16
- data/lib/ahoy/engine.rb +3 -1
- data/lib/ahoy/helper.rb +40 -0
- data/lib/ahoy/model.rb +2 -2
- data/lib/ahoy/query_methods.rb +46 -1
- data/lib/ahoy/tracker.rb +59 -27
- data/lib/ahoy/utils.rb +7 -0
- data/lib/ahoy/version.rb +1 -1
- data/lib/ahoy/visit_properties.rb +73 -37
- data/lib/generators/ahoy/activerecord_generator.rb +17 -26
- data/lib/generators/ahoy/base_generator.rb +1 -1
- data/lib/generators/ahoy/install_generator.rb +1 -1
- data/lib/generators/ahoy/mongoid_generator.rb +1 -5
- data/lib/generators/ahoy/templates/active_record_event_model.rb.tt +10 -0
- data/lib/generators/ahoy/templates/{active_record_migration.rb → active_record_migration.rb.tt} +14 -7
- data/lib/generators/ahoy/templates/active_record_visit_model.rb.tt +6 -0
- data/lib/generators/ahoy/templates/{base_store_initializer.rb → base_store_initializer.rb.tt} +8 -0
- data/lib/generators/ahoy/templates/database_store_initializer.rb.tt +10 -0
- data/lib/generators/ahoy/templates/{mongoid_event_model.rb → mongoid_event_model.rb.tt} +1 -1
- data/lib/generators/ahoy/templates/{mongoid_visit_model.rb → mongoid_visit_model.rb.tt} +9 -7
- data/vendor/assets/javascripts/ahoy.js +539 -552
- metadata +27 -204
- data/.github/ISSUE_TEMPLATE.md +0 -7
- data/.gitignore +0 -17
- data/Gemfile +0 -6
- data/Rakefile +0 -9
- data/ahoy_matey.gemspec +0 -36
- data/docs/Ahoy-2-Upgrade.md +0 -147
- data/docs/Data-Store-Examples.md +0 -240
- data/lib/generators/ahoy/templates/active_record_event_model.rb +0 -10
- data/lib/generators/ahoy/templates/active_record_visit_model.rb +0 -6
- data/lib/generators/ahoy/templates/database_store_initializer.rb +0 -5
- data/test/query_methods/mongoid_test.rb +0 -23
- data/test/query_methods/mysql_json_test.rb +0 -18
- data/test/query_methods/mysql_text_test.rb +0 -19
- data/test/query_methods/postgresql_hstore_test.rb +0 -20
- data/test/query_methods/postgresql_json_test.rb +0 -18
- data/test/query_methods/postgresql_jsonb_test.rb +0 -19
- data/test/query_methods/postgresql_text_test.rb +0 -19
- data/test/test_helper.rb +0 -100
    
        data/lib/ahoy/tracker.rb
    CHANGED
    
    | @@ -1,5 +1,9 @@ | |
| 1 | 
            +
            require "active_support/core_ext/digest/uuid"
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module Ahoy
         | 
| 2 4 | 
             
              class Tracker
         | 
| 5 | 
            +
                UUID_NAMESPACE = "a82ae811-5011-45ab-a728-569df7499c5f"
         | 
| 6 | 
            +
             | 
| 3 7 | 
             
                attr_reader :request, :controller
         | 
| 4 8 |  | 
| 5 9 | 
             
                def initialize(**options)
         | 
| @@ -7,6 +11,7 @@ module Ahoy | |
| 7 11 | 
             
                  @controller = options[:controller]
         | 
| 8 12 | 
             
                  @request = options[:request] || @controller.try(:request)
         | 
| 9 13 | 
             
                  @visit_token = options[:visit_token]
         | 
| 14 | 
            +
                  @user = options[:user]
         | 
| 10 15 | 
             
                  @options = options
         | 
| 11 16 | 
             
                end
         | 
| 12 17 |  | 
| @@ -33,7 +38,7 @@ module Ahoy | |
| 33 38 | 
             
                  report_exception(e)
         | 
| 34 39 | 
             
                end
         | 
| 35 40 |  | 
| 36 | 
            -
                def track_visit(defer: false)
         | 
| 41 | 
            +
                def track_visit(defer: false, started_at: nil)
         | 
| 37 42 | 
             
                  if exclude?
         | 
| 38 43 | 
             
                    debug "Visit excluded"
         | 
| 39 44 | 
             
                  elsif missing_params?
         | 
| @@ -42,16 +47,18 @@ module Ahoy | |
| 42 47 | 
             
                    if defer
         | 
| 43 48 | 
             
                      set_cookie("ahoy_track", true, nil, false)
         | 
| 44 49 | 
             
                    else
         | 
| 50 | 
            +
                      delete_cookie("ahoy_track")
         | 
| 51 | 
            +
             | 
| 45 52 | 
             
                      data = {
         | 
| 46 53 | 
             
                        visit_token: visit_token,
         | 
| 47 54 | 
             
                        visitor_token: visitor_token,
         | 
| 48 55 | 
             
                        user_id: user.try(:id),
         | 
| 49 | 
            -
                        started_at: trusted_time,
         | 
| 56 | 
            +
                        started_at: trusted_time(started_at),
         | 
| 50 57 | 
             
                      }.merge(visit_properties).select { |_, v| v }
         | 
| 51 58 |  | 
| 52 59 | 
             
                      @store.track_visit(data)
         | 
| 53 60 |  | 
| 54 | 
            -
                      Ahoy::GeocodeV2Job.perform_later(visit_token, data[:ip]) if Ahoy.geocode
         | 
| 61 | 
            +
                      Ahoy::GeocodeV2Job.perform_later(visit_token, data[:ip]) if Ahoy.geocode && data[:ip]
         | 
| 55 62 | 
             
                    end
         | 
| 56 63 | 
             
                  end
         | 
| 57 64 | 
             
                  true
         | 
| @@ -60,12 +67,12 @@ module Ahoy | |
| 60 67 | 
             
                end
         | 
| 61 68 |  | 
| 62 69 | 
             
                def geocode(data)
         | 
| 63 | 
            -
                   | 
| 64 | 
            -
                     | 
| 65 | 
            -
                   | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
                   | 
| 70 | 
            +
                  data = {
         | 
| 71 | 
            +
                    visit_token: visit_token
         | 
| 72 | 
            +
                  }.merge(data).select { |_, v| v }
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                  @store.geocode(data)
         | 
| 75 | 
            +
                  true
         | 
| 69 76 | 
             
                rescue => e
         | 
| 70 77 | 
             
                  report_exception(e)
         | 
| 71 78 | 
             
                end
         | 
| @@ -91,8 +98,12 @@ module Ahoy | |
| 91 98 | 
             
                  @visit ||= @store.visit
         | 
| 92 99 | 
             
                end
         | 
| 93 100 |  | 
| 101 | 
            +
                def visit_or_create
         | 
| 102 | 
            +
                  @visit ||= @store.visit_or_create
         | 
| 103 | 
            +
                end
         | 
| 104 | 
            +
             | 
| 94 105 | 
             
                def new_visit?
         | 
| 95 | 
            -
                  !existing_visit_token
         | 
| 106 | 
            +
                  Ahoy.cookies ? !existing_visit_token : visit.nil?
         | 
| 96 107 | 
             
                end
         | 
| 97 108 |  | 
| 98 109 | 
             
                def new_visitor?
         | 
| @@ -113,9 +124,8 @@ module Ahoy | |
| 113 124 | 
             
                  @user ||= @store.user
         | 
| 114 125 | 
             
                end
         | 
| 115 126 |  | 
| 116 | 
            -
                # TODO better name
         | 
| 117 127 | 
             
                def visit_properties
         | 
| 118 | 
            -
                  @visit_properties ||= Ahoy::VisitProperties.new(request, api: api?).generate
         | 
| 128 | 
            +
                  @visit_properties ||= request ? Ahoy::VisitProperties.new(request, api: api?).generate : {}
         | 
| 119 129 | 
             
                end
         | 
| 120 130 |  | 
| 121 131 | 
             
                def visit_token
         | 
| @@ -130,13 +140,13 @@ module Ahoy | |
| 130 140 |  | 
| 131 141 | 
             
                def reset
         | 
| 132 142 | 
             
                  reset_visit
         | 
| 133 | 
            -
                   | 
| 143 | 
            +
                  delete_cookie("ahoy_visitor")
         | 
| 134 144 | 
             
                end
         | 
| 135 145 |  | 
| 136 146 | 
             
                def reset_visit
         | 
| 137 | 
            -
                   | 
| 138 | 
            -
                   | 
| 139 | 
            -
                   | 
| 147 | 
            +
                  delete_cookie("ahoy_visit")
         | 
| 148 | 
            +
                  delete_cookie("ahoy_events")
         | 
| 149 | 
            +
                  delete_cookie("ahoy_track")
         | 
| 140 150 | 
             
                end
         | 
| 141 151 |  | 
| 142 152 | 
             
                protected
         | 
| @@ -146,7 +156,7 @@ module Ahoy | |
| 146 156 | 
             
                end
         | 
| 147 157 |  | 
| 148 158 | 
             
                def missing_params?
         | 
| 149 | 
            -
                  if api? && Ahoy.protect_from_forgery
         | 
| 159 | 
            +
                  if Ahoy.cookies && api? && Ahoy.protect_from_forgery
         | 
| 150 160 | 
             
                    !(existing_visit_token && existing_visitor_token)
         | 
| 151 161 | 
             
                  else
         | 
| 152 162 | 
             
                    false
         | 
| @@ -154,18 +164,24 @@ module Ahoy | |
| 154 164 | 
             
                end
         | 
| 155 165 |  | 
| 156 166 | 
             
                def set_cookie(name, value, duration = nil, use_domain = true)
         | 
| 157 | 
            -
                   | 
| 158 | 
            -
             | 
| 159 | 
            -
             | 
| 167 | 
            +
                  # safety net
         | 
| 168 | 
            +
                  return unless Ahoy.cookies && request
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                  cookie = Ahoy.cookie_options.merge(value: value)
         | 
| 160 171 | 
             
                  cookie[:expires] = duration.from_now if duration
         | 
| 161 | 
            -
                  domain  | 
| 162 | 
            -
                  cookie[:domain]  | 
| 172 | 
            +
                  # prefer cookie_options[:domain] over cookie_domain
         | 
| 173 | 
            +
                  cookie[:domain] ||= Ahoy.cookie_domain if Ahoy.cookie_domain
         | 
| 174 | 
            +
                  cookie.delete(:domain) unless use_domain
         | 
| 163 175 | 
             
                  request.cookie_jar[name] = cookie
         | 
| 164 176 | 
             
                end
         | 
| 165 177 |  | 
| 178 | 
            +
                def delete_cookie(name)
         | 
| 179 | 
            +
                  request.cookie_jar.delete(name) if request && request.cookie_jar[name]
         | 
| 180 | 
            +
                end
         | 
| 181 | 
            +
             | 
| 166 182 | 
             
                def trusted_time(time = nil)
         | 
| 167 183 | 
             
                  if !time || (api? && !(1.minute.ago..Time.now).cover?(time))
         | 
| 168 | 
            -
                    Time. | 
| 184 | 
            +
                    Time.current
         | 
| 169 185 | 
             
                  else
         | 
| 170 186 | 
             
                    time
         | 
| 171 187 | 
             
                  end
         | 
| @@ -176,7 +192,12 @@ module Ahoy | |
| 176 192 | 
             
                end
         | 
| 177 193 |  | 
| 178 194 | 
             
                def report_exception(e)
         | 
| 179 | 
            -
                   | 
| 195 | 
            +
                  if defined?(ActionDispatch::RemoteIp::IpSpoofAttackError) && e.is_a?(ActionDispatch::RemoteIp::IpSpoofAttackError)
         | 
| 196 | 
            +
                    debug "Tracking excluded due to IP spoofing"
         | 
| 197 | 
            +
                  else
         | 
| 198 | 
            +
                    raise e if !defined?(Rails) || Rails.env.development? || Rails.env.test?
         | 
| 199 | 
            +
                    Safely.report_exception(e)
         | 
| 200 | 
            +
                  end
         | 
| 180 201 | 
             
                end
         | 
| 181 202 |  | 
| 182 203 | 
             
                def generate_id
         | 
| @@ -186,6 +207,7 @@ module Ahoy | |
| 186 207 | 
             
                def visit_token_helper
         | 
| 187 208 | 
             
                  @visit_token_helper ||= begin
         | 
| 188 209 | 
             
                    token = existing_visit_token
         | 
| 210 | 
            +
                    token ||= visit_anonymity_set unless Ahoy.cookies
         | 
| 189 211 | 
             
                    token ||= generate_id unless Ahoy.api_only
         | 
| 190 212 | 
             
                    token
         | 
| 191 213 | 
             
                  end
         | 
| @@ -194,6 +216,7 @@ module Ahoy | |
| 194 216 | 
             
                def visitor_token_helper
         | 
| 195 217 | 
             
                  @visitor_token_helper ||= begin
         | 
| 196 218 | 
             
                    token = existing_visitor_token
         | 
| 219 | 
            +
                    token ||= visitor_anonymity_set unless Ahoy.cookies
         | 
| 197 220 | 
             
                    token ||= generate_id unless Ahoy.api_only
         | 
| 198 221 | 
             
                    token
         | 
| 199 222 | 
             
                  end
         | 
| @@ -202,7 +225,7 @@ module Ahoy | |
| 202 225 | 
             
                def existing_visit_token
         | 
| 203 226 | 
             
                  @existing_visit_token ||= begin
         | 
| 204 227 | 
             
                    token = visit_header
         | 
| 205 | 
            -
                    token ||= visit_cookie  | 
| 228 | 
            +
                    token ||= visit_cookie if Ahoy.cookies && !(api? && Ahoy.protect_from_forgery)
         | 
| 206 229 | 
             
                    token ||= visit_param if api?
         | 
| 207 230 | 
             
                    token
         | 
| 208 231 | 
             
                  end
         | 
| @@ -211,12 +234,20 @@ module Ahoy | |
| 211 234 | 
             
                def existing_visitor_token
         | 
| 212 235 | 
             
                  @existing_visitor_token ||= begin
         | 
| 213 236 | 
             
                    token = visitor_header
         | 
| 214 | 
            -
                    token ||= visitor_cookie  | 
| 237 | 
            +
                    token ||= visitor_cookie if Ahoy.cookies && !(api? && Ahoy.protect_from_forgery)
         | 
| 215 238 | 
             
                    token ||= visitor_param if api?
         | 
| 216 239 | 
             
                    token
         | 
| 217 240 | 
             
                  end
         | 
| 218 241 | 
             
                end
         | 
| 219 242 |  | 
| 243 | 
            +
                def visit_anonymity_set
         | 
| 244 | 
            +
                  @visit_anonymity_set ||= Digest::UUID.uuid_v5(UUID_NAMESPACE, ["visit", Ahoy.mask_ip(request.remote_ip), request.user_agent].join("/"))
         | 
| 245 | 
            +
                end
         | 
| 246 | 
            +
             | 
| 247 | 
            +
                def visitor_anonymity_set
         | 
| 248 | 
            +
                  @visitor_anonymity_set ||= Digest::UUID.uuid_v5(UUID_NAMESPACE, ["visitor", Ahoy.mask_ip(request.remote_ip), request.user_agent].join("/"))
         | 
| 249 | 
            +
                end
         | 
| 250 | 
            +
             | 
| 220 251 | 
             
                def visit_cookie
         | 
| 221 252 | 
             
                  @visit_cookie ||= request && request.cookies["ahoy_visit"]
         | 
| 222 253 | 
             
                end
         | 
| @@ -242,11 +273,12 @@ module Ahoy | |
| 242 273 | 
             
                end
         | 
| 243 274 |  | 
| 244 275 | 
             
                def ensure_token(token)
         | 
| 276 | 
            +
                  token = Ahoy::Utils.ensure_utf8(token)
         | 
| 245 277 | 
             
                  token.to_s.gsub(/[^a-z0-9\-]/i, "").first(64) if token
         | 
| 246 278 | 
             
                end
         | 
| 247 279 |  | 
| 248 280 | 
             
                def debug(message)
         | 
| 249 | 
            -
                   | 
| 281 | 
            +
                  Ahoy.log message
         | 
| 250 282 | 
             
                end
         | 
| 251 283 | 
             
              end
         | 
| 252 284 | 
             
            end
         | 
    
        data/lib/ahoy/utils.rb
    ADDED
    
    
    
        data/lib/ahoy/version.rb
    CHANGED
    
    
| @@ -1,6 +1,6 @@ | |
| 1 | 
            -
            require " | 
| 2 | 
            -
            require " | 
| 3 | 
            -
            require " | 
| 1 | 
            +
            require "cgi"
         | 
| 2 | 
            +
            require "device_detector"
         | 
| 3 | 
            +
            require "uri"
         | 
| 4 4 |  | 
| 5 5 | 
             
            module Ahoy
         | 
| 6 6 | 
             
              class VisitProperties
         | 
| @@ -20,59 +20,95 @@ module Ahoy | |
| 20 20 | 
             
                private
         | 
| 21 21 |  | 
| 22 22 | 
             
                def utm_properties
         | 
| 23 | 
            -
                   | 
| 24 | 
            -
                   | 
| 23 | 
            +
                  landing_params = {}
         | 
| 24 | 
            +
                  begin
         | 
| 25 | 
            +
                    landing_uri = URI.parse(landing_page)
         | 
| 26 | 
            +
                    # could also use Rack::Utils.parse_nested_query
         | 
| 27 | 
            +
                    landing_params = CGI.parse(landing_uri.query) if landing_uri
         | 
| 28 | 
            +
                  rescue
         | 
| 29 | 
            +
                    # do nothing
         | 
| 30 | 
            +
                  end
         | 
| 25 31 |  | 
| 26 32 | 
             
                  props = {}
         | 
| 27 33 | 
             
                  %w(utm_source utm_medium utm_term utm_content utm_campaign).each do |name|
         | 
| 28 | 
            -
                    props[name.to_sym] = params[name] || landing_params[name]
         | 
| 34 | 
            +
                    props[name.to_sym] = params[name] || landing_params[name].try(:first)
         | 
| 29 35 | 
             
                  end
         | 
| 30 36 | 
             
                  props
         | 
| 31 37 | 
             
                end
         | 
| 32 38 |  | 
| 33 39 | 
             
                def traffic_properties
         | 
| 34 | 
            -
                   | 
| 35 | 
            -
                  @@referrer_parser ||= RefererParser::Parser.new
         | 
| 36 | 
            -
             | 
| 40 | 
            +
                  uri = URI.parse(referrer) rescue nil
         | 
| 37 41 | 
             
                  {
         | 
| 38 | 
            -
                    referring_domain:  | 
| 39 | 
            -
                    search_keyword: (@@referrer_parser.parse(@referrer)[:term][0..255] rescue nil).presence
         | 
| 42 | 
            +
                    referring_domain: uri.try(:host).try(:first, 255)
         | 
| 40 43 | 
             
                  }
         | 
| 41 44 | 
             
                end
         | 
| 42 45 |  | 
| 43 46 | 
             
                def tech_properties
         | 
| 44 | 
            -
                   | 
| 45 | 
            -
             | 
| 47 | 
            +
                  if Ahoy.user_agent_parser == :device_detector
         | 
| 48 | 
            +
                    client = DeviceDetector.new(request.user_agent)
         | 
| 49 | 
            +
                    device_type =
         | 
| 50 | 
            +
                      case client.device_type
         | 
| 51 | 
            +
                      when "smartphone"
         | 
| 52 | 
            +
                        "Mobile"
         | 
| 53 | 
            +
                      when "tv"
         | 
| 54 | 
            +
                        "TV"
         | 
| 55 | 
            +
                      else
         | 
| 56 | 
            +
                        client.device_type.try(:titleize)
         | 
| 57 | 
            +
                      end
         | 
| 46 58 |  | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
                     | 
| 52 | 
            -
             | 
| 53 | 
            -
                     | 
| 54 | 
            -
             | 
| 55 | 
            -
                    elsif browser.device.console?
         | 
| 56 | 
            -
                      "Console"
         | 
| 57 | 
            -
                    elsif browser.device.tablet?
         | 
| 58 | 
            -
                      "Tablet"
         | 
| 59 | 
            -
                    elsif browser.device.mobile?
         | 
| 60 | 
            -
                      "Mobile"
         | 
| 61 | 
            -
                    else
         | 
| 62 | 
            -
                      "Desktop"
         | 
| 63 | 
            -
                    end
         | 
| 59 | 
            +
                    {
         | 
| 60 | 
            +
                      browser: client.name,
         | 
| 61 | 
            +
                      os: client.os_name,
         | 
| 62 | 
            +
                      device_type: device_type
         | 
| 63 | 
            +
                    }
         | 
| 64 | 
            +
                  else
         | 
| 65 | 
            +
                    raise "Add browser to your Gemfile to use legacy user agent parsing" unless defined?(Browser)
         | 
| 66 | 
            +
                    raise "Add user_agent_parser to your Gemfile to use legacy user agent parsing" unless defined?(UserAgentParser)
         | 
| 64 67 |  | 
| 65 | 
            -
             | 
| 66 | 
            -
                     | 
| 67 | 
            -
             | 
| 68 | 
            -
                     | 
| 69 | 
            -
             | 
| 68 | 
            +
                    # cache for performance
         | 
| 69 | 
            +
                    @@user_agent_parser ||= UserAgentParser::Parser.new
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                    user_agent = request.user_agent
         | 
| 72 | 
            +
                    agent = @@user_agent_parser.parse(user_agent)
         | 
| 73 | 
            +
                    browser = Browser.new(user_agent)
         | 
| 74 | 
            +
                    device_type =
         | 
| 75 | 
            +
                      if browser.bot?
         | 
| 76 | 
            +
                        "Bot"
         | 
| 77 | 
            +
                      elsif browser.device.tv?
         | 
| 78 | 
            +
                        "TV"
         | 
| 79 | 
            +
                      elsif browser.device.console?
         | 
| 80 | 
            +
                        "Console"
         | 
| 81 | 
            +
                      elsif browser.device.tablet?
         | 
| 82 | 
            +
                        "Tablet"
         | 
| 83 | 
            +
                      elsif browser.device.mobile?
         | 
| 84 | 
            +
                        "Mobile"
         | 
| 85 | 
            +
                      else
         | 
| 86 | 
            +
                        "Desktop"
         | 
| 87 | 
            +
                      end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                    {
         | 
| 90 | 
            +
                      browser: agent.name,
         | 
| 91 | 
            +
                      os: agent.os.name,
         | 
| 92 | 
            +
                      device_type: device_type
         | 
| 93 | 
            +
                    }
         | 
| 94 | 
            +
                  end
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                # masking based on Google Analytics anonymization
         | 
| 98 | 
            +
                # https://support.google.com/analytics/answer/2763052
         | 
| 99 | 
            +
                def ip
         | 
| 100 | 
            +
                  ip = request.remote_ip
         | 
| 101 | 
            +
                  if ip && Ahoy.mask_ips
         | 
| 102 | 
            +
                    Ahoy.mask_ip(ip)
         | 
| 103 | 
            +
                  else
         | 
| 104 | 
            +
                    ip
         | 
| 105 | 
            +
                  end
         | 
| 70 106 | 
             
                end
         | 
| 71 107 |  | 
| 72 108 | 
             
                def request_properties
         | 
| 73 109 | 
             
                  {
         | 
| 74 | 
            -
                    ip:  | 
| 75 | 
            -
                    user_agent: request.user_agent,
         | 
| 110 | 
            +
                    ip: ip,
         | 
| 111 | 
            +
                    user_agent: Ahoy::Utils.ensure_utf8(request.user_agent),
         | 
| 76 112 | 
             
                    referrer: referrer,
         | 
| 77 113 | 
             
                    landing_page: landing_page,
         | 
| 78 114 | 
             
                    platform: params["platform"],
         | 
| @@ -1,40 +1,23 @@ | |
| 1 | 
            -
            # taken from https://github.com/collectiveidea/audited/blob/master/lib/generators/audited/install_generator.rb
         | 
| 2 | 
            -
            require "rails/generators"
         | 
| 3 | 
            -
            require "rails/generators/migration"
         | 
| 4 | 
            -
            require "active_record"
         | 
| 5 1 | 
             
            require "rails/generators/active_record"
         | 
| 6 2 |  | 
| 7 3 | 
             
            module Ahoy
         | 
| 8 4 | 
             
              module Generators
         | 
| 9 5 | 
             
                class ActiverecordGenerator < Rails::Generators::Base
         | 
| 10 | 
            -
                  include  | 
| 11 | 
            -
                  source_root File. | 
| 6 | 
            +
                  include ActiveRecord::Generators::Migration
         | 
| 7 | 
            +
                  source_root File.join(__dir__, "templates")
         | 
| 12 8 |  | 
| 13 9 | 
             
                  class_option :database, type: :string, aliases: "-d"
         | 
| 14 10 |  | 
| 15 | 
            -
                  # Implement the required interface for Rails::Generators::Migration.
         | 
| 16 | 
            -
                  def self.next_migration_number(dirname) #:nodoc:
         | 
| 17 | 
            -
                    next_migration_number = current_migration_number(dirname) + 1
         | 
| 18 | 
            -
                    if ::ActiveRecord::Base.timestamped_migrations
         | 
| 19 | 
            -
                      [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max
         | 
| 20 | 
            -
                    else
         | 
| 21 | 
            -
                      "%.3d" % next_migration_number
         | 
| 22 | 
            -
                    end
         | 
| 23 | 
            -
                  end
         | 
| 24 | 
            -
             | 
| 25 11 | 
             
                  def copy_templates
         | 
| 26 12 | 
             
                    template "database_store_initializer.rb", "config/initializers/ahoy.rb"
         | 
| 27 13 | 
             
                    template "active_record_visit_model.rb", "app/models/ahoy/visit.rb"
         | 
| 28 14 | 
             
                    template "active_record_event_model.rb", "app/models/ahoy/event.rb"
         | 
| 29 15 | 
             
                    migration_template "active_record_migration.rb", "db/migrate/create_ahoy_visits_and_events.rb", migration_version: migration_version
         | 
| 30 | 
            -
                     | 
| 31 | 
            -
                    puts "\nAlmost set! Last, run:\n\n    #{migrate_command} db:migrate"
         | 
| 16 | 
            +
                    puts "\nAlmost set! Last, run:\n\n    rails db:migrate"
         | 
| 32 17 | 
             
                  end
         | 
| 33 18 |  | 
| 34 19 | 
             
                  def properties_type
         | 
| 35 | 
            -
                     | 
| 36 | 
            -
                    # so database connection isn't needed
         | 
| 37 | 
            -
                    case ActiveRecord::Base.connection_config[:adapter].to_s
         | 
| 20 | 
            +
                    case adapter
         | 
| 38 21 | 
             
                    when /postg/i # postgres, postgis
         | 
| 39 22 | 
             
                      "jsonb"
         | 
| 40 23 | 
             
                    when /mysql/i
         | 
| @@ -44,14 +27,22 @@ module Ahoy | |
| 44 27 | 
             
                    end
         | 
| 45 28 | 
             
                  end
         | 
| 46 29 |  | 
| 47 | 
            -
                   | 
| 48 | 
            -
             | 
| 30 | 
            +
                  # use connection_config instead of connection.adapter
         | 
| 31 | 
            +
                  # so database connection isn't needed
         | 
| 32 | 
            +
                  def adapter
         | 
| 33 | 
            +
                    if ActiveRecord::VERSION::STRING.to_f >= 6.1
         | 
| 34 | 
            +
                      ActiveRecord::Base.connection_db_config.adapter.to_s
         | 
| 35 | 
            +
                    else
         | 
| 36 | 
            +
                      ActiveRecord::Base.connection_config[:adapter].to_s
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def rails52?
         | 
| 41 | 
            +
                    ActiveRecord::VERSION::STRING.to_f >= 5.2
         | 
| 49 42 | 
             
                  end
         | 
| 50 43 |  | 
| 51 44 | 
             
                  def migration_version
         | 
| 52 | 
            -
                     | 
| 53 | 
            -
                      "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
         | 
| 54 | 
            -
                    end
         | 
| 45 | 
            +
                    "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
         | 
| 55 46 | 
             
                  end
         | 
| 56 47 | 
             
                end
         | 
| 57 48 | 
             
              end
         | 
| @@ -3,7 +3,7 @@ require "rails/generators" | |
| 3 3 | 
             
            module Ahoy
         | 
| 4 4 | 
             
              module Generators
         | 
| 5 5 | 
             
                class BaseGenerator < Rails::Generators::Base
         | 
| 6 | 
            -
                  source_root File. | 
| 6 | 
            +
                  source_root File.join(__dir__, "templates")
         | 
| 7 7 |  | 
| 8 8 | 
             
                  def copy_templates
         | 
| 9 9 | 
             
                    template "base_store_initializer.rb", "config/initializers/ahoy.rb"
         |