Created
February 28, 2011 18:44
-
-
Save TomTriple/847786 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# See Mike Perham's proposal on ticket: https://rails.lighthouseapp.com/projects/8994/tickets/6477-activemodel-transformations | |
# Chainable Transformations API | |
require "active_support/core_ext/string/inflections" | |
require "active_support/concern" | |
module ActiveModel | |
module Transformers | |
extend ActiveSupport::Concern | |
module ClassMethods | |
def transform(*args, &block) | |
name = args[0] | |
define_method :"#{name}=" do |attr_value| | |
@_transform_chain ||= {} | |
@_transform_attribute = name | |
@_transform_chain[@_transform_attribute] = Transformers::TransformerChain.new(attr_value) | |
if(args.length == 1) | |
instance_eval(&block) | |
else | |
args.delete_at(0) | |
instance_eval do | |
args.each do |arg| | |
with(arg) | |
end | |
end | |
end | |
write_attribute(name, @_transform_chain[@_transform_attribute].transform) | |
end | |
end | |
end | |
module InstanceMethods | |
def with(sym_or_block, options = {}) | |
if sym_or_block.is_a?(Symbol) | |
transformer = Transformers.const_get(:"#{sym_or_block.to_s.camelize}Transformer").new(options) | |
else | |
transformer = AnonTransformer.new(sym_or_block) | |
end | |
@_transform_chain[@_transform_attribute] << transformer | |
end | |
end | |
class StripTransformer | |
def initialize(options) | |
@options = { | |
:r => true, | |
:l => true | |
}.merge(options) | |
end | |
def transform(value) | |
case @options | |
when {:r => true, :l => true} then value.strip | |
when {:r => false, :l => true} then value.lstrip | |
when {:r => true, :l => false} then value.rstrip | |
end | |
end | |
end | |
class DigitTransformer | |
def initialize(options) | |
end | |
def transform(value) | |
value.gsub(/\D/, '') | |
end | |
end | |
class AnonTransformer | |
def initialize(block) | |
@block = block | |
end | |
def transform(value) | |
@block.call(value) | |
end | |
end | |
class TransformerChain | |
def initialize(value) | |
@ops = [] | |
@value = value | |
end | |
def <<(transformer) | |
@ops << transformer | |
end | |
def transform | |
@ops.inject(@value) {|acc, t| t.transform(acc)} | |
end | |
end | |
end | |
end | |
class Asset < ActiveRecord::Base | |
include ActiveModel::Transformers | |
# Usage examples for chainable transformer API. UseCases: | |
# - builtin transformer without customized options | |
# - builtin transformer with customized options | |
# - custom transformer (as a lambda) | |
# API for builtin transformers relying on default-options | |
transform :age, :digit, :strip | |
# API for builtin transformer with customized options and a custom transformer | |
transform :name do | |
with :strip, :l => false | |
with lambda {|value| "custom transformer: ...#{value}..."} | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment