rails_view_counter 1.0.1
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/MIT-LICENSE +20 -0
- data/README.md +49 -0
- data/Rakefile +6 -0
- data/app/assets/stylesheets/rails_view_counter/application.css +15 -0
- data/app/controllers/rails_view_counter/application_controller.rb +4 -0
- data/app/helpers/rails_view_counter/application_helper.rb +4 -0
- data/app/jobs/rails_view_counter/application_job.rb +4 -0
- data/app/mailers/rails_view_counter/application_mailer.rb +6 -0
- data/app/models/rails_view_counter/application_record.rb +5 -0
- data/app/views/layouts/rails_view_counter/application.html.erb +17 -0
- data/config/routes.rb +2 -0
- data/lib/generators/rails_view_counter/install_generator.rb +18 -0
- data/lib/generators/rails_view_counter/migration_generator.rb +32 -0
- data/lib/generators/templates/initializer.rb +14 -0
- data/lib/generators/templates/migration.rb +6 -0
- data/lib/rails_view_counter/configuration.rb +21 -0
- data/lib/rails_view_counter/controller_additions.rb +24 -0
- data/lib/rails_view_counter/engine.rb +23 -0
- data/lib/rails_view_counter/model_additions.rb +74 -0
- data/lib/rails_view_counter/version.rb +3 -0
- data/lib/rails_view_counter.rb +19 -0
- data/lib/tasks/rails_view_counter_tasks.rake +4 -0
- metadata +81 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 68f292167e4cdd05f97668402c13874c8430c72576617db238fed93300406b32
|
|
4
|
+
data.tar.gz: d548e125c5f634c57b6d52b1bba9f8a8d5985663f6c256921b61848fb64d03dc
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 47a42521d810b3100054ab638ec6f4567a753977d031cd9b0bd2231a7fe688c5defa58656291ff3dab09f7b48e23c24d3bad455b89241e2b12f3ccb5c5c7c58a
|
|
7
|
+
data.tar.gz: 0125db9783a615d06b5be8c0f039b910979b549def60f57ed75115241b16b1227019dd4dfe5ed0bd979717346435352d3fc5c16e8c24065b15a5fae7ebddaafe
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright aric.zheng
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# rails_view_counter
|
|
2
|
+
> A Rails gem for tracking and managing view counts with IP limiting.
|
|
3
|
+
|
|
4
|
+
## Usage
|
|
5
|
+
```sh
|
|
6
|
+
rails generate rails_view_counter:install
|
|
7
|
+
rails generate rails_view_counter:migration posts
|
|
8
|
+
rails db:migrate
|
|
9
|
+
```
|
|
10
|
+
```rb
|
|
11
|
+
# config/initializers/rails_view_counter.rb
|
|
12
|
+
RailsViewCounter.configure do |config|
|
|
13
|
+
config.ip_limit_duration = 2.hours
|
|
14
|
+
config.enable_ip_limit = true
|
|
15
|
+
config.log_views = true
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Post < ApplicationRecord
|
|
20
|
+
# 自动包含 ViewCounter::ModelAdditions
|
|
21
|
+
validates :title, presence: true
|
|
22
|
+
end
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
Add this line to your application's Gemfile:
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
29
|
+
gem "rails_view_counter"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
And then execute:
|
|
33
|
+
```bash
|
|
34
|
+
$ bundle
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Or install it yourself as:
|
|
38
|
+
```bash
|
|
39
|
+
$ gem install rails_view_counter
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Resources
|
|
43
|
+
- https://chat.qwen.ai/c/b1a1ea17-4937-48df-abf0-81be548e3d89
|
|
44
|
+
|
|
45
|
+
## Contributing
|
|
46
|
+
Contribution directions go here.
|
|
47
|
+
|
|
48
|
+
## License
|
|
49
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
|
3
|
+
* listed below.
|
|
4
|
+
*
|
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
|
7
|
+
*
|
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
|
11
|
+
* It is generally better to create a new file per style scope.
|
|
12
|
+
*
|
|
13
|
+
*= require_tree .
|
|
14
|
+
*= require_self
|
|
15
|
+
*/
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Rails view counter</title>
|
|
5
|
+
<%= csrf_meta_tags %>
|
|
6
|
+
<%= csp_meta_tag %>
|
|
7
|
+
|
|
8
|
+
<%= yield :head %>
|
|
9
|
+
|
|
10
|
+
<%= stylesheet_link_tag "rails_view_counter/application", media: "all" %>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
|
|
14
|
+
<%= yield %>
|
|
15
|
+
|
|
16
|
+
</body>
|
|
17
|
+
</html>
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'rails/generators'
|
|
2
|
+
|
|
3
|
+
module RailsViewCounter
|
|
4
|
+
class InstallGenerator < Rails::Generators::Base
|
|
5
|
+
source_root File.expand_path('templates', __dir__)
|
|
6
|
+
desc 'Generates Rails View Counter initializer'
|
|
7
|
+
|
|
8
|
+
def copy_initializer
|
|
9
|
+
template 'initializer.rb', 'config/initializers/rails_view_counter.rb'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def source_paths
|
|
15
|
+
[File.expand_path('../templates', __dir__)]
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'rails/generators'
|
|
2
|
+
require 'rails/generators/migration'
|
|
3
|
+
|
|
4
|
+
module RailsViewCounter
|
|
5
|
+
class MigrationGenerator < Rails::Generators::Base
|
|
6
|
+
include Rails::Generators::Migration
|
|
7
|
+
|
|
8
|
+
source_root File.expand_path('../templates', __dir__)
|
|
9
|
+
desc 'Generates migration for adding view counter to a model'
|
|
10
|
+
|
|
11
|
+
argument :table_name, type: :string, required: true, desc: 'Table name to add view counter to'
|
|
12
|
+
|
|
13
|
+
def create_migration_file
|
|
14
|
+
# 确保表名是复数形式
|
|
15
|
+
plural_table_name = table_name.pluralize
|
|
16
|
+
migration_template 'migration.rb',
|
|
17
|
+
"db/migrate/add_view_counter_to_#{plural_table_name}.rb"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def source_paths
|
|
23
|
+
[File.expand_path('../templates', __dir__)]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# 必需的方法:返回下一个可用的迁移版本号
|
|
27
|
+
def self.next_migration_number(dirname)
|
|
28
|
+
next_migration_number = current_migration_number(dirname) + 1
|
|
29
|
+
ActiveRecord::Migration.next_migration_number(next_migration_number)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# generators/templates/initializer.rb
|
|
2
|
+
RailsViewCounter.configure do |config|
|
|
3
|
+
# IP 限制时间间隔(默认1小时)
|
|
4
|
+
config.ip_limit_duration = 1.hour
|
|
5
|
+
|
|
6
|
+
# 是否启用 IP 限制
|
|
7
|
+
config.enable_ip_limit = true
|
|
8
|
+
|
|
9
|
+
# 是否记录详细访问日志
|
|
10
|
+
config.log_views = false
|
|
11
|
+
|
|
12
|
+
# 缓存存储方式
|
|
13
|
+
config.cache_store = :rails_cache
|
|
14
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# lib/rails_view_counter/configuration.rb
|
|
2
|
+
module RailsViewCounter
|
|
3
|
+
def self.configuration
|
|
4
|
+
@configuration ||= Configuration.new
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def self.configure
|
|
8
|
+
yield(configuration)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class Configuration
|
|
12
|
+
attr_accessor :ip_limit_duration, :enable_ip_limit, :log_views, :cache_store
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@ip_limit_duration = 1.hour
|
|
16
|
+
@enable_ip_limit = true
|
|
17
|
+
@log_views = false
|
|
18
|
+
@cache_store = :rails_cache
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module RailsViewCounter
|
|
2
|
+
module ControllerAdditions
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
def increment_view_count!(viewable, options = {})
|
|
6
|
+
ip_address = get_user_ip
|
|
7
|
+
viewable.increment_view_count!(ip_address, options)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def get_user_ip
|
|
13
|
+
# 优先使用 X-Forwarded-For 头(用于负载均衡器或代理)
|
|
14
|
+
forwarded_ips = request.headers['X-Forwarded-For']
|
|
15
|
+
if forwarded_ips.present?
|
|
16
|
+
# 取第一个 IP(客户端真实 IP)
|
|
17
|
+
forwarded_ips.split(',').first.strip
|
|
18
|
+
else
|
|
19
|
+
# 直接使用 remote_ip
|
|
20
|
+
request.remote_ip
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module RailsViewCounter
|
|
2
|
+
class Engine < ::Rails::Engine
|
|
3
|
+
isolate_namespace RailsViewCounter
|
|
4
|
+
|
|
5
|
+
config.generators do |g|
|
|
6
|
+
g.test_framework :rspec
|
|
7
|
+
g.fixture_replacement :factory_bot
|
|
8
|
+
g.factory_bot dir: 'spec/factories'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
initializer "rails_view_counter.active_record" do
|
|
12
|
+
ActiveSupport.on_load :active_record do
|
|
13
|
+
include RailsViewCounter::ModelAdditions
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
initializer "rails_view_counter.action_controller" do
|
|
18
|
+
ActiveSupport.on_load :action_controller do
|
|
19
|
+
include RailsViewCounter::ControllerAdditions
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# lib/rails_view_counter/model_additions.rb
|
|
2
|
+
module RailsViewCounter
|
|
3
|
+
module ModelAdditions
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
after_initialize :set_default_view_count, if: :new_record?
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def increment_view_count!(ip_address = nil, options = {})
|
|
11
|
+
return false unless view_counter_enabled?
|
|
12
|
+
|
|
13
|
+
if ip_address && should_count_view?(ip_address, options)
|
|
14
|
+
increment!(:view_count)
|
|
15
|
+
log_view(ip_address) if log_views_enabled?
|
|
16
|
+
true
|
|
17
|
+
else
|
|
18
|
+
false
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def can_increment_view_count?(ip_address, options = {})
|
|
23
|
+
should_count_view?(ip_address, options)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def set_default_view_count
|
|
29
|
+
self.view_count ||= 0
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def should_count_view?(ip_address, options = {})
|
|
33
|
+
return true unless ip_address
|
|
34
|
+
|
|
35
|
+
# 获取配置
|
|
36
|
+
limit_duration = options[:limit_duration] || RailsViewCounter.configuration.ip_limit_duration
|
|
37
|
+
enable_ip_limit = options[:enable_ip_limit] || RailsViewCounter.configuration.enable_ip_limit
|
|
38
|
+
|
|
39
|
+
return true unless enable_ip_limit
|
|
40
|
+
|
|
41
|
+
cache_key = generate_cache_key(ip_address)
|
|
42
|
+
|
|
43
|
+
# 检查该 IP 是否在限制时间内已经访问过
|
|
44
|
+
if Rails.cache.read(cache_key)
|
|
45
|
+
return false # 不允许增加浏览次数
|
|
46
|
+
else
|
|
47
|
+
# 设置缓存,有效期为限制时间
|
|
48
|
+
Rails.cache.write(cache_key, true, expires_in: limit_duration)
|
|
49
|
+
return true # 允许增加浏览次数
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def generate_cache_key(ip_address)
|
|
54
|
+
"#{self.class.name.downcase}_#{id}_#{normalize_ip(ip_address)}"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def normalize_ip(ip)
|
|
58
|
+
ip.gsub(/[.:]/, '_')
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def view_counter_enabled?
|
|
62
|
+
true
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def log_views_enabled?
|
|
66
|
+
RailsViewCounter.configuration.log_views
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def log_view(ip_address)
|
|
70
|
+
# 如果需要记录访问日志,这里可以实现
|
|
71
|
+
# ViewCounter::ViewLog.create!(...)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require "rails_view_counter/version"
|
|
2
|
+
require "rails_view_counter/engine"
|
|
3
|
+
require "rails_view_counter/model_additions"
|
|
4
|
+
require "rails_view_counter/controller_additions"
|
|
5
|
+
require "rails_view_counter/configuration"
|
|
6
|
+
|
|
7
|
+
module RailsViewCounter
|
|
8
|
+
class << self
|
|
9
|
+
attr_accessor :configuration
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.configuration
|
|
13
|
+
@configuration ||= Configuration.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.configure
|
|
17
|
+
yield(configuration)
|
|
18
|
+
end
|
|
19
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rails_view_counter
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- aric.zheng
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 2025-11-07 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rails
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 6.0.0
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 6.0.0
|
|
26
|
+
description: A Rails gem for tracking and managing view counts with IP limiting and
|
|
27
|
+
cache optimization.
|
|
28
|
+
email:
|
|
29
|
+
- 1290657123@qq.com
|
|
30
|
+
executables: []
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- MIT-LICENSE
|
|
35
|
+
- README.md
|
|
36
|
+
- Rakefile
|
|
37
|
+
- app/assets/stylesheets/rails_view_counter/application.css
|
|
38
|
+
- app/controllers/rails_view_counter/application_controller.rb
|
|
39
|
+
- app/helpers/rails_view_counter/application_helper.rb
|
|
40
|
+
- app/jobs/rails_view_counter/application_job.rb
|
|
41
|
+
- app/mailers/rails_view_counter/application_mailer.rb
|
|
42
|
+
- app/models/rails_view_counter/application_record.rb
|
|
43
|
+
- app/views/layouts/rails_view_counter/application.html.erb
|
|
44
|
+
- config/routes.rb
|
|
45
|
+
- lib/generators/rails_view_counter/install_generator.rb
|
|
46
|
+
- lib/generators/rails_view_counter/migration_generator.rb
|
|
47
|
+
- lib/generators/templates/initializer.rb
|
|
48
|
+
- lib/generators/templates/migration.rb
|
|
49
|
+
- lib/rails_view_counter.rb
|
|
50
|
+
- lib/rails_view_counter/configuration.rb
|
|
51
|
+
- lib/rails_view_counter/controller_additions.rb
|
|
52
|
+
- lib/rails_view_counter/engine.rb
|
|
53
|
+
- lib/rails_view_counter/model_additions.rb
|
|
54
|
+
- lib/rails_view_counter/version.rb
|
|
55
|
+
- lib/tasks/rails_view_counter_tasks.rake
|
|
56
|
+
homepage: https://js.work
|
|
57
|
+
licenses:
|
|
58
|
+
- MIT
|
|
59
|
+
metadata:
|
|
60
|
+
homepage_uri: https://js.work
|
|
61
|
+
source_code_uri: https://github.com/ariczheng/rails_view_counter
|
|
62
|
+
changelog_uri: https://github.com/ariczheng/rails_view_counter/blob/main/CHANGELOG.md
|
|
63
|
+
allowed_push_host: https://rubygems.org
|
|
64
|
+
rdoc_options: []
|
|
65
|
+
require_paths:
|
|
66
|
+
- lib
|
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
68
|
+
requirements:
|
|
69
|
+
- - ">="
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: '0'
|
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - ">="
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: '0'
|
|
77
|
+
requirements: []
|
|
78
|
+
rubygems_version: 3.6.3
|
|
79
|
+
specification_version: 4
|
|
80
|
+
summary: A Rails gem for tracking and managing view counts with IP limiting.
|
|
81
|
+
test_files: []
|