ryanb-association-freezer 0.1.1
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/CHANGELOG +13 -0
- data/LICENSE +20 -0
- data/Manifest +16 -0
- data/README +110 -0
- data/association-freezer.gemspec +50 -0
- data/lib/association_freezer/belongs_to_freezer.rb +60 -0
- data/lib/association_freezer/method_generator.rb +63 -0
- data/lib/association_freezer/model_additions.rb +14 -0
- data/lib/association_freezer.rb +4 -0
- data/spec/freezer_spec.rb +106 -0
- data/spec/lib/order.rb +18 -0
- data/spec/lib/ship_method.rb +15 -0
- data/spec/spec_helper.rb +23 -0
- data/tasks/deployment.rake +2 -0
- data/tasks/spec.rake +9 -0
- metadata +81 -0
data/CHANGELOG
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
*0.1.1* (July 14th, 2008)
|
2
|
+
|
3
|
+
* frozen record is no longer considered new
|
4
|
+
|
5
|
+
* frozen record keeps id attribute of old record
|
6
|
+
|
7
|
+
* don't raise exception when trying to freeze nil association
|
8
|
+
|
9
|
+
* raise an exception when trying to replace frozen association
|
10
|
+
|
11
|
+
*0.1.0* (July 14th, 2008)
|
12
|
+
|
13
|
+
* initial release
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 Ryan Bates
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
association-freezer.gemspec
|
2
|
+
CHANGELOG
|
3
|
+
lib/association_freezer/belongs_to_freezer.rb
|
4
|
+
lib/association_freezer/method_generator.rb
|
5
|
+
lib/association_freezer/model_additions.rb
|
6
|
+
lib/association_freezer.rb
|
7
|
+
LICENSE
|
8
|
+
Manifest
|
9
|
+
README
|
10
|
+
spec/freezer_spec.rb
|
11
|
+
spec/lib/order.rb
|
12
|
+
spec/lib/ship_method.rb
|
13
|
+
spec/spec_helper.rb
|
14
|
+
tasks/deployment.rake
|
15
|
+
tasks/spec.rake
|
16
|
+
tmp/test.sqlite3
|
data/README
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
= Association Freezer
|
2
|
+
|
3
|
+
Freeze an Active Record belongs_to association to ignore any future changes.
|
4
|
+
|
5
|
+
|
6
|
+
== Install
|
7
|
+
|
8
|
+
First specify it in your Rails config.
|
9
|
+
|
10
|
+
config.gem 'ryanb-association-freezer', :lib => 'association_freezer', :source => 'http://gems.github.com'
|
11
|
+
|
12
|
+
And then install it.
|
13
|
+
|
14
|
+
rake gems:install
|
15
|
+
|
16
|
+
Follow the instructions below to finish setup. Rails 2.1 or later
|
17
|
+
required.
|
18
|
+
|
19
|
+
|
20
|
+
== Scenario
|
21
|
+
|
22
|
+
Let's say we have an Order model with a couple belongs_to associations
|
23
|
+
for setting the billing and shipping address.
|
24
|
+
|
25
|
+
class Order < ActiveRecord::Base
|
26
|
+
belongs_to :shipping_address, :class_name => 'Address'
|
27
|
+
belongs_to :billing_address, :class_name => 'Address'
|
28
|
+
# ...
|
29
|
+
end
|
30
|
+
|
31
|
+
Consider this scenario. A user comes to the site and places an order.
|
32
|
+
Then he comes back a month later and changes his address. Now our Order
|
33
|
+
model is incorrect, it will point to this new address instead of the
|
34
|
+
old one he placed the order with.
|
35
|
+
|
36
|
+
There's a couple ways to solve this, one is to create a new Address
|
37
|
+
model whenever one edits the address. Another is to freeze the address
|
38
|
+
attributes upon placing an order so it isn't effected when the original
|
39
|
+
Address changes. This gem will help with the latter.
|
40
|
+
|
41
|
+
|
42
|
+
== Usage
|
43
|
+
|
44
|
+
First you need to generate a binary (or blob) column to hold each
|
45
|
+
frozen assoiation. The name of the column must start with "frozen_" and
|
46
|
+
end with the association name. You can do that with a migration like
|
47
|
+
this:
|
48
|
+
|
49
|
+
script/generate migration add_frozen_addresses_to_orders \
|
50
|
+
frozen_billing_address:binary frozen_shipping_address:binary
|
51
|
+
|
52
|
+
|
53
|
+
Next, enable the association freezer on your model. This must be done
|
54
|
+
AFTER the associations have been specified.
|
55
|
+
|
56
|
+
class Order < ActiveRecord::Base
|
57
|
+
belongs_to :shipping_address, :class_name => 'Address'
|
58
|
+
belongs_to :billing_address, :class_name => 'Address'
|
59
|
+
enable_association_freezer
|
60
|
+
#...
|
61
|
+
end
|
62
|
+
|
63
|
+
Now you can freeze the association at will:
|
64
|
+
|
65
|
+
# in order
|
66
|
+
def purchase
|
67
|
+
#...
|
68
|
+
freeze_billing_address
|
69
|
+
freeze_shipping_address
|
70
|
+
save!
|
71
|
+
end
|
72
|
+
|
73
|
+
When freezing an association, the attributes will be set to the frozen
|
74
|
+
column. However, the model is not saved automatically, so you must call
|
75
|
+
save at some point after freezing.
|
76
|
+
|
77
|
+
Here's where the magic starts. Now when you fetch the frozen
|
78
|
+
association (order.billing_address), the association freezer will step
|
79
|
+
in and return an Address model which is built from the attributes in
|
80
|
+
the frozen column, not the attributes in the addresses table.
|
81
|
+
Therefore, any changes to the address will not effect the order's
|
82
|
+
address. "freeze" is called on the model before returning it to prevent
|
83
|
+
accidentally altering the data.
|
84
|
+
|
85
|
+
You can also unfreeze an already frozen association if you want it to
|
86
|
+
use the database record instead.
|
87
|
+
|
88
|
+
unfreeze_billing_address
|
89
|
+
|
90
|
+
You can then freeze it again to use the updated attributes.
|
91
|
+
|
92
|
+
|
93
|
+
== Alternative Usage
|
94
|
+
|
95
|
+
Not only is this gem good at handling the situation above, but it can
|
96
|
+
also be used as a caching technique. If the belongs_to association is
|
97
|
+
frequently accessed, it can be more efficient to freeze (cache) it to
|
98
|
+
remove the need for a database call. Of course with this approach you
|
99
|
+
want it to stay in sync with the database, so you'll need to expire the
|
100
|
+
cache (refreeze the association) whenever the associated model changes.
|
101
|
+
|
102
|
+
|
103
|
+
== Development
|
104
|
+
|
105
|
+
This project can be found on github at the following URL.
|
106
|
+
|
107
|
+
http://github.com/ryanb/association-freezer/
|
108
|
+
|
109
|
+
If you would like to contribute to this project, please fork the
|
110
|
+
repository and send me a pull request.
|
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
# Gem::Specification for Association-freezer-0.1.1
|
3
|
+
# Originally generated by Echoe
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = %q{association-freezer}
|
7
|
+
s.version = "0.1.1"
|
8
|
+
|
9
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
10
|
+
s.authors = ["Ryan Bates"]
|
11
|
+
s.date = %q{2008-07-24}
|
12
|
+
s.description = %q{Freeze an Active Record belongs_to association.}
|
13
|
+
s.email = %q{ryan (at) railscasts (dot) com}
|
14
|
+
s.extra_rdoc_files = ["CHANGELOG", "lib/association_freezer/belongs_to_freezer.rb", "lib/association_freezer/method_generator.rb", "lib/association_freezer/model_additions.rb", "lib/association_freezer.rb", "LICENSE", "README", "tasks/deployment.rake", "tasks/spec.rake"]
|
15
|
+
s.files = ["association-freezer.gemspec", "CHANGELOG", "lib/association_freezer/belongs_to_freezer.rb", "lib/association_freezer/method_generator.rb", "lib/association_freezer/model_additions.rb", "lib/association_freezer.rb", "LICENSE", "Manifest", "README", "spec/freezer_spec.rb", "spec/lib/order.rb", "spec/lib/ship_method.rb", "spec/spec_helper.rb", "tasks/deployment.rake", "tasks/spec.rake", "tmp/test.sqlite3"]
|
16
|
+
s.has_rdoc = true
|
17
|
+
s.homepage = %q{http://github.com/ryanb/association-freezer}
|
18
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Association-freezer", "--main", "README"]
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
s.rubyforge_project = %q{association-freezer}
|
21
|
+
s.rubygems_version = %q{1.2.0}
|
22
|
+
s.summary = %q{Freeze an Active Record belongs_to association.}
|
23
|
+
|
24
|
+
if s.respond_to? :specification_version then
|
25
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
26
|
+
s.specification_version = 2
|
27
|
+
if current_version >= 3 then
|
28
|
+
else
|
29
|
+
end
|
30
|
+
else
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
# # Original Rakefile source (requires the Echoe gem):
|
36
|
+
#
|
37
|
+
# require 'rubygems'
|
38
|
+
# require 'rake'
|
39
|
+
# require 'echoe'
|
40
|
+
#
|
41
|
+
# Echoe.new('association-freezer', '0.1.1') do |p|
|
42
|
+
# p.summary = "Freeze an Active Record belongs_to association."
|
43
|
+
# p.description = "Freeze an Active Record belongs_to association."
|
44
|
+
# p.url = "http://github.com/ryanb/association-freezer"
|
45
|
+
# p.author = 'Ryan Bates'
|
46
|
+
# p.email = "ryan (at) railscasts (dot) com"
|
47
|
+
# p.ignore_pattern = ["script/*"]
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module AssociationFreezer
|
2
|
+
class BelongsToFreezer
|
3
|
+
def initialize(owner, reflection)
|
4
|
+
@owner = owner
|
5
|
+
@reflection = reflection
|
6
|
+
end
|
7
|
+
|
8
|
+
def freeze
|
9
|
+
self.frozen_data = Marshal.dump(nonfrozen.attributes) if nonfrozen
|
10
|
+
end
|
11
|
+
|
12
|
+
def unfreeze
|
13
|
+
@frozen = nil
|
14
|
+
self.frozen_data = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def fetch(*args)
|
18
|
+
frozen || nonfrozen(*args)
|
19
|
+
end
|
20
|
+
|
21
|
+
def frozen?
|
22
|
+
frozen_data
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def frozen
|
28
|
+
@frozen ||= load_frozen if frozen?
|
29
|
+
end
|
30
|
+
|
31
|
+
def load_frozen
|
32
|
+
attributes = Marshal.load(frozen_data)
|
33
|
+
target = target_class.new(attributes.except('id'))
|
34
|
+
target.id = attributes['id']
|
35
|
+
target.instance_variable_set('@new_record', false)
|
36
|
+
target.readonly!
|
37
|
+
target.freeze
|
38
|
+
end
|
39
|
+
|
40
|
+
def nonfrozen(*args)
|
41
|
+
@owner.send("#{name}_without_frozen_check", *args)
|
42
|
+
end
|
43
|
+
|
44
|
+
def frozen_data=(data)
|
45
|
+
@owner.write_attribute("frozen_#{name}", data)
|
46
|
+
end
|
47
|
+
|
48
|
+
def frozen_data
|
49
|
+
@owner.read_attribute("frozen_#{name}")
|
50
|
+
end
|
51
|
+
|
52
|
+
def target_class
|
53
|
+
@reflection.klass
|
54
|
+
end
|
55
|
+
|
56
|
+
def name
|
57
|
+
@reflection.name
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module AssociationFreezer
|
2
|
+
class MethodGenerator
|
3
|
+
|
4
|
+
def initialize(reflection)
|
5
|
+
@reflection = reflection
|
6
|
+
end
|
7
|
+
|
8
|
+
def generate
|
9
|
+
# it is very important that we first make sure this hasn't already been done
|
10
|
+
# because otherwise it will result in an endless loop the way alias method works.
|
11
|
+
return if previously_generated? || !frozen_column_exists?
|
12
|
+
|
13
|
+
reflection = @reflection
|
14
|
+
freezer = "#{reflection.name}_freezer"
|
15
|
+
|
16
|
+
generate_method freezer do
|
17
|
+
read_attribute("@#{freezer}") || write_attribute("@#{freezer}", BelongsToFreezer.new(self, reflection))
|
18
|
+
end
|
19
|
+
|
20
|
+
generate_method "freeze_#{reflection.name}" do
|
21
|
+
send(freezer).freeze
|
22
|
+
end
|
23
|
+
|
24
|
+
generate_method "unfreeze_#{reflection.name}" do
|
25
|
+
send(freezer).unfreeze
|
26
|
+
end
|
27
|
+
|
28
|
+
generate_method "#{reflection.name}_with_frozen_check" do |*args|
|
29
|
+
send(freezer).fetch(*args)
|
30
|
+
end
|
31
|
+
model_class.alias_method_chain reflection.name, :frozen_check
|
32
|
+
|
33
|
+
generate_method "#{reflection.name}_with_frozen_check=" do |*args|
|
34
|
+
if send(freezer).frozen?
|
35
|
+
# TODO make this a custom exception
|
36
|
+
raise "Unable to set #{reflection.name} because association is frozen."
|
37
|
+
else
|
38
|
+
send("#{reflection.name}_without_frozen_check=", *args)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
model_class.alias_method_chain "#{reflection.name}=", :frozen_check
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def previously_generated?
|
47
|
+
model_class.instance_methods.include? "freeze_#{@reflection.name}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def frozen_column_exists?
|
51
|
+
model_class.column_names.include? "frozen_#{@reflection.name}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def model_class
|
55
|
+
@reflection.active_record
|
56
|
+
end
|
57
|
+
|
58
|
+
def generate_method(name, &block)
|
59
|
+
model_class.send(:define_method, name, &block)
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module AssociationFreezer
|
2
|
+
module ModelAdditions
|
3
|
+
# REFACTORME !!!
|
4
|
+
def enable_association_freezer
|
5
|
+
reflect_on_all_associations(:belongs_to).each do |reflection|
|
6
|
+
MethodGenerator.new(reflection).generate
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class ActiveRecord::Base
|
13
|
+
extend AssociationFreezer::ModelAdditions
|
14
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Order do
|
4
|
+
it "respond to enable_association_freezer" do
|
5
|
+
Order.should respond_to(:enable_association_freezer)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "with freezer" do
|
9
|
+
before(:each) do
|
10
|
+
Order.enable_association_freezer
|
11
|
+
@order = Order.new
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should add a freeze association method" do
|
15
|
+
@order.should respond_to(:freeze_ship_method)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should add an unfreeze association method" do
|
19
|
+
@order.should respond_to(:unfreeze_ship_method)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should not add freeze/unfreeze methods to cart association since it doesn't have a frozen column" do
|
23
|
+
@order.should_not respond_to(:freeze_cart)
|
24
|
+
@order.should_not respond_to(:unfreeze_cart)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should not be frozen at first" do
|
28
|
+
@order.ship_method = ShipMethod.create!
|
29
|
+
@order.ship_method(true).should_not be_frozen
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should freeze association in its current state" do
|
33
|
+
ship_method = ShipMethod.create!(:price => 2)
|
34
|
+
@order.ship_method = ship_method
|
35
|
+
ship_method.price = 3
|
36
|
+
@order.freeze_ship_method
|
37
|
+
@order.ship_method.price.should == 3
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should do nothing when attempting to freeze a nil association" do
|
41
|
+
@order.ship_method.should be_nil
|
42
|
+
lambda { @order.freeze_ship_method }.should_not raise_error
|
43
|
+
@order.ship_method.should be_nil
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "when freezing association" do
|
47
|
+
before(:each) do
|
48
|
+
@ship_method = ShipMethod.create!(:price => 5)
|
49
|
+
@order.ship_method = @ship_method
|
50
|
+
@order.freeze_ship_method
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should freeze associated model" do
|
54
|
+
@order.ship_method.should be_frozen
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should not freeze original object" do
|
58
|
+
@ship_method.should_not be_frozen
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should still consider model frozen after reloading association" do
|
62
|
+
@order.ship_method(true).should be_frozen
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should ignore changes to associated model" do
|
66
|
+
@ship_method.update_attribute(:price, 8)
|
67
|
+
@order.ship_method.price.should == 5
|
68
|
+
@order.ship_method(true).price.should == 5
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should be frozen after reloading order" do
|
72
|
+
@order.save!
|
73
|
+
@order.reload
|
74
|
+
@order.ship_method.should be_frozen
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should not be frozen when unfreezing" do
|
78
|
+
@order.unfreeze_ship_method
|
79
|
+
@order.ship_method.should_not be_frozen
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should restore original attributes when unfreezing" do
|
83
|
+
@ship_method.update_attribute(:price, 8)
|
84
|
+
@order.unfreeze_ship_method
|
85
|
+
@order.ship_method.price.should == 8
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should raise an exception when attempting to save associated model" do
|
89
|
+
lambda { @order.ship_method.save }.should raise_error
|
90
|
+
lambda { @order.ship_method.save! }.should raise_error
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should raise an exception when attempting to replace association" do
|
94
|
+
lambda { @order.ship_method = ShipMethod.new }.should raise_error
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should keep id attribute for association" do
|
98
|
+
@order.ship_method.id.should == @ship_method.id
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should not consider association a new record" do
|
102
|
+
@order.ship_method.should_not be_new_record
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
data/spec/lib/order.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
class Order < ActiveRecord::Base
|
2
|
+
belongs_to :ship_method
|
3
|
+
belongs_to :cart
|
4
|
+
end
|
5
|
+
|
6
|
+
class CreateOrders < ActiveRecord::Migration
|
7
|
+
def self.up
|
8
|
+
create_table :orders do |t|
|
9
|
+
t.integer :ship_method_id
|
10
|
+
t.binary :frozen_ship_method
|
11
|
+
t.binary :cart_id
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.down
|
16
|
+
drop_table :orders
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class ShipMethod < ActiveRecord::Base
|
2
|
+
has_many :orders
|
3
|
+
end
|
4
|
+
|
5
|
+
class CreateShipMethods < ActiveRecord::Migration
|
6
|
+
def self.up
|
7
|
+
create_table :ship_methods do |t|
|
8
|
+
t.decimal :price
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.down
|
13
|
+
drop_table :ship_methods
|
14
|
+
end
|
15
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
require 'active_support'
|
4
|
+
require 'active_record'
|
5
|
+
require File.dirname(__FILE__) + '/../lib/association_freezer.rb'
|
6
|
+
|
7
|
+
# setup database adapter
|
8
|
+
FileUtils.mkdir_p(File.dirname(__FILE__) + "/../tmp/")
|
9
|
+
ActiveRecord::Base.establish_connection({
|
10
|
+
:adapter => "sqlite3",
|
11
|
+
:dbfile => File.dirname(__FILE__) + "/../tmp/test.sqlite3"
|
12
|
+
})
|
13
|
+
|
14
|
+
# load models
|
15
|
+
# there's probably a better way to handle this
|
16
|
+
require File.dirname(__FILE__) + '/lib/order.rb'
|
17
|
+
CreateOrders.migrate(:up) unless Order.table_exists?
|
18
|
+
require File.dirname(__FILE__) + '/lib/ship_method.rb'
|
19
|
+
CreateShipMethods.migrate(:up) unless ShipMethod.table_exists?
|
20
|
+
|
21
|
+
Spec::Runner.configure do |config|
|
22
|
+
config.mock_with :mocha
|
23
|
+
end
|
data/tasks/spec.rake
ADDED
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ryanb-association-freezer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryan Bates
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-07-24 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Freeze an Active Record belongs_to association.
|
17
|
+
email: ryan (at) railscasts (dot) com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- CHANGELOG
|
24
|
+
- lib/association_freezer/belongs_to_freezer.rb
|
25
|
+
- lib/association_freezer/method_generator.rb
|
26
|
+
- lib/association_freezer/model_additions.rb
|
27
|
+
- lib/association_freezer.rb
|
28
|
+
- LICENSE
|
29
|
+
- README
|
30
|
+
- tasks/deployment.rake
|
31
|
+
- tasks/spec.rake
|
32
|
+
files:
|
33
|
+
- association-freezer.gemspec
|
34
|
+
- CHANGELOG
|
35
|
+
- lib/association_freezer/belongs_to_freezer.rb
|
36
|
+
- lib/association_freezer/method_generator.rb
|
37
|
+
- lib/association_freezer/model_additions.rb
|
38
|
+
- lib/association_freezer.rb
|
39
|
+
- LICENSE
|
40
|
+
- Manifest
|
41
|
+
- README
|
42
|
+
- spec/freezer_spec.rb
|
43
|
+
- spec/lib/order.rb
|
44
|
+
- spec/lib/ship_method.rb
|
45
|
+
- spec/spec_helper.rb
|
46
|
+
- tasks/deployment.rake
|
47
|
+
- tasks/spec.rake
|
48
|
+
- tmp/test.sqlite3
|
49
|
+
has_rdoc: true
|
50
|
+
homepage: http://github.com/ryanb/association-freezer
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options:
|
53
|
+
- --line-numbers
|
54
|
+
- --inline-source
|
55
|
+
- --title
|
56
|
+
- Association-freezer
|
57
|
+
- --main
|
58
|
+
- README
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "0"
|
66
|
+
version:
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: "0"
|
72
|
+
version:
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project: association-freezer
|
76
|
+
rubygems_version: 1.2.0
|
77
|
+
signing_key:
|
78
|
+
specification_version: 2
|
79
|
+
summary: Freeze an Active Record belongs_to association.
|
80
|
+
test_files: []
|
81
|
+
|