lib/policy/follower.rb in policy-1.2.0 vs lib/policy/follower.rb in policy-2.0.0

- old
+ new

@@ -1,142 +1,102 @@ # encoding: utf-8 module Policy - # Adds features for the object to follow external policies + # Interface for the class that follows policies module Follower - require_relative "follower/names" - require_relative "follower/followed_policy" - require_relative "follower/followed_policies" - - # Methods to be added to the class the module is included to - # - # @private + # Methods to be added to the follower class module ClassMethods - # @!attribute [r] followed_policies - # The collection of policies to be followed by instances of the class + # Declares a policy to be followed # - # @return [Policy::Follower::FollowedPolicies] + # Mutates the object by adding an item to its {#policies}. # - # @private - def followed_policies - @followed_policies ||= FollowedPolicies.new + # @param [Symbol] name + # + # @return [:follows_policy] the name of the method + def follows_policy(name) + policies.add name + + :follows_policy end - # Adds a policy to the list of {#followed_policies} + # Declares policies to be followed # - # @param [Class] policy - # the policy object klass - # @param [Array<#to_sym>] attributes - # the list of attributes of the instance the policy should be applied to + # Mutates the object by adding items to its {#policies}. # - # @option [#to_sym] :as - # the name for the policy to be used for selecting it - # in {#follow_policies!} and {#follow_policies?} methods + # @param [Symbol, Array<Symbol>] names # - # @return [undefined] - def follow_policy(policy, *attributes, as: nil) - object = FollowedPolicy.new(__policies__, policy, as, *attributes) - followed_policies.add object + # @return [:follows_policies] the name of the method + def follows_policies(*names) + names.each(&method(:follows_policy)) + + :follows_policies end - # Changes the namespace for applied policies + # @!attribute [r] policies + # The collection of followed policies # - # @example For Policies::Finances::TransferConsistency - # use_policies Policies::Finances do - # apply_policy :TransferConstistency, :debet, :credit - # end - # - # @param [Module] namespace - # - # @yield the block in the current scope - # - # @return [undefined] - def use_policies(namespace, &block) - @__policies__ = namespace - instance_eval(&block) - ensure - @__policies__ = nil + # @return [Policy::Follower::Policies] + def policies + @policies ||= Policies.new(self) end - private - - def __policies__ - @__policies__ ||= self - end - end - # Checks whether an instance meets selected policies + # Checks whether an object follows all its policies or subset of policies # - # Mutates the object by adding new #errors + # @overload follow_policies?() + # Checks whether an object follows all registered policies # - # @param [Array<#to_sym>] names - # the ordered list of names to select policies by - # when not names selected all policies will be applied + # @overload follow_policies?(names) + # Checks whether an object follows given policies # - # @raise [Policy::ViolationError] - # unless all selected policies has been met + # @param [#to_sym, Array<#to_sym>] names # - # @return [undefined] - def follow_policies!(*names) - followed_policies.apply_to self, *names - rescue ViolationError => error - collect_errors_from(error) - raise - end - - # Syntax shugar for the {#follow_policies!} with one argument + # @raise [Policy::Follower::NameError] + # if the policy is not registered by name # - # @param [#to_sym] name - # the name of the policy to follow + # @raise [NoMethodError] + # if the name not implemented as follower's instance method + # @raise [ViolationError] + # if the policy is violated by the follower # - # @raise (see #follow_policies!) - # - # @return [undefined] - def follow_policy!(name) - follow_policies! name - end - - # Safely checks whether an instance meets selected policies - # - # Mutates the object by adding new #errors - # - # @param (see #follow_policies!) - # - # @return [Boolean] + # @return [true] if no exception being raised def follow_policies?(*names) - follow_policies!(*names) + __policies__ + .subset(names) # raises NameError + .map(&method(:__send__)) # raises NoMethodError + .each(&method(:__validate_policy__)) # raises ViolationError true - rescue ViolationError - false end - # Syntax shugar for the {#follow_policies?} with one argument + # Checks whether an object follows given policy # - # @param (see #follow_policy!) + # @param [#to_sym] name + # the name of the policy to follow # + # @raise (see #follow_policies?) + # # @return (see #follow_policies?) def follow_policy?(name) follow_policies? name end - private - - # @!parse extend Policy::Follower::ClassMethods - # @!parse include ActiveModel::Validations + # @private def self.included(klass) - klass.extend(ClassMethods).__send__(:include, Validations) + klass.instance_eval { extend ClassMethods } end - def followed_policies - @followed_policies ||= self.class.followed_policies + private + + def __validate_policy__(policy) + fail ViolationError.new(self, policy) unless policy.valid? end - def collect_errors_from(exception) - exception.messages.each { |text| errors.add :base, text } + def __policies__ + self.class.policies end end # module Follower end # module Policy