freeze-ray 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ === 0.4.0 :: 2009-05-29
2
+
3
+ * Initial release.
@@ -0,0 +1,65 @@
1
+ Freeze Ray
2
+ ==========
3
+
4
+ > "With my freeze ray I will stop the pain." --Dr. Horrible
5
+
6
+ The problem
7
+ -----------
8
+
9
+ ActiveRecord's dirty tracking feature is broken. Awesome, but broken. Let me demonstrate.
10
+
11
+ >> p = Post.last
12
+ => #<Post id: 261, ... >
13
+ >> p.title
14
+ => "A quick update"
15
+ >> p.changes
16
+ => {}
17
+ >> p.title << " about my pet frogs"
18
+ => "A quick update about my pet frogs"
19
+ >> p.changes
20
+ => {}
21
+
22
+ Hang on, now! We changed the title! Why didn't we see this?
23
+
24
+ => {"title"=>["A quick update", "A quick update about my pet frogs"]}
25
+
26
+ Because ActiveRecord doesn't have any way of knowing that we changed the attribute. That's because we **mutated it in place**. Rather than replace the string with a new one, *we changed the one it already had*. That doesn't involve calling `#title=` on the Post, so the Post doesn't realize that the actual value changed.
27
+
28
+ ActiveRecord provides one solution: call `#title_will_change!` first. That tells the Post to remember the current value of the title to compare to the old one. Observe:
29
+
30
+ >> p.title << " whom I love dearly"
31
+ => "A quick update about my pet frogs whom I love dearly"
32
+ >> p.changes
33
+ => {"title"=>["A quick update about my pet frogs", "A quick update about my pet frogs whom I love dearly"]}
34
+
35
+ Well, sure, that works. But you have to be careful. What if you forget to that at some point?
36
+
37
+
38
+ Another Solution
39
+ ----------------
40
+
41
+ Freeze Ray offers another solution. Just mark the attributes you want to track as `attr_frozen`:
42
+
43
+ class Post < ActiveRecord::Base
44
+ attr_frozen :title
45
+ end
46
+
47
+ Now try to mess up dirty tracking:
48
+
49
+ >> p = Post.last
50
+ => #<Post id: 261, ... >
51
+ >> p.title
52
+ => "A quick update"
53
+ >> p.title << " about my pet frogs"
54
+ TypeError: can't modify frozen string
55
+ from (irb):36:in `<<'
56
+ from (irb):36
57
+ >> p.title
58
+ => "A quick update"
59
+ >> p.title.frozen?
60
+ => true
61
+
62
+ You can't do it!
63
+
64
+ Obviously, this isn't very useful in a case where you need to change attribute objects in place. On the other hand, I can't think of a reason you'd *want* to change them in place. Now, if you try, you'll know.
65
+
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 0
3
+ :patch: 1
4
+ :major: 0
@@ -0,0 +1,9 @@
1
+ module FreezeRay
2
+ def attr_frozen(*attrs)
3
+ attrs.each do |attr|
4
+ define_method(attr) do
5
+ super.freeze
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,41 @@
1
+ $LOAD_PATH << File.dirname(__FILE__) + "/../lib"
2
+
3
+ require 'rubygems'
4
+ require 'acts_as_fu'
5
+ require 'spec'
6
+
7
+ Spec::Runner.configure do |config|
8
+ config.include ActsAsFu
9
+ end
10
+
11
+ require File.dirname(__FILE__) + "/../rails/init"
12
+
13
+
14
+ describe "attr_frozen" do
15
+ before(:each) do
16
+ build_model :things do
17
+ string :string_attribute, :default => "foobar"
18
+ string :serialized_attribute
19
+ serialize :serialized_attribute
20
+
21
+ # Turn off acts_as_foo's method_missing extension for schema
22
+ # definition. For some reason, it delegates #define_method to
23
+ # the table definition.
24
+ class << self
25
+ alias_method :method_missing, :method_missing_without_columns
26
+ end
27
+
28
+ attr_frozen :string_attribute, :serialized_attribute
29
+ end
30
+ end
31
+
32
+ describe "freezes attributes which are" do
33
+ before do
34
+ @thing = Thing.new(:string_attribute => "foobar",
35
+ :serialized_attribute => [:a, :b, :c])
36
+ end
37
+
38
+ specify("strings") { @thing.string_attribute.should be_frozen }
39
+ specify("serialized") { @thing.serialized_attribute.should be_frozen }
40
+ end
41
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: freeze-ray
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Peter Jaros
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-29 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Fixes ActiveRecord's dirty tracking. Provides an attr_frozen macro which causes an attribute to be returned frozen.
17
+ email: peter.a.jaros@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - History.txt
26
+ - README.markdown
27
+ - VERSION.yml
28
+ - lib/freeze_ray.rb
29
+ - spec/freeze_ray_spec.rb
30
+ has_rdoc: true
31
+ homepage:
32
+ post_install_message:
33
+ rdoc_options:
34
+ - --inline-source
35
+ - --charset=UTF-8
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: "0"
43
+ version:
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ requirements: []
51
+
52
+ rubyforge_project: freeze-ray
53
+ rubygems_version: 1.3.1
54
+ signing_key:
55
+ specification_version: 2
56
+ summary: Fixes ActiveRecord's dirty tracking.
57
+ test_files: []
58
+