active_attr 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

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