Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
ActiveLayer provides validations and attribute filtering in a layer sitting on top of any model.
branch: master

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
lib
spec
.gitignore
CHANGELOG.md
Gemfile
Gemfile.lock
LICENSE
README.md
Rakefile
active_layer.gemspec

README.md

ActiveLayer

ActiveLayer provides a simple way to apply a set of validations, attribute filtering to your models.

ActiveRecord and other ORM validations are great for simple/ and relatively complex scenarios but they can very quickly become overloaded. ActiveLayer takes the approach that you might not want to have 'all' your validations in the model all the time. You might want to have a different set of accessible attributes for different classes of users.

Quick Example

    class User < ActiveRecord::Base; end
    # Every user field you want.. 

    # This layer uses the ActiveRecord adapter which pulls in several other pieces
    class UserLayer
        include ActiveLayer::ActiveRecord

        attr_accessible :name, :email, :address

        validates :name, :email, :presence => true
        validates :address_validation

        before_validate :normalize_address

        def normalize_address; end
        def address_validation
            errors.add(:address, :invalid) if address.blank?
        end
    end

    # Now how to use it:
    user = User.find(1)
    layer = UserLayer.new(user)
    layer.update_attributes( {:name => '', :admin => true, :address => 'on a busy road'} )   # => false
    layer.errors[:name].present # => true
    user.errors[:name].present => true
    user.admin  # => false   - was filtered out

Some of the players

  • ActiveLayer::Proxy
  • ActiveLayer::Validations
  • ActiveLayer::Attributes
  • ActiveLayer::Persistence

ActiveLayer::Proxy

This module provides the ability to delegate method calls down to the object and typically you would not use this element directly. However, it does provide one key method active__layer__object which provides access to the underlying object/model. This may be necessary in certain cases.

This module also brings in the layers method which provides a friendly accessor for the active_layer_object

ActiveLayer::Validations

Currently the majority of the functionality resides in this module and provides the ability for composable validation classes to be layered together. This module is completely compatible with the wonderful ActiveModel::Validation module and in fact just wraps it and provides extra functionality.

Currently the following is supported:

  • Standard ActiveModel::Validators support (Each, With, Custom, etc.)
  • Custom validation methods
  • before_validation and after_validation hooks (Just like ActiveRecord)
  • Nested ActiveLayer validations (This is neat!)
  • All existing custom validators should 'just work'

Examples

    class AddressValidator
        include ActiveLayer::Validations

        before_validation :normalize_address
        validates :address, :presence => true
        validate :custom_method

        def normalize_address; end
        def custom_method; end
    end

    class EmailValidator
        include ActiveLayer::Validations

        validates :email, :presence => true
    end

    class UserValidator
        include ActiveLayer::Validations

        validates :name, :presence => true
        validates_with EmailValidator 
        validates_with AddressValidator, :attributes => [:addresses]
    end

    # the EmailValidator will get passed the user object
    # the AddressValidator will get passed each address of the user and merge the errors back up
    user = User.find(1)
    validator = UserValidator.new(user)
    validator.valid?   # => true/false

ActiveLayer::Attributes

This module provides the ability to bulk assign attributes with attribute protection via att_accessible. By default all attributes are not assignable and you must declare which attributes are accessible. Note, each attribute is available for individual assigning or reading.

Examples

    class FlawedUserFilter
        all_attributes_accessible!
        # All attributes are now assignable
    end

    class UserFilter
        attr_accessible :name, :address
    end

    user = User.find(1)
    filter = UserFilter.new(user)
    filter.attributes = {:name => 'Bob', 'admin' => true}
    user.admin  #  => false

ActiveLayer::Persistence

This layer is responsible for providing the save and update_attributes methods that function very similar to ActiveRecord. Both layers invoke the validations in the layer, if currently mixed in and ultimately delegate to the proxy object for saving. If the Attributes module is mixed in then the guards will be used however, if it is not mixed then active_layer_object.attributes=(hash) will be invoked.

Note: If you plan to use Persistence with Attributes then you must mix-in the Attributes module after the Persistence module

Examples

    class UserPersistor
        include ActiveLayer::Persistence
    end

    user = User.find(1)
    persistor = UserPersistor.new(user)
    persistor.save
    persistor.save!  # will raise an ActiveLayer::RecordInvalidError with a #record method
    persistor.update_attributes(:name => 'new')
    persistor.update_attributes!(:name => 'new')

TODO / Plans

  • Ensure that the valid? method calls the underlying proxy object.valid?
  • Nested attribute support - similar to Rails - but in an adaptable manner for use in other ORMs
  • Add support for additional ORMs
  • Ideas?

License

ActiveLayer is available under the terms of the MIT license (see LICENSE.txt for details).

Something went wrong with that request. Please try again.