footprinted 0.1.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 +7 -0
- data/CHANGELOG.md +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +182 -0
- data/Rakefile +4 -0
- data/TODO +3 -0
- data/lib/footprinted/configuration.rb +10 -0
- data/lib/footprinted/model.rb +73 -0
- data/lib/footprinted/railtie.rb +15 -0
- data/lib/footprinted/trackable_activity.rb +55 -0
- data/lib/footprinted/version.rb +5 -0
- data/lib/footprinted.rb +28 -0
- data/lib/generators/footprinted/install_generator.rb +29 -0
- data/lib/generators/footprinted/templates/create_footprinted_trackable_activities.rb.erb +30 -0
- data/lib/generators/footprinted/templates/footprinted.rb +4 -0
- data/sig/footprinted.rbs +4 -0
- metadata +120 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9896445daea0ce69e019da7472258e3c87035ce60245e8941de245edda8d3865
|
4
|
+
data.tar.gz: 3b858b7cc413344388f9e9ccacce615e0a0c56a3e461d87cc69204e52c722b04
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 60f7ecfda0afd96cbdbc67591d1c6e5687e02bce4d30f8b5f2b3fdaad61d5493332b3d2a6c8183a0fc960d8e78dfc124af7e934cacdc77558ec5eb3f04e6c772
|
7
|
+
data.tar.gz: 876c40969d9a9de55dfe8298808dc162519da408f578e20d6f5b66516e9c272696f82c4f232027ec92915c23cb6277dbf1a49e95a18d6e3ee56c072bce378ef2
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## [0.1.0] - 2024-09-25
|
4
|
+
|
5
|
+
- Initial release
|
6
|
+
- Added Trackable concern for easy activity tracking
|
7
|
+
- Integrated with trackdown gem for IP geolocation
|
8
|
+
- Added customizable tracking associations
|
9
|
+
- Created install generator for easy setup
|
10
|
+
- Added configuration options
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2024 Javi R
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
# 👣 `footprinted` - Track geolocated user activity in Rails
|
2
|
+
|
3
|
+
`footprinted` provides a simple way to track user activity with associated IP addresses and geolocation data in your Rails app.
|
4
|
+
|
5
|
+
It's good for tracking profile views, downloads, login attempts, or any user interaction where location matters.
|
6
|
+
|
7
|
+
## Why
|
8
|
+
|
9
|
+
Sometimes you need to know where your users are performing certain actions from.
|
10
|
+
|
11
|
+
For example, let's say your users have profiles. Where has a particular profile been viewed from?
|
12
|
+
|
13
|
+
This gem makes it trivial to track and analyze this kind of data:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
# First, add this to your User model
|
17
|
+
has_trackable :profile_views
|
18
|
+
|
19
|
+
# Then, track the activity in the controller
|
20
|
+
@user.track_profile_view(ip: request.remote_ip)
|
21
|
+
|
22
|
+
# And finally, analyze the data
|
23
|
+
@user.profile_views.group(:country).count
|
24
|
+
# => { 'US'=>529, 'UK'=>291, 'CA'=>78... }
|
25
|
+
```
|
26
|
+
|
27
|
+
That's it! This is all you need for `footprinted` to store the profile view along with the IP's geolocation data.
|
28
|
+
|
29
|
+
> [!NOTE]
|
30
|
+
> By adding `has_trackable :profile_views` to your model, `footprinted` automatically creates a `profile_views` association and a `track_profile_view` method to your User model.
|
31
|
+
>
|
32
|
+
> `footprinted` does all the heavy lifting for you, so you don't need to define any models or associations. Just track and query.
|
33
|
+
|
34
|
+
|
35
|
+
## How it works
|
36
|
+
|
37
|
+
`footprinted` relies on a `trackable_activities` table, and provides a model concern to interact with it.
|
38
|
+
|
39
|
+
This model concern allows you to define polymorphic associations to store activity data associated with any model.
|
40
|
+
|
41
|
+
For each activity, `footprinted` stores:
|
42
|
+
- IP address
|
43
|
+
- Country
|
44
|
+
- City
|
45
|
+
- Activity type
|
46
|
+
- Event timestamp
|
47
|
+
- Optionally, an associated `performer` record, which could be a `user`, `admin`, or any other model. It answers the question: "who triggered this activity?"
|
48
|
+
|
49
|
+
`footprinted` also provides named methods that interact with the `trackable_activities` table to save and query this data.
|
50
|
+
|
51
|
+
For example, `has_trackable :profile_views` will generate the `profile_views` association and the `track_profile_view` method. Similarly, `has_trackable :downloads` will generate the `downloads` association and the `track_download` method.
|
52
|
+
|
53
|
+
## Installation
|
54
|
+
|
55
|
+
> [!IMPORTANT]
|
56
|
+
> This gem depends on the [`trackdown`](https://github.com/rameerez/trackdown) gem for locating IPs.
|
57
|
+
>
|
58
|
+
> **Start by following the `trackdown` README to install and configure the gem**, and make sure you have a valid installation with a working MaxMind database before continuing – otherwise we won't be able to get any geolocation data from IPs.
|
59
|
+
|
60
|
+
After [`trackdown`](https://github.com/rameerez/trackdown) has been installed and configured, add this line to your application's Gemfile:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
gem 'footprinted'
|
64
|
+
```
|
65
|
+
|
66
|
+
And then execute:
|
67
|
+
|
68
|
+
```bash
|
69
|
+
bundle install
|
70
|
+
rails generate footprinted:install
|
71
|
+
rails db:migrate
|
72
|
+
```
|
73
|
+
|
74
|
+
This will create a migration file to create the polymorphic `trackable_activities` table, and migrate the database.
|
75
|
+
|
76
|
+
## Usage
|
77
|
+
|
78
|
+
### Basic Setup
|
79
|
+
|
80
|
+
Include the `Footprinted::Model` concern and declare what you want to track:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
class User < ApplicationRecord
|
84
|
+
include Footprinted::Model
|
85
|
+
|
86
|
+
# Track a single activity type
|
87
|
+
has_trackable :profile_views
|
88
|
+
|
89
|
+
# Track multiple activity types
|
90
|
+
has_trackable :downloads
|
91
|
+
has_trackable :login_attempts
|
92
|
+
end
|
93
|
+
```
|
94
|
+
|
95
|
+
### Recording Activity
|
96
|
+
|
97
|
+
`footprinted` generates methods for you.
|
98
|
+
|
99
|
+
For example, the `has_trackable :profile_views` association automatically provides you with a `track_profile_view` method that you can use:
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
# Basic tracking with IP
|
103
|
+
user.track_profile_view(ip: request.remote_ip)
|
104
|
+
|
105
|
+
# Or track with a performer as well ("who triggered the activity?")
|
106
|
+
user.track_profile_view(
|
107
|
+
ip: request.remote_ip,
|
108
|
+
performer: current_user
|
109
|
+
)
|
110
|
+
```
|
111
|
+
|
112
|
+
### Querying Activity
|
113
|
+
|
114
|
+
#### Basic Queries
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
# Basic queries
|
118
|
+
user.profile_views.recent
|
119
|
+
user.profile_views.last_days(7)
|
120
|
+
user.profile_views.between(1.week.ago, Time.current)
|
121
|
+
|
122
|
+
# Location queries
|
123
|
+
user.profile_views.by_country('US')
|
124
|
+
user.profile_views.countries # => ['US', 'UK', 'CA', ...]
|
125
|
+
|
126
|
+
# Performer queries
|
127
|
+
user.profile_views.performed_by(some_user)
|
128
|
+
```
|
129
|
+
|
130
|
+
### Advanced Usage
|
131
|
+
|
132
|
+
Track multiple activity types:
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
class Resource < ApplicationRecord
|
136
|
+
include Footprinted::Model
|
137
|
+
|
138
|
+
has_trackable :downloads
|
139
|
+
has_trackable :previews
|
140
|
+
end
|
141
|
+
|
142
|
+
# Track activities
|
143
|
+
product.track_download(ip: request.remote_ip)
|
144
|
+
product.track_preview(ip: request.remote_ip)
|
145
|
+
|
146
|
+
# Query activities
|
147
|
+
product.downloads.count
|
148
|
+
product.previews.last_days(30)
|
149
|
+
product.downloads.between(1.week.ago, Time.current)
|
150
|
+
```
|
151
|
+
|
152
|
+
Time-based analysis:
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
# Daily activity for the last 30 days
|
156
|
+
resource.downloads
|
157
|
+
.where('created_at > ?', 30.days.ago)
|
158
|
+
.group("DATE(created_at)")
|
159
|
+
.count
|
160
|
+
.transform_keys { |k| k.strftime("%Y-%m-%d") }
|
161
|
+
# => {"2024-03-26" => 5, "2024-03-25" => 3, ...}
|
162
|
+
|
163
|
+
# Hourly distribution
|
164
|
+
resource.downloads
|
165
|
+
.group("HOUR(created_at)")
|
166
|
+
.count
|
167
|
+
# => {0=>10, 1=>5, 2=>8, ...}
|
168
|
+
```
|
169
|
+
|
170
|
+
## Development
|
171
|
+
|
172
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
173
|
+
|
174
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
175
|
+
|
176
|
+
## Contributing
|
177
|
+
|
178
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/rameerez/footprinted. Our code of conduct is: just be nice and make your mom proud of what you do and post online.
|
179
|
+
|
180
|
+
## License
|
181
|
+
|
182
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/TODO
ADDED
@@ -0,0 +1,3 @@
|
|
1
|
+
✘ Add index on users t.index ["user_id"], name: "index_trackable_activities_on_user_id" @cancelled(24-09-26 16:59)
|
2
|
+
✔ make user:references optional in migration (activities may not have an associated user) -- or just make it more flexible, like a performer polymorphic association or something @done(24-10-30 01:35)
|
3
|
+
✔ can they have multiple activity types per model? (user: profile_views, downloads, etc) @done(24-09-26 17:28)
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Footprinted
|
4
|
+
module Model
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
# The Footprinted::Model module provides a flexible way to track activities related to any model that includes this concern.
|
8
|
+
#
|
9
|
+
# Footprinted tracks activities through a polymorphic association: the Footprinted::TrackableActivity model.
|
10
|
+
#
|
11
|
+
# The Footprinted::Model concern sets up a :trackable_activities association using the
|
12
|
+
# Footprinted::TrackableActivity model.
|
13
|
+
#
|
14
|
+
# It also provides a basic method to track unnamed activities, `track_activity`,
|
15
|
+
# which can be used as is (not recommended) or overridden with a custom activity type:
|
16
|
+
#
|
17
|
+
# Track specific types of activities using the `has_trackable` class method.
|
18
|
+
# This method also dynamically defines a method to create activity records for the custom association.
|
19
|
+
# For example, `has_trackable :profile_views` generates the `track_profile_view` method.
|
20
|
+
#
|
21
|
+
# Example:
|
22
|
+
# class YourModel < ApplicationRecord
|
23
|
+
# include Trackable
|
24
|
+
# has_trackable :profile_views
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# The above will:
|
28
|
+
# - Create a `has_many :profile_views` association.
|
29
|
+
# - Define a method `track_profile_view` (singular) to create records in `profile_views`.
|
30
|
+
#
|
31
|
+
#
|
32
|
+
# Methods:
|
33
|
+
#
|
34
|
+
# - has_trackable(association_name): Sets up a custom association for tracking activities.
|
35
|
+
# This method dynamically defines a tracking method based on the given association name.
|
36
|
+
#
|
37
|
+
# - track_activity(ip, user = nil): Default method provided to track activities. It logs
|
38
|
+
# the IP address, and optionally, the user involved in the activity. This method can be
|
39
|
+
# overridden in the model including this module for custom behavior.
|
40
|
+
#
|
41
|
+
# Note:
|
42
|
+
# The Footprinted::TrackableActivity model must exist and have a polymorphic association set up
|
43
|
+
# with the :trackable attribute for this concern to function correctly.
|
44
|
+
|
45
|
+
included do
|
46
|
+
has_many :trackable_activities, as: :trackable, class_name: 'Footprinted::TrackableActivity', dependent: :destroy
|
47
|
+
end
|
48
|
+
|
49
|
+
class_methods do
|
50
|
+
# Method to set custom association names
|
51
|
+
def has_trackable(association_name)
|
52
|
+
track_method_name = "track_#{association_name.to_s.singularize}"
|
53
|
+
|
54
|
+
has_many association_name, -> { where(activity_type: association_name.to_s.singularize) },
|
55
|
+
as: :trackable, class_name: 'Footprinted::TrackableActivity'
|
56
|
+
|
57
|
+
# Define a custom method for tracking activities of this type
|
58
|
+
define_method(track_method_name) do |ip:, performer: nil|
|
59
|
+
send(association_name).create!(
|
60
|
+
ip: ip,
|
61
|
+
performer: performer,
|
62
|
+
activity_type: association_name.to_s.singularize
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Fallback method for tracking activity. This will be overridden if has_trackable is called.
|
69
|
+
def track_activity(ip:, user: nil, activity_type: nil)
|
70
|
+
trackable_activities.create(ip: ip, user: user, activity_type: activity_type)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Footprinted
|
4
|
+
class Railtie < Rails::Railtie
|
5
|
+
initializer "footprinted.initialize" do
|
6
|
+
ActiveSupport.on_load(:active_record) do
|
7
|
+
extend Footprinted::Model
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
generators do
|
12
|
+
require "generators/footprinted/install_generator"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Footprinted
|
4
|
+
class TrackableActivity < ActiveRecord::Base
|
5
|
+
# Associations
|
6
|
+
belongs_to :trackable, polymorphic: true
|
7
|
+
belongs_to :performer, polymorphic: true, optional: true
|
8
|
+
|
9
|
+
# Validations
|
10
|
+
validates :ip, presence: true
|
11
|
+
validates :activity_type, presence: true
|
12
|
+
validates :trackable, presence: true
|
13
|
+
|
14
|
+
# Callbacks
|
15
|
+
before_save :set_geolocation_data
|
16
|
+
|
17
|
+
# Scopes
|
18
|
+
scope :by_activity, ->(type) { where(activity_type: type) }
|
19
|
+
scope :by_country, ->(country) { where(country: country) }
|
20
|
+
scope :recent, -> { order(created_at: :desc) }
|
21
|
+
scope :performed_by, ->(performer) { where(performer: performer) }
|
22
|
+
scope :between, ->(start_date, end_date) { where(created_at: start_date..end_date) }
|
23
|
+
scope :last_days, ->(days) { where('created_at >= ?', days.days.ago) }
|
24
|
+
|
25
|
+
# Class methods
|
26
|
+
def self.activity_types
|
27
|
+
distinct.pluck(:activity_type)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.countries
|
31
|
+
distinct.where.not(country: nil).pluck(:country)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def set_geolocation_data
|
37
|
+
return unless ip.present?
|
38
|
+
|
39
|
+
unless defined?(Trackdown)
|
40
|
+
raise Footprinted::Error, "The Trackdown gem is not installed. Please add `gem 'trackdown'` to your Gemfile and follow the setup instructions to configure the gem and download an IP geolocation database."
|
41
|
+
end
|
42
|
+
|
43
|
+
unless Trackdown.database_exists?
|
44
|
+
raise Footprinted::Error, "MaxMind IP geolocation database not found. Please follow the Trackdown gem setup instructions to configure the gem and download an IP geolocation database."
|
45
|
+
end
|
46
|
+
|
47
|
+
location = Trackdown.locate(ip.to_s)
|
48
|
+
self.country = location.country_code
|
49
|
+
self.city = location.city
|
50
|
+
rescue => e
|
51
|
+
Rails.logger.error "Failed to geolocate IP #{ip}: #{e.message}"
|
52
|
+
nil # Don't fail the save if geolocation fails
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/footprinted.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "footprinted/version"
|
4
|
+
require_relative "footprinted/configuration"
|
5
|
+
require_relative "footprinted/model"
|
6
|
+
require_relative "footprinted/trackable_activity"
|
7
|
+
|
8
|
+
module Footprinted
|
9
|
+
class Error < StandardError; end
|
10
|
+
|
11
|
+
class << self
|
12
|
+
attr_writer :configuration
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.configuration
|
16
|
+
@configuration ||= Configuration.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.configure
|
20
|
+
yield(configuration)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.reset
|
24
|
+
@configuration = Configuration.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
require "footprinted/railtie" if defined?(Rails)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/generators/base'
|
4
|
+
require 'rails/generators/active_record'
|
5
|
+
|
6
|
+
module Footprinted
|
7
|
+
module Generators
|
8
|
+
class InstallGenerator < Rails::Generators::Base
|
9
|
+
include ActiveRecord::Generators::Migration
|
10
|
+
|
11
|
+
source_root File.expand_path('templates', __dir__)
|
12
|
+
|
13
|
+
def self.next_migration_number(dir)
|
14
|
+
ActiveRecord::Generators::Base.next_migration_number(dir)
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_migration_file
|
18
|
+
migration_template 'create_footprinted_trackable_activities.rb.erb', File.join(db_migrate_path, "create_footprinted_trackable_activities.rb")
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def migration_version
|
24
|
+
"[#{ActiveRecord::VERSION::STRING.to_f}]"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class CreateFootprintedTrackableActivities < ActiveRecord::Migration<%= migration_version %>
|
2
|
+
def change
|
3
|
+
primary_key_type, foreign_key_type = primary_and_foreign_key_types
|
4
|
+
|
5
|
+
create_table :trackable_activities, id: primary_key_type do |t|
|
6
|
+
t.inet :ip, null: false
|
7
|
+
t.text :country
|
8
|
+
t.text :city
|
9
|
+
t.references :trackable, polymorphic: true, null: false, type: foreign_key_type, index: true
|
10
|
+
t.references :performer, polymorphic: true, type: foreign_key_type, index: true
|
11
|
+
t.text :activity_type, null: false
|
12
|
+
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
add_index :trackable_activities, [:trackable_type, :trackable_id, :activity_type]
|
17
|
+
add_index :trackable_activities, :activity_type
|
18
|
+
add_index :trackable_activities, :country
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def primary_and_foreign_key_types
|
24
|
+
config = Rails.configuration.generators
|
25
|
+
setting = config.options[config.orm][:primary_key_type]
|
26
|
+
primary_key_type = setting || :primary_key
|
27
|
+
foreign_key_type = setting || :bigint
|
28
|
+
[primary_key_type, foreign_key_type]
|
29
|
+
end
|
30
|
+
end
|
data/sig/footprinted.rbs
ADDED
metadata
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: footprinted
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- rameerez
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-10-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '7.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '7.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: trackdown
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.1'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubocop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.7'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.7'
|
69
|
+
description: Track user activity with associated IP addresses and geolocation info,
|
70
|
+
easily and with minimal setup. It's good for tracking profile views, downloads,
|
71
|
+
login attempts, or any user interaction where location matters.
|
72
|
+
email:
|
73
|
+
- rubygems@rameerez.com
|
74
|
+
executables: []
|
75
|
+
extensions: []
|
76
|
+
extra_rdoc_files: []
|
77
|
+
files:
|
78
|
+
- CHANGELOG.md
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- TODO
|
83
|
+
- lib/footprinted.rb
|
84
|
+
- lib/footprinted/configuration.rb
|
85
|
+
- lib/footprinted/model.rb
|
86
|
+
- lib/footprinted/railtie.rb
|
87
|
+
- lib/footprinted/trackable_activity.rb
|
88
|
+
- lib/footprinted/version.rb
|
89
|
+
- lib/generators/footprinted/install_generator.rb
|
90
|
+
- lib/generators/footprinted/templates/create_footprinted_trackable_activities.rb.erb
|
91
|
+
- lib/generators/footprinted/templates/footprinted.rb
|
92
|
+
- sig/footprinted.rbs
|
93
|
+
homepage: https://github.com/rameerez/footprinted
|
94
|
+
licenses:
|
95
|
+
- MIT
|
96
|
+
metadata:
|
97
|
+
allowed_push_host: https://rubygems.org
|
98
|
+
homepage_uri: https://github.com/rameerez/footprinted
|
99
|
+
source_code_uri: https://github.com/rameerez/footprinted
|
100
|
+
changelog_uri: https://github.com/rameerez/footprinted/blob/main/CHANGELOG.md
|
101
|
+
post_install_message:
|
102
|
+
rdoc_options: []
|
103
|
+
require_paths:
|
104
|
+
- lib
|
105
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 3.0.0
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
requirements: []
|
116
|
+
rubygems_version: 3.5.16
|
117
|
+
signing_key:
|
118
|
+
specification_version: 4
|
119
|
+
summary: Track IP-geolocated user activity in your Rails app
|
120
|
+
test_files: []
|