diff --git a/lib/the_moderator.rb b/lib/the_moderator.rb index e2879d1..d473b90 100644 --- a/lib/the_moderator.rb +++ b/lib/the_moderator.rb @@ -1,5 +1,6 @@ -require "the_moderator/version" +require 'the_moderator/version' +require 'the_moderator/exceptions' +require 'the_moderator/model' +require 'the_moderator/moderation_model' -module TheModerator - # Your code goes here... -end +require 'the_moderator/railtie' if defined?(Rails) diff --git a/lib/the_moderator/exceptions.rb b/lib/the_moderator/exceptions.rb new file mode 100644 index 0000000..df2e9a7 --- /dev/null +++ b/lib/the_moderator/exceptions.rb @@ -0,0 +1,4 @@ +module TheModerator + class ModerationNotAccepted < StandardError + end +end diff --git a/lib/the_moderator/model.rb b/lib/the_moderator/model.rb new file mode 100644 index 0000000..126db0f --- /dev/null +++ b/lib/the_moderator/model.rb @@ -0,0 +1,49 @@ +module TheModerator + module Model + def self.included(base) + base.has_many :moderations, as: :moderatable, dependent: :destroy + end + + def moderate(*moderated_attributes) + data = moderation_data(*moderated_attributes) + moderations.build(data: {attributes: data}) unless data.empty? + end + + protected + + def moderation_data(*moderated_attributes) + moderate_object moderated_attributes + end + + private + + def moderate_object(moderated_attributes) + object_fields = {} + moderated_attributes.each do |attribute| + if attribute.is_a?(Hash) + attribute.each do |key, value| + data = moderate_association(key, value) + object_fields[:"#{key}_attributes"] = data unless data.empty? + end + elsif changed.include?(attribute.to_s) + object_fields[attribute.to_sym] = send(attribute) + send("#{attribute}=", changed_attributes[attribute.to_s]) + end + end + + object_fields + end + + def moderate_association(assoc, moderated_attributes) + assoc_fields = {} + send(assoc).each do |resource| + if respond_to?("#{assoc}_attributes=") + data = resource.moderation_data(*moderated_attributes) + assoc_fields[resource.id] = data.merge(id: resource.id) unless data.empty? + end + end + + assoc_fields + end + end +end diff --git a/lib/the_moderator/moderation_model.rb b/lib/the_moderator/moderation_model.rb new file mode 100644 index 0000000..16c047b --- /dev/null +++ b/lib/the_moderator/moderation_model.rb @@ -0,0 +1,36 @@ +module TheModerator + module ModerationModel + def self.included(base) + base.send :extend, ClassMethods + + base.class_eval do + belongs_to :moderatable, polymorphic: true + serialize :data + end + end + + module ClassMethods + end + + def accept + self.class.transaction do + destroy + moderatable.update_attributes(data) + end + end + + def accept! + accept || raise(TheModerator::ModerationNotAccepted) + end + + def discard + destroy + end + + def preview + preview = moderatable.clone + preview.attributes = data + preview.freeze + end + end +end diff --git a/lib/the_moderator/railtie.rb b/lib/the_moderator/railtie.rb new file mode 100644 index 0000000..01a9bbd --- /dev/null +++ b/lib/the_moderator/railtie.rb @@ -0,0 +1,9 @@ +module TheModerator + class Railtie < Rails::Railtie + initializer "the_moderator.include_in_active_record" do + ActiveSupport.on_load :active_record do + include TheModerator::Model + end + end + end +end diff --git a/the_moderator.gemspec b/the_moderator.gemspec index 89a8123..d32d65a 100644 --- a/the_moderator.gemspec +++ b/the_moderator.gemspec @@ -18,6 +18,9 @@ Gem::Specification.new do |spec| spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] + spec.add_dependency "activemodel", ">= 3.2.0" + spec.add_dependency "activerecord", ">= 3.2.0" + spec.add_development_dependency "bundler", "~> 1.3" spec.add_development_dependency "rake" end