40 votes

Comment mettre en œuvre un système de réalisation de RoR

Je suis d'essayer, mal, de mettre en œuvre un système de réalisation dans mon Ruby on Rails application.

J'ai une longue liste de réalisations, je voudrais vérifier. Tous sont déclenchées par certains à créer des actions dans divers contrôleurs.

J'ai eu l'idée que je vais avoir une réalisation du modèle, qui inclut le contrôleur et l'action il répond. Puis faire un avant de filtre pour le créer et vérifier les résultats. Je suis coincé quand il s'agit de la définition d'exécution/les réalisations. Chaque réalisation peut être différente des données. Par exemple, on veut savoir à combien de questions que l'utilisateur a répondu, un autre le nombre de commentaires qu'ils ont fait, et un troisième combien de personnes l'utilisateur invités ont répondu.

EST la meilleure chose à faire pour réellement juste intégrer toutes les portions de code directement dans la DB? J'ai pu voir en faisant un autonome bloc qui fait tout l'enregistrement actif à trouver, etc et renvoie true (vrai/faux, bien qu'il nous reste encore des questions au sujet de savoir qu'est-ce que le programme d'installation à l'avance (c'est à dire current_user, etc).

Toute raisonnable des meilleures pratiques qui ne me faites pas se sentir sale? J'ai pu voir plein sur la politique/moteur de règles en cours de chemin, mais cela peut m'effrayer plus d'un plan.

merci! Oren

52voto

molf Points 34978

Je suis d'accord avec votre idée d'utiliser un Achievement modèle.

Vous ne devriez probablement pas mettre en œuvre les déclencheurs de vos contrôleurs, cependant. Imaginez que vous avez deux façons de publier un commentaire, vous sera inévitablement la duplication de code. Ce genre de comportement s'inscrit dans un modèle.

Supposons que vous souhaitez suivre le nombre de commentaires par l'utilisateur, et les prix d'une réalisation pour 100 commentaires. Vous pourriez avoir les modèles suivants:

class User < ActiveRecord::Base
  has_many :comments
  has_many :achievements

  def award(achievement)
    achievements << achievement.new
  end

  def awarded?(achievement)
    achievements.count(:conditions => { :type => achievement }) > 0
  end
end

class Achievement < ActiveRecord::Base
  belongs_to :user
end

class Comment < ActiveRecord::Base
  belongs_to :user
end

class CommentAchievement < Achievement
  def self.check_conditions_for(user)
    # Check if achievement is already awarded before doing possibly expensive
    # operations to see if the achievement conditions are met.
    if !user.awarded?(self) and user.comments.size > 100
      user.award(self)
    end
  end
end

Les différentes réalisations sont toutes les sous-classes de Achievement modèle, et l'utilisation unique de l'héritage de table, de sorte qu'ils sont stockés dans un tableau. Les sous-classes peuvent contenir toute la logique nécessaire pour chaque réalisation. Vous pouvez également stocker des informations supplémentaires dans ce modèle, tels que la date à laquelle la réalisation a été attribué. Assurez-vous que la base de données rejette double réalisations, vous pouvez créer un UNIQUE indice sur l' type et user_id colonnes.

CommentAchievement.check_conditions_for(user) peut être appelé à chaque fois que vous le souhaitez. Vous pouvez créer une tâche en arrière-plan qui s'exécute chaque maintenant et puis, vous pouvez aussi créer un observateur:

# app/models/comment_achievement_observer.rb
class CommentAchievementObserver < ActiveRecord::Observer
  observe :comment

  def after_create(comment)
    CommentAchievement.check_conditions_for(comment.user)
  end
end

# config/environment.rb
config.active_record.observers = :comment_achievement_observer

Le ci-dessus est juste une idée de comment le faire, bien sûr, il peut y en avoir d'autres. Le code est juste un exemple, je n'ai pas réellement testé. J'espère que c'est de l'aide pour vous.

18voto

Paul Campbell Points 171

Vraiment sympa solution, molf.

J'ai roulé dans un plugin / gem avec des générateurs de nouvelles réalisations:

http://github.com/paulca/paths_of_glory

Heureux réalisation!

7voto

TuteC Points 3123

J'ai écrit un Rails 3 gem pour cette tâche, qui travaille pour les badges, les points et les classements. Vous pouvez trouver le code source dans https://github.com/tute/merit.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X