J'ai trouvé plusieurs solutions à ce problème, par exemple railstat de ce post:
J'ai un tas d'articles et de critiques dont je voudrais un compteur d'accès filtré par des adresses IP uniques. Exactement comme Stackoverflow le fait pour ce post. Mais je ne me soucie pas vraiment d'une solution telle que railstat lorsque google analytics le fait déjà pour moi et inclut beaucoup de code, en gardant une trace d'adresses IP uniques, etc. Ma pensée actuelle est d'utiliser Garb ou d'autres analytics plugin pour extraire les statistiques des pages si elles sont plus anciennes que 12 heures de mise à jour d'une table, mais j'ai également besoin d'un cache_column.
Je suppose que vous pouvez extraire les statistiques d'Analytics pour une page particulière et qu'elles mettent à jour leurs statistiques toutes les 12 heures?
Je me demande s'il y a des raisons pour lesquelles ce serait une mauvaise idée, ou si quelqu'un a une meilleure solution?
Merci
[~ # ~] mise à jour [~ # ~]
Le code de cette réponse a été utilisé comme base pour http://github.com/charlotte-Ruby/impressionist Essayez-le
Il vous faudrait probablement moins de temps pour coder cela dans votre application que pour extraire les données d'Analytics à l'aide de leur API. Ces données seraient probablement plus précises et vous n'auriez pas à vous fier à une dépendance externe .. vous auriez également les statistiques en temps réel au lieu d'attendre 12 heures sur les données Analytics. request.remote_ip
fonctionne plutôt bien. Voici une solution utilisant le polymorphisme. Veuillez noter que ce code n'a pas été testé, mais il devrait être proche.
Créez un nouveau modèle/migration pour stocker vos pages vues (impressions):
class Impressions < ActiveRecord::Base
belongs_to :impressionable, :polymorphic=>true
end
class CreateImpressionsTable < ActiveRecord::Migration
def self.up
create_table :impressions, :force => true do |t|
t.string :impressionable_type
t.integer :impressionable_id
t.integer :user_id
t.string :ip_address
t.timestamps
end
end
def self.down
drop_table :impressions
end
end
Ajoutez une ligne à votre modèle d'article pour l'association et ajoutez une méthode pour renvoyer le nombre d'impressions:
class Article < ActiveRecord::Base
has_many :impressions, :as=>:impressionable
def impression_count
impressions.size
end
def unique_impression_count
# impressions.group(:ip_address).size gives => {'127.0.0.1'=>9, '0.0.0.0'=>1}
# so getting keys from the hash and calculating the number of keys
impressions.group(:ip_address).size.keys.length #TESTED
end
end
Créez un before_filter pour articles_controller sur l'action show:
before_filter :log_impression, :only=> [:show]
def log_impression
@article = Article.find(params[:id])
# this assumes you have a current_user method in your authentication system
@article.impressions.create(ip_address: request.remote_ip,user_id:current_user.id)
end
Ensuite, vous appelez simplement le unique_impression_count dans votre vue
<%[email protected]_impression_count %>
Si vous l'utilisez sur un tas de modèles, vous voudrez peut-être DRY le mettre en place. Mettez le def avant_filter dans application_controller et utilisez quelque chose de dynamique comme:
impressionable_class = controller_name.gsub("Controller","").constantize
impressionable_instance = impressionable_class.find(params[:id])
impressionable_instance.impressions.create(ip_address:request.remote_ip,user_id:current_user.id)
Et déplacez également le code du modèle Article vers un module qui sera inclus dans ActiveRecord :: Base. Vous pouvez mettre le send include dans une config/initializer .. ou si vous voulez devenir fou, il suffit de transformer le tout en un moteur Rails, afin que vous puissiez le réutiliser sur d'autres applications.
module Impressionable
def is_impressionable
has_many :impressions, :as=>:impressionable
include InstanceMethods
end
module InstanceMethods
def impression_count
impressions.size
end
def unique_impression_count
impressions.group(:ip_address).size
end
end
end
ActiveRecord::Base.extend Impressionable