entasis 0.3.2 → 0.4.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.
data/HISTORY CHANGED
@@ -1,3 +1,8 @@
1
+ == 0.4.0
2
+ Introduced options for Entasis::Model.attributes and Entasis::TransposeKeys
3
+ It's now possible to silently ignore unknown attributes by passing
4
+ options ignore_undefined: true as last argument when defining attributes.
5
+
1
6
  == 0.3.2
2
7
  Do not require attribute hash at initialization (Jack Christensen and Joshua Davey)
3
8
 
data/README.md CHANGED
@@ -18,18 +18,22 @@ class Person
18
18
  end
19
19
  end
20
20
 
21
- hilda = Person.new(name: 'Hilda', age: '23', city: 'Berlin')
21
+ hilda = Person.new(name: 'Hilda', age: '23', city: 'Stockholm')
22
22
  hilda.attribute_names # => ["name", "age", "city"]
23
- hilda.attributes # => {"name"=>"Hilda", "age"=>23, "city"=>"Berlin"}
23
+ hilda.attributes # => {"name"=>"Hilda", "age"=>23, "city"=>"Stockholm"}
24
24
 
25
25
  anon = Person.new
26
26
  anon.valid? # => false
27
27
  anon.errors # => {:name=>["can't be blank"]}>
28
28
  ```
29
29
 
30
+ Default behavior is to raise if any key in the hash given to `.new` or `#attributes=` is not defined,
31
+ this can be circumvented by passing `ignore_undefined: true` as options when defining your attributes.
30
32
 
31
33
  Contributors
32
34
  ------------
33
35
 
36
+ Ingemar Edsborn (ingemar)
34
37
  Joshua Davey (jgdavey)
35
38
  Johnny Winn (nurugger07)
39
+ Jack Christensen (jackc)
data/lib/entasis/model.rb CHANGED
@@ -4,7 +4,8 @@ module Entasis
4
4
 
5
5
  included do
6
6
  include ActiveModel::Validations
7
- class_attribute :attribute_names
7
+ class_attribute :attribute_names, :attributes_config, instance_writer: false
8
+
8
9
  self.attribute_names ||= []
9
10
  self.class_eval 'class UnknownAttributeError < StandardError; end'
10
11
  end
@@ -12,10 +13,14 @@ module Entasis
12
13
  module ClassMethods
13
14
  ##
14
15
  #
15
- # Takes a list of attribute names
16
+ # Takes a list of attribute names. Last argument can be an options hash.
17
+ #
18
+ # ignore_undefined: true - Silently ignore any undefined attributes
16
19
  #
17
20
  def attributes(*attrs)
18
- self.attribute_names += attrs.map(&:to_s)
21
+ self.attributes_config = attrs.last.is_a?(Hash) ? attrs.pop : {}
22
+
23
+ self.attribute_names += attrs.map(&:to_s).sort
19
24
 
20
25
  attr_accessor *attrs
21
26
  end
@@ -29,33 +34,27 @@ module Entasis
29
34
  self.attributes = hash
30
35
  end
31
36
 
32
- ##
33
- #
34
- # Returns a list of attribute names
35
- #
36
- def attribute_names
37
- self.class.class_variable_get :@@attribute_names
38
- end
39
-
40
37
  ##
41
38
  #
42
39
  # Takes a hash of attribute names and values and set each attribute.
43
40
  #
44
- # If passwed an unkown attribute it ill raise +class::UnknownAttributeError+
41
+ # If passwed an unkown attribute it will raise +class::UnknownAttributeError+
45
42
  #
46
43
  def attributes=(hash)
47
44
  hash.each do |name, value|
48
45
  if attribute_names.include?(name.to_s) || self.respond_to?("#{name}=")
49
46
  self.send("#{name}=", value)
50
47
  else
51
- raise self.class::UnknownAttributeError, "unkown attribute: #{name}"
48
+ if attributes_config[:ignore_undefined] != true
49
+ raise self.class::UnknownAttributeError, "unknown attribute: #{name}"
50
+ end
52
51
  end
53
52
  end
54
53
  end
55
54
 
56
55
  ##
57
56
  #
58
- # Returns all attributes serialied as hash
57
+ # Returns all attributes serialized as hash
59
58
  #
60
59
  def attributes
61
60
  attribute_names.inject({}) { |h, name| h[name] = send(name); h }
@@ -0,0 +1,28 @@
1
+ module Entasis
2
+ module TransposeKeys
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ alias_method_chain :attributes=, :transpose
7
+ end
8
+
9
+ ##
10
+ #
11
+ # Takes a hash of attribute names and values and set each attribute.
12
+ #
13
+ # If passwed an unkown attribute it ill raise +class::UnknownAttributeError+
14
+ #
15
+ def attributes_with_transpose=(hash)
16
+ hash.each do |name, value|
17
+ transposed_name = name.to_s.dup.underscore.downcase
18
+ if attribute_names.include?(transposed_name) || self.respond_to?("#{transposed_name}=")
19
+ self.send("#{transposed_name}=", value)
20
+ else
21
+ if attributes_config[:ignore_undefined] != true
22
+ raise self.class::UnknownAttributeError, "unknown attribute: #{transposed_name} (transposed from #{name})"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,3 +1,3 @@
1
1
  module Entasis
2
- VERSION = "0.3.2"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/entasis.rb CHANGED
@@ -2,6 +2,9 @@ require 'active_support'
2
2
  require 'active_model'
3
3
 
4
4
  module Entasis
5
- autoload :Model, 'entasis/model'
6
- autoload :Base, 'entasis/base'
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :Model
8
+ autoload :TransposeKeys
9
+ autoload :Base
7
10
  end
data/spec/entasis_spec.rb CHANGED
@@ -1,57 +1,81 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "Entasis::Model" do
4
- let(:hilda) { hilda = Person.new(:name => 'Hilda', :age => '23', :city => 'Berlin') }
5
-
6
- describe "#new" do
7
- it "sets the attributes from the given hash" do
8
- hilda.name.should == 'Hilda'
9
- hilda.age.should == 23
10
- hilda.city.should == 'Berlin'
11
- end
3
+ describe Entasis::Model do
4
+ let(:attributes) do
5
+ { name: 'Hilda', age: '23', city: 'Stockholm' }
6
+ end
7
+ let(:person) { Person.new(attributes) }
12
8
 
13
- it "raises an error if attribute is unknown" do
14
- expect {
15
- Person.new(undefined: 'value')
16
- }.to raise_error Person::UnknownAttributeError, 'unkown attribute: undefined'
9
+ describe '#new' do
10
+ it 'calls #attributes= with the given hash' do
11
+ Person.any_instance.should_receive(:attributes=).once.with(attributes)
12
+ person
17
13
  end
18
14
 
19
- it "does not require attribute hash" do
15
+ it 'does not require attribute hash' do
20
16
  expect { Person.new }.to_not raise_error
21
17
  end
22
18
  end
23
19
 
24
- describe "#attribute_names" do
20
+ describe '#attribute_names' do
25
21
  it 'returns a list of attribute names' do
26
- hilda.attribute_names.should == %w[name age city]
22
+ expect(person.attribute_names).to eq(%w[name age city].sort)
27
23
  end
28
24
  end
29
25
 
30
- describe "#attributes" do
31
- it 'returns a hash of attributes names and values' do
32
- hilda.attributes.should == {"name"=>"Hilda", "age"=>23, "city"=>"Berlin"}
26
+ describe '#attributes=' do
27
+ context 'when given a hash' do
28
+ it 'sets the attributes from the given hash' do
29
+ person.attributes = attributes
30
+
31
+ expect(person.name).to eq('Hilda')
32
+ expect(person.age).to eq(23)
33
+ expect(person.city).to eq('Stockholm')
34
+ end
35
+ end
36
+
37
+ it 'raises an error if attribute is unknown' do
38
+ expect {
39
+ Person.new(undefined: 'value')
40
+ }.to raise_error Person::UnknownAttributeError, 'unknown attribute: undefined'
41
+ end
42
+
43
+ context 'when .attributes option :allow_unknown is set to true' do
44
+ subject { RelaxedPerson.new(undefined: 'value') }
45
+
46
+ it 'ignores that attribute' do
47
+ expect(subject.attributes.keys).to_not include('undifined')
48
+ end
33
49
  end
34
50
  end
35
51
 
36
- describe "subclasses" do
37
- let(:hans) { Child.new(:name => 'Hans', :age => "8", :candy => true) }
52
+ describe '#attributes' do
53
+ it 'returns a hash of attributes names and values' do
54
+ expect(person.attributes).to eq({ 'name' => 'Hilda', 'age' => 23, 'city' => 'Stockholm' })
55
+ end
38
56
 
39
- it "inherits attributes from the parent" do
40
- hans.attributes.should == { "name" => "Hans", "age" => 8, "city" => nil, "candy" => true }
57
+ context 'subclasses' do
58
+ let(:child) { Child.new(name: 'Hans', age: '8', candy: true) }
41
59
 
60
+ it 'inherits attributes from the parent' do
61
+ expect(child.attributes).to eq({ 'name' => 'Hans', 'age' => 8, 'city' => nil, 'candy' => true })
62
+ end
42
63
  end
43
64
  end
44
65
 
45
- context "validations" do
46
- describe "#valid?" do
47
- it "validates" do
48
- hilda.should be_valid
66
+ context 'validations' do
67
+ describe '#valid?' do
68
+ context 'when valid' do
69
+ it { expect(person).to be_valid }
49
70
  end
50
71
 
51
- it "will have errors" do
52
- anon = Person.new(:name => "")
53
- anon.should_not be_valid
54
- anon.errors.to_hash.should == { :name => ["can't be blank"] }
72
+ context 'invalid' do
73
+ subject { Person.new(name: '') }
74
+
75
+ it 'will have errors' do
76
+ expect(subject).to_not be_valid
77
+ expect(subject.errors.to_hash).to eq({ name: ["can't be blank"] })
78
+ end
55
79
  end
56
80
  end
57
81
  end
data/spec/spec_helper.rb CHANGED
@@ -2,7 +2,10 @@ require "rubygems"
2
2
  require "bundler/setup"
3
3
 
4
4
  require 'entasis'
5
- require File.expand_path(File.dirname(__FILE__) + '/support/person')
5
+
6
+ Dir.glob(File.dirname(__FILE__) + '/support/**/*.rb').each do |filename|
7
+ require filename
8
+ end
6
9
 
7
10
  RSpec.configure do |config|
8
11
  end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Entasis::TransposeKeys do
4
+ let(:attributes) do
5
+ { 'Speed' => 200, 'leftFrontDoor' => 'blue', 'RightFront_Door' => 'green' }
6
+ end
7
+ let(:car) { Car.new(attributes) }
8
+
9
+ describe '#attributes=' do
10
+ context 'when given a hash' do
11
+ it 'sets the attributes from the given hash' do
12
+ car.attributes = attributes
13
+
14
+ expect(car.speed).to eq(200)
15
+ expect(car.left_front_door).to eq('blue')
16
+ expect(car.right_front_door).to eq('green')
17
+ end
18
+ end
19
+
20
+ it 'raises an error if attribute is unknown' do
21
+ expect {
22
+ Car.new(unDefined: 'value')
23
+ }.to raise_error Car::UnknownAttributeError, 'unknown attribute: un_defined (transposed from unDefined)'
24
+ end
25
+ end
26
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: entasis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-11 00:00:00.000000000 Z
12
+ date: 2013-01-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activemodel
@@ -53,6 +53,7 @@ extra_rdoc_files: []
53
53
  files:
54
54
  - lib/entasis/base.rb
55
55
  - lib/entasis/model.rb
56
+ - lib/entasis/transpose_keys.rb
56
57
  - lib/entasis/version.rb
57
58
  - lib/entasis.rb
58
59
  - Gemfile
@@ -62,6 +63,7 @@ files:
62
63
  - LICENSE
63
64
  - spec/entasis_spec.rb
64
65
  - spec/spec_helper.rb
66
+ - spec/transpose_keys_spec.rb
65
67
  homepage: http://github.com/ingemar/entasis
66
68
  licenses: []
67
69
  post_install_message:
@@ -89,3 +91,4 @@ summary: A few neat methods for a basic class
89
91
  test_files:
90
92
  - spec/entasis_spec.rb
91
93
  - spec/spec_helper.rb
94
+ - spec/transpose_keys_spec.rb