active_attr 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of active_attr might be problematic. Click here for more details.

data/.document ADDED
@@ -0,0 +1 @@
1
+ - CHANGELOG* *LICENSE*
data/.gitignore CHANGED
@@ -1,5 +1,7 @@
1
1
  *.gem
2
2
  .bundle
3
+ .yardoc
3
4
  coverage
5
+ doc
4
6
  Gemfile.lock
5
7
  pkg/*
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
+ # ActiveAttr 0.2.0 (October 3, 2011) #
2
+
3
+ * ActiveAttr now autoloads nested classes and modules
4
+ * Added AttributeDefinition
5
+ * Added Attributes
6
+ * Added BasicModel
7
+ * Added Error
8
+ * Added Matchers::HaveAttributeMatcher
9
+ * Added StrictMassAssignment
10
+ * Added UnknownAttributesError
11
+ * Documented everything
12
+
1
13
  # ActiveAttr 0.1.0 (September 30, 2011) #
2
14
 
3
- * Added MassAssignment#initialize
4
- * Added MassAssignment#attributes=
5
15
  * Added MassAssignment#assign_attributes
16
+ * Added MassAssignment#attributes=
17
+ * Added MassAssignment#initialize
data/Gemfile CHANGED
@@ -8,7 +8,10 @@ group :development do
8
8
  gem "guard-bundler"
9
9
  gem "guard-rspec"
10
10
  gem "rb-fsevent"
11
- gem 'ruby-debug', :platforms => :mri_18
11
+ gem "rdiscount"
12
+ gem "rdoc"
13
+ gem "ruby-debug", :platforms => :mri_18
12
14
  gem "ruby-debug19", :platforms => :mri_19 if RUBY_VERSION < "1.9.3"
13
15
  gem "spec_coverage", :platforms => :mri_19
16
+ gem "yard"
14
17
  end
data/Guardfile CHANGED
@@ -1,10 +1,11 @@
1
- guard 'bundler' do
2
- watch('Gemfile')
1
+ guard "bundler" do
2
+ watch("Gemfile")
3
3
  watch(/^.+\.gemspec/)
4
4
  end
5
5
 
6
- guard 'rspec', :version => 2, :cli=> '--format nested --debugger' do
6
+ guard "rspec", :version => 2, :cli=> "--format nested --debugger" do
7
7
  watch(%r{^spec/.+_spec\.rb$})
8
8
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
9
- watch('spec/spec_helper.rb') { "spec" }
9
+ watch("spec/spec_helper.rb") { "spec" }
10
+ watch(%r{^spec/support/(.+)\.rb$}) { |m| "spec" }
10
11
  end
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (C) 2011 by Chris Griego
1
+ Copyright (C) 2011 by Chris Griego, Ben Poweski
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -2,7 +2,58 @@
2
2
 
3
3
  [![Build History][2]][1]
4
4
 
5
- ActiveAttr makes it easy to create plain old ruby models without reinventing the wheel.
5
+ ActiveAttr makes it easy to create plain old ruby models without reinventing
6
+ the wheel.
7
+
8
+ [API Documentation](http://rubydoc.info/gems/active_attr)
6
9
 
7
10
  [1]: http://travis-ci.org/cgriego/active_attr
8
11
  [2]: https://secure.travis-ci.org/cgriego/active_attr.png?branch=master
12
+
13
+ ## Attributes ##
14
+
15
+ Including the Attributes module into your class gives you a DSL for defining
16
+ the attributes of your model.
17
+
18
+ class Person
19
+ include ActiveAttr::Attributes
20
+
21
+ attribute :first_name
22
+ attribute :last_name
23
+ end
24
+
25
+ p = Person.new
26
+ p.first_name = "Chris"
27
+ p.last_name = "Griego"
28
+ p.attributes #=> {"first_name"=>"Chris", "last_name"=>"Griego"}
29
+
30
+ ## BasicModel ##
31
+
32
+ Including the BasicModel module into your class gives you the bare minimum
33
+ required for your model to meet the ActiveModel API requirements.
34
+
35
+ class Person
36
+ include ActiveAttr::BasicModel
37
+ end
38
+
39
+ Person.model_name.plural #=> "people"
40
+ p = Person.new
41
+ p.valid? #=> true
42
+ p.errors.full_messages #=> []
43
+
44
+ ## MassAssignment ##
45
+
46
+ Including the MassAssignment module into your class gives you methods for bulk
47
+ initializing and updating the attributes of your model. Any unknown attributes
48
+ are silently ignored unless you substitute the StrictMassAssignment module
49
+ which will raise an exception if an attempt is made to assign an unknown
50
+ attribute.
51
+
52
+ class Person
53
+ include ActiveAttr::MassAssignment
54
+ end
55
+
56
+ p = Person.new(:first_name => "Chris")
57
+ p.attributes = { :last_name => "Griego" }
58
+ p.first_name #=> "Chris"
59
+ p.last_name #=> "Griego"
data/active_attr.gemspec CHANGED
@@ -5,8 +5,8 @@ require "active_attr/version"
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "active_attr"
7
7
  s.version = ActiveAttr::VERSION
8
- s.authors = ["Chris Griego"]
9
- s.email = ["cgriego@gmail.com"]
8
+ s.authors = ["Chris Griego", "Ben Poweski"]
9
+ s.email = ["cgriego@gmail.com", "bpoweski@gmail.com"]
10
10
  s.homepage = "https://github.com/cgriego/active_attr"
11
11
  s.summary = %q{What ActiveModel left out}
12
12
  s.description = %q{Create plain old ruby models without reinventing the wheel.}
data/lib/active_attr.rb CHANGED
@@ -1,4 +1,19 @@
1
- require "active_attr/version"
1
+ require "active_support/dependencies/autoload"
2
2
 
3
+ # ActiveAttr is a set of modules to enhance Plain Old Ruby Objects (POROs)
4
+ #
5
+ # These modules give your objects the type of features that are normally found
6
+ # in popular Object Relation Mappers (ORMs) like ActiveRecord, DataMapper, and
7
+ # Mongoid. The goal is to lower the bar for creating easy-to-use Ruby models.
3
8
  module ActiveAttr
9
+ extend ActiveSupport::Autoload
10
+
11
+ autoload :AttributeDefinition
12
+ autoload :Attributes
13
+ autoload :BasicModel
14
+ autoload :Error
15
+ autoload :MassAssignment
16
+ autoload :StrictMassAssignment
17
+ autoload :UnknownAttributesError
18
+ autoload :VERSION
4
19
  end
@@ -0,0 +1,52 @@
1
+ module ActiveAttr
2
+ # Represents an attribute for reflection
3
+ #
4
+ # @example Usage
5
+ # AttributeDefinition.new(:amount)
6
+ #
7
+ # @since 0.2.0
8
+ class AttributeDefinition
9
+ # The attribute name
10
+ # @since 0.2.0
11
+ attr_reader :name
12
+
13
+ # Performs equality checking of the attribute definition
14
+ #
15
+ # @example Compare for equality.
16
+ # attribute_definition == other
17
+ #
18
+ # @param [AttributeDefinition, Object] other The other attribute definition to compare with.
19
+ #
20
+ # @return [true, false] True if attribute name is equal and other is instance of the same Class, false if not.
21
+ #
22
+ # @since 0.2.0
23
+ def ==(attribute)
24
+ return false unless attribute.instance_of? self.class
25
+ name == attribute.name
26
+ end
27
+
28
+ # Creates a new AttributeDefinition
29
+ #
30
+ # @example Create an attribute defintion
31
+ # AttributeDefinition.new(:amount)
32
+ #
33
+ # @param [Symbol, String, #to_sym] attribute name
34
+ #
35
+ # @return [AttributeDefinition]
36
+ #
37
+ # @since 0.2.0
38
+ def initialize(name, options={})
39
+ raise TypeError, "can't convert #{name.class} into Symbol" unless name.respond_to? :to_sym
40
+ @name = name.to_sym
41
+ end
42
+
43
+ # Returns the attribute name
44
+ #
45
+ # @return [String] the attribute name
46
+ #
47
+ # @since 0.2.0
48
+ def to_s
49
+ name.to_s
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,138 @@
1
+ require "active_attr/attribute_definition"
2
+ require "active_support/concern"
3
+
4
+ module ActiveAttr
5
+ # Attributes provides a set of class methods for defining an attributes
6
+ # schema and instance methods for reading and writing attributes.
7
+ #
8
+ # @example Usage
9
+ # class Person
10
+ # include ActiveAttr::Attributes
11
+ # attribute :name
12
+ # end
13
+ #
14
+ # person = Person.new
15
+ # person.name = "Ben Poweski"
16
+ #
17
+ # @since 0.2.0
18
+ module Attributes
19
+ extend ActiveSupport::Concern
20
+
21
+ # Performs equality checking on the result of attributes and its type.
22
+ #
23
+ # @example Compare for equality.
24
+ # model == other
25
+ #
26
+ # @param [Attributes, Object] other The other model to compare with.
27
+ #
28
+ # @return [true, false] True if attributes are equal and other is instance of the same Class, false if not.
29
+ #
30
+ # @since 0.2.0
31
+ def ==(other)
32
+ return false unless other.instance_of? self.class
33
+ attributes == other.attributes
34
+ end
35
+
36
+ # Returns the raw attributes Hash
37
+ #
38
+ # @example Get attributes
39
+ # person.attributes # => {"name"=>"Ben Poweski"}
40
+ #
41
+ # @return [Hash] The Hash of attributes
42
+ #
43
+ # @since 0.2.0
44
+ def attributes
45
+ @attributes ||= {}
46
+ end
47
+
48
+ # Returns the class name plus its attributes
49
+ #
50
+ # @example Inspect the model.
51
+ # person.inspect
52
+ #
53
+ # @return [String] A nice pretty string to look at.
54
+ #
55
+ # @since 0.2.0
56
+ def inspect
57
+ attribute_descriptions = self.class.attributes.map do |attribute|
58
+ "#{attribute.name.to_s}: #{read_attribute(attribute.name).inspect}"
59
+ end
60
+
61
+ "#<#{self.class.name} #{attribute_descriptions.join(", ")}>"
62
+ end
63
+
64
+ # Read a value from the model's attributes. If the value does not exist
65
+ # it will return nil.
66
+ #
67
+ # @example Read an attribute.
68
+ # person.read_attribute(:name)
69
+ #
70
+ # @param [String, Symbol] name The name of the attribute to get.
71
+ #
72
+ # @return [Object] The value of the attribute.
73
+ #
74
+ # @since 0.2.0
75
+ def read_attribute(name)
76
+ attributes[name.to_s]
77
+ end
78
+
79
+ # Write a single attribute to the model's attribute hash.
80
+ #
81
+ # @example Write the attribute.
82
+ # person.write_attribute(:name, "Benjamin")
83
+ #
84
+ # @param [String, Symbol] name The name of the attribute to update.
85
+ # @param [Object] value The value to set for the attribute.
86
+ #
87
+ # @since 0.2.0
88
+ def write_attribute(name, value)
89
+ attributes[name.to_s] = value
90
+ end
91
+
92
+ module ClassMethods
93
+ # Defines all the attributes that are to be returned from the attributes instance method.
94
+ # For each attribute that is defined, a getter and setter will be
95
+ # added as an instance method to the model. An AttributeDefinition instance will be
96
+ # added to result of the attributes class method.
97
+ #
98
+ # @example Define an attribute.
99
+ # attribute :name
100
+ #
101
+ # @param [Symbol] name The name of the attribute.
102
+ #
103
+ # @since 0.2.0
104
+ def attribute(name, options={})
105
+ attribute_definition = AttributeDefinition.new(name, options)
106
+ attributes << attribute_definition
107
+ method_name = attribute_definition.name
108
+
109
+ define_method("#{method_name}=") { |value| write_attribute(name, value) }
110
+ define_method(method_name) { read_attribute(name) }
111
+ end
112
+
113
+ # Returns an Array of AttributeDefinition instances
114
+ #
115
+ # @example Get attribute definitions
116
+ # Person.attributes
117
+ #
118
+ # @return [Array<AttributeDefinition>] The Array of AttributeDefinition instances
119
+ #
120
+ # @since 0.2.0
121
+ def attributes
122
+ @attributes ||= []
123
+ end
124
+
125
+ # Returns the class name plus its attribute definitions
126
+ #
127
+ # @example Inspect the model's definition.
128
+ # Person.inspect
129
+ #
130
+ # @return [String] A nice pretty string to look at.
131
+ #
132
+ # @since 0.2.0
133
+ def inspect
134
+ "#{self.name}(#{attributes.map { |a| a.to_s }.join(", ")})"
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,25 @@
1
+ require "active_model"
2
+ require "active_support/concern"
3
+
4
+ module ActiveAttr
5
+ # Provides the minimum functionality to pass the ActiveModel lint tests
6
+ #
7
+ # @example Usage
8
+ # class Person
9
+ # include ActiveAttr::BasicModel
10
+ # end
11
+ #
12
+ # @since 0.2.0
13
+ module BasicModel
14
+ extend ActiveSupport::Concern
15
+ extend ActiveModel::Naming
16
+ include ActiveModel::Conversion
17
+ include ActiveModel::Validations
18
+
19
+ # @return [false]
20
+ # @since 0.2.0
21
+ def persisted?
22
+ false
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,16 @@
1
+ module ActiveAttr
2
+ # All exceptions defined by and raised directly by ActiveAttr include this
3
+ # module, if you want to rescue any of the exceptions raised by the
4
+ # ActiveAttr library, you can rescue {ActiveAttr::Error}
5
+ #
6
+ # @example Rescuing an ActiveAttr error
7
+ # begin
8
+ # Person.new(attributes)
9
+ # rescue ActiveAttr::Error
10
+ # Person.new
11
+ # end
12
+ #
13
+ # @since 0.2.0
14
+ module Error
15
+ end
16
+ end
@@ -1,18 +1,59 @@
1
1
  module ActiveAttr
2
+ # MassAssignment allows you to bulk set and update attributes
3
+ #
4
+ # Including MassAssignment into your model gives it a set of mass assignment
5
+ # methods, similar to those found in ActiveRecord.
6
+ #
7
+ # @example Usage
8
+ # class Person
9
+ # include ActiveAttr::MassAssignment
10
+ # end
11
+ #
12
+ # @since 0.1.0
2
13
  module MassAssignment
3
- def initialize(attributes=nil, options={})
4
- assign_attributes attributes, options
14
+ # Mass update a model's attributes
15
+ #
16
+ # @example Assigning a hash
17
+ # person.assign_attributes(:first_name => "Chris", :last_name => "Griego")
18
+ # person.first_name #=> "Chris"
19
+ # person.last_name #=> "Griego"
20
+ #
21
+ # @param [Hash, #each] attributes Attributes used to populate the model
22
+ #
23
+ # @since 0.1.0
24
+ def assign_attributes(new_attributes, options={})
25
+ new_attributes.each do |name, value|
26
+ writer = "#{name}="
27
+ send writer, value if respond_to? writer
28
+ end if new_attributes
5
29
  end
6
30
 
31
+ # Mass update a model's attributes
32
+ #
33
+ # @example Assigning a hash
34
+ # person.attributes = { :first_name => "Chris", :last_name => "Griego" }
35
+ # person.first_name #=> "Chris"
36
+ # person.last_name #=> "Griego"
37
+ #
38
+ # @param (see #assign_attributes)
39
+ #
40
+ # @since 0.1.0
7
41
  def attributes=(new_attributes)
8
42
  assign_attributes new_attributes
9
43
  end
10
44
 
11
- def assign_attributes(new_attributes, options={})
12
- new_attributes.each do |name, value|
13
- writer = "#{name}="
14
- send writer, value if respond_to? writer
15
- end if new_attributes
45
+ # Initialize a model with a set of attributes
46
+ #
47
+ # @example Initializing with a hash
48
+ # person = Person.new(:first_name => "Chris", :last_name => "Griego")
49
+ # person.first_name #=> "Chris"
50
+ # person.last_name #=> "Griego"
51
+ #
52
+ # @param (see #assign_attributes)
53
+ #
54
+ # @since 0.1.0
55
+ def initialize(attributes=nil, options={})
56
+ assign_attributes attributes, options
16
57
  end
17
58
  end
18
59
  end