Skip to content
This repository
  • 4 commits
  • 6 files changed
  • 0 comments
  • 1 contributor
May 19, 2012
John Nunemaker Update changelog cce24e4
John Nunemaker Raise exception on write attribute if attribute not found. 8405dda
John Nunemaker Move @attributes hash defaulting to dirty module
This is where the error was happening technically.
3f3afdb
John Nunemaker Change #attributes= precedence.
Pick accessor over write_attribute. Did not have any specs for this either way so I won't consider it a breaking change.
65a8f81
2  Changelog.md
Source Rendered
@@ -2,6 +2,8 @@ I will do my best to keep this up to date with significant changes here, startin
2 2
3 3 * 0.10.1
4 4 * [Allow changing list attribute type](https://github.com/jnunemaker/toystore/commit/a5b1a944622509c32688d2e56088a7d7aa6fc0b3)
  5 + * [No longer include id in `persisted_attributes`](https://github.com/jnunemaker/toystore/commit/9f713311ebf174e314db700392e27af86ca00662)
  6 + * [Allow overriding `persist` safely](https://github.com/jnunemaker/toystore/commit/304e50c7e4ac11a365ae00f5d4caed722de31909)
5 7
6 8 * 0.10.0
7 9 * [Reference proxy api changes](https://github.com/jnunemaker/toystore/pull/5) thanks to jakehow
17 lib/toy/attributes.rb
@@ -52,10 +52,10 @@ def persisted_attributes
52 52 def attributes=(attrs, *)
53 53 return if attrs.nil?
54 54 attrs.each do |key, value|
55   - if attribute_method?(key)
56   - write_attribute(key, value)
57   - elsif respond_to?("#{key}=")
  55 + if respond_to?("#{key}=")
58 56 send("#{key}=", value)
  57 + elsif attribute_method?(key)
  58 + write_attribute(key, value)
59 59 end
60 60 end
61 61 end
@@ -71,16 +71,15 @@ def []=(key, value)
71 71 private
72 72
73 73 def read_attribute(key)
74   - @attributes ||= {}
75 74 @attributes[key.to_s]
76 75 end
77 76
78 77 def write_attribute(key, value)
79   - @attributes[key.to_s] = attribute_definition(key).try(:from_store, value)
80   - end
81   -
82   - def attribute_definition(key)
83   - self.class.attributes[key.to_s]
  78 + key = key.to_s
  79 + attribute = self.class.attributes.fetch(key) {
  80 + raise AttributeNotDefined, "#{self.class} does not have attribute #{key}"
  81 + }
  82 + @attributes[key.to_s] = attribute.from_store(value)
84 83 end
85 84
86 85 def attribute_method?(key)
3  lib/toy/dirty.rb
@@ -19,10 +19,11 @@ def initialize_copy(*)
19 19 end
20 20
21 21 def write_attribute(name, value)
  22 + @attributes ||= {}
22 23 name = name.to_s
23 24 current = read_attribute(name)
24 25 attribute_will_change!(name) if current != value
25 26 super
26 27 end
27 28 end
28   -end
  29 +end
4 lib/toy/exceptions.rb
... ... @@ -1,6 +1,8 @@
1 1 module Toy
2 2 class Error < StandardError; end
3 3
  4 + class AttributeNotDefined < Error; end
  5 +
4 6 class RecordInvalid < Error
5 7 attr_reader :record
6 8 def initialize(record)
@@ -26,4 +28,4 @@ def initialize(*)
26 28 super("Key may not be nil")
27 29 end
28 30 end
29   -end
  31 +end
81 spec/toy/attributes_spec.rb
@@ -156,6 +156,28 @@
156 156 it "ignores keys that are not attributes and do not have accessors defined" do
157 157 lambda { User.new(:taco => 'bell') }.should_not raise_error
158 158 end
  159 +
  160 + it "uses accessor over writing attribute" do
  161 + User.attribute :age, Integer
  162 +
  163 + User.class_eval do
  164 + def age=(value)
  165 + write_attribute :age, value + 10
  166 + end
  167 + end
  168 +
  169 + record = User.new
  170 + record.attributes = {:age => 15}
  171 + record.age.should be(25)
  172 + end
  173 +
  174 + it "uses write_attribute if accessor not present" do
  175 + User.attribute :age, Integer
  176 + record = User.new
  177 + record.should_receive(:respond_to?).with("age=") { false }
  178 + record.attributes = {:age => 10}
  179 + record.age.should be(10)
  180 + end
159 181 end
160 182
161 183 describe "reading an attribute" do
@@ -169,6 +191,42 @@
169 191 end
170 192 end
171 193
  194 + describe "writing an attribute" do
  195 + before do
  196 + User.attribute :name, String
  197 +
  198 + User.class_eval do
  199 + def alternate_name=(value)
  200 + write_attribute :name, value
  201 + end
  202 + end
  203 + end
  204 +
  205 + it "assigns attribute value" do
  206 + user = User.new
  207 + user.alternate_name = 'Joe'
  208 + user.name.should eq('Joe')
  209 + end
  210 +
  211 + context "when attribute not defined" do
  212 + before do
  213 + User.class_eval do
  214 + def pirate=(value)
  215 + write_attribute :pirate, value
  216 + end
  217 + end
  218 +
  219 + @user = User.new
  220 + end
  221 +
  222 + it "raises error" do
  223 + expect {
  224 + @user.pirate = 'arrrrrr'
  225 + }.to raise_error(Toy::AttributeNotDefined, "User does not have attribute pirate")
  226 + end
  227 + end
  228 + end
  229 +
172 230 describe "declaring an attribute" do
173 231 before do
174 232 User.attribute :name, String
@@ -271,25 +329,4 @@
271 329 User.new.skills.should == []
272 330 end
273 331 end
274   -
275   - # https://github.com/newtoy/toystore/issues/13
276   - describe "Overriding initialize and setting an attribute before calling super" do
277   - before do
278   - User.attribute(:name, String)
279   - User.class_eval do
280   - def initialize(*)
281   - self.name = 'John'
282   - super
283   - end
284   - end
285   - end
286   -
287   - it "does not throw error" do
288   - lambda { User.new }.should_not raise_error
289   - end
290   -
291   - it "sets value" do
292   - User.new.name.should == 'John'
293   - end
294   - end
295   -end
  332 +end
23 spec/toy/dirty_spec.rb
@@ -64,4 +64,25 @@
64 64 User.new.clone.should_not be_changed
65 65 end
66 66 end
67   -end
  67 +
  68 + # https://github.com/newtoy/toystore/issues/13
  69 + describe "Overriding initialize and setting an attribute before calling super" do
  70 + before do
  71 + User.attribute(:name, String)
  72 + User.class_eval do
  73 + def initialize(*)
  74 + self.name = 'John'
  75 + super
  76 + end
  77 + end
  78 + end
  79 +
  80 + it "does not throw error" do
  81 + lambda { User.new }.should_not raise_error
  82 + end
  83 +
  84 + it "sets value" do
  85 + User.new.name.should == 'John'
  86 + end
  87 + end
  88 +end

No commit comments for this range

Something went wrong with that request. Please try again.