railsgarden-has_draft 0.1.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/CHANGELOG +1 -0
- data/MIT-LICENSE +20 -0
- data/Manifest +18 -0
- data/README.rdoc +158 -0
- data/Rakefile +37 -0
- data/has_draft.gemspec +32 -0
- data/init.rb +3 -0
- data/install.rb +1 -0
- data/lib/has_draft.rb +120 -0
- data/tasks/has_draft_tasks.rake +4 -0
- data/test/config/database.yml +18 -0
- data/test/fixtures/article_drafts.yml +12 -0
- data/test/fixtures/articles.yml +23 -0
- data/test/has_draft_test.rb +96 -0
- data/test/models/article.rb +3 -0
- data/test/schema.rb +14 -0
- data/test/test_helper.rb +24 -0
- data/uninstall.rb +1 -0
- metadata +80 -0
data/CHANGELOG
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* [0.1.0] Initial Version
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 [name of plugin creator]
|
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,18 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
has_draft_plugin.sqlite3
|
3
|
+
init.rb
|
4
|
+
install.rb
|
5
|
+
lib/has_draft.rb
|
6
|
+
Manifest
|
7
|
+
MIT-LICENSE
|
8
|
+
Rakefile
|
9
|
+
README.rdoc
|
10
|
+
tasks/has_draft_tasks.rake
|
11
|
+
test/config/database.yml
|
12
|
+
test/fixtures/article_drafts.yml
|
13
|
+
test/fixtures/articles.yml
|
14
|
+
test/has_draft_test.rb
|
15
|
+
test/models/article.rb
|
16
|
+
test/schema.rb
|
17
|
+
test/test_helper.rb
|
18
|
+
uninstall.rb
|
data/README.rdoc
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
== Has Draft
|
2
|
+
|
3
|
+
Allows for multiple "drafts" of a model which can be useful when developing:
|
4
|
+
* Draft/Live Version of Pages, for examples
|
5
|
+
* A workflow system whereby a live copy may need to be active while a draft copy is
|
6
|
+
awaiting approval.
|
7
|
+
|
8
|
+
The semantics of this as well as most of the inspiration comes from version_fu,
|
9
|
+
an excellent plugin for a similar purpose of maintaining several "versions" of a model.
|
10
|
+
|
11
|
+
This was built to be able to be tacked on to existing models, so the data schema doesn't need to change
|
12
|
+
at all for the model this is applied to. As such, drafts are actually stored in a nearly-identical table
|
13
|
+
and there is a has_one relationship to this. This separation allows the base model to really be treated
|
14
|
+
just as before without having to apply conditions in queries to make sure you are really getting the
|
15
|
+
"live" (non-draft) copy: Page.all will still only return the non-draft pages. This separate table is backed by
|
16
|
+
a model created on the fly as a constant on the original model class. For example if a Page has_draft,
|
17
|
+
a Page::Draft class will exist as the model for the page_drafts table.
|
18
|
+
|
19
|
+
== Installation
|
20
|
+
|
21
|
+
# In environment.rb
|
22
|
+
config.gem 'railsgarden-has_draft', :lib => 'has_draft', :source => 'http://gems.github.com'
|
23
|
+
|
24
|
+
== Basic Example
|
25
|
+
|
26
|
+
## First Migration (If Creating base model and drafts at the same time):
|
27
|
+
class InitialSchema < ActiveRecord::Migration
|
28
|
+
|
29
|
+
[:articles, :article_drafts].each do |table_name|
|
30
|
+
create_table table_name, :force => true do |t|
|
31
|
+
t.references :article if table_name == :article_drafts
|
32
|
+
|
33
|
+
t.string :title
|
34
|
+
t.text :summary
|
35
|
+
t.text :body
|
36
|
+
t.date :post_date
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
## Model Class
|
44
|
+
class Article < ActiveRecord::Base
|
45
|
+
has_draft
|
46
|
+
end
|
47
|
+
|
48
|
+
## Exposed Class Methods & Scopes:
|
49
|
+
Article.draft_class
|
50
|
+
=> Article::Draft
|
51
|
+
Article.with_draft.all
|
52
|
+
=> (Articles that have an associated draft)
|
53
|
+
Article.without_draft.all
|
54
|
+
=> (Articles with no associated draft)
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
## Usage Examples:
|
59
|
+
|
60
|
+
article = Article.create(
|
61
|
+
:title => "My Title",
|
62
|
+
:summary => "Information here.",
|
63
|
+
:body => "Full body",
|
64
|
+
:post_date => Date.today
|
65
|
+
)
|
66
|
+
|
67
|
+
article.has_draft?
|
68
|
+
=> false
|
69
|
+
|
70
|
+
article.instantiate_draft!
|
71
|
+
|
72
|
+
article.has_draft?
|
73
|
+
=> true
|
74
|
+
|
75
|
+
article.draft
|
76
|
+
=> Article::Draft Instance
|
77
|
+
|
78
|
+
article.draft.update_attributes(
|
79
|
+
:title => "New Title"
|
80
|
+
)
|
81
|
+
|
82
|
+
article.replace_with_draft!
|
83
|
+
|
84
|
+
article.title
|
85
|
+
=> "New Title"
|
86
|
+
|
87
|
+
article.destroy_draft!
|
88
|
+
|
89
|
+
article.has_draft?
|
90
|
+
=> false
|
91
|
+
|
92
|
+
== Custom Options
|
93
|
+
|
94
|
+
## First Migration (If Creating base model and drafts at the same time):
|
95
|
+
class InitialSchema < ActiveRecord::Migration
|
96
|
+
|
97
|
+
[:articles, :article_copies].each do |table_name|
|
98
|
+
create_table table_name, :force => true do |t|
|
99
|
+
t.integer :news_article_id if table_name == :article_copies
|
100
|
+
|
101
|
+
t.string :title
|
102
|
+
t.text :summary
|
103
|
+
t.text :body
|
104
|
+
t.date :post_date
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
## Model Class
|
111
|
+
class Article < ActiveRecord::Base
|
112
|
+
has_draft :class_name => 'Copy', :foreign_key => :news_article_id, :table_name => 'article_copies'
|
113
|
+
end
|
114
|
+
|
115
|
+
== Method Callbacks
|
116
|
+
|
117
|
+
There are three callbacks you can specify directly as methods:
|
118
|
+
|
119
|
+
class Article < ActiveRecord::Base
|
120
|
+
has_draft
|
121
|
+
|
122
|
+
def before_instantiate_draft
|
123
|
+
# Do Something
|
124
|
+
end
|
125
|
+
|
126
|
+
def before_replace_with_draft
|
127
|
+
# Do Something
|
128
|
+
end
|
129
|
+
|
130
|
+
def before_destroy_draft
|
131
|
+
# Do Something
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
|
137
|
+
== Extending the Draft Class
|
138
|
+
|
139
|
+
Because you don't directly define the draft class, you can specify a block of code to be run in its
|
140
|
+
context by passing a block to has_draft:
|
141
|
+
|
142
|
+
class Article < ActiveRecord::Base
|
143
|
+
belongs_to :user
|
144
|
+
|
145
|
+
has_draft do
|
146
|
+
belongs_to :last_updated_user
|
147
|
+
|
148
|
+
def approve!
|
149
|
+
self.approved_at = Time.now
|
150
|
+
self.save
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
|
158
|
+
Copyright (c) 2008 Ben Hughes, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'echoe'
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
|
7
|
+
desc 'Default: run unit tests.'
|
8
|
+
task :default => :test
|
9
|
+
|
10
|
+
desc 'Test the has_draft plugin.'
|
11
|
+
Rake::TestTask.new(:test) do |t|
|
12
|
+
t.libs << 'lib'
|
13
|
+
t.pattern = 'test/**/*_test.rb'
|
14
|
+
t.verbose = true
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'Generate documentation for the has_draft plugin.'
|
18
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
19
|
+
rdoc.rdoc_dir = 'rdoc'
|
20
|
+
rdoc.title = 'HasDraft'
|
21
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
22
|
+
rdoc.rdoc_files.include('README')
|
23
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
Echoe.new('has_draft', '0.1.0') do |p|
|
28
|
+
p.description = "Allows for your ActiveRecord models to have drafts which are stored in a separate duplicate table."
|
29
|
+
p.url = "http://github.com/railsgarden/has_draft"
|
30
|
+
p.author = "Ben Hughes"
|
31
|
+
p.email = "ben@railsgarden.com"
|
32
|
+
p.ignore_pattern = ["tmp/*", "script/*"]
|
33
|
+
p.development_dependencies = []
|
34
|
+
end
|
35
|
+
|
36
|
+
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
37
|
+
|
data/has_draft.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{has_draft}
|
5
|
+
s.version = "0.1.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Ben Hughes"]
|
9
|
+
s.date = %q{2009-01-16}
|
10
|
+
s.description = %q{Allows for your ActiveRecord models to have drafts which are stored in a separate duplicate table.}
|
11
|
+
s.email = %q{ben@railsgarden.com}
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "lib/has_draft.rb", "README.rdoc", "tasks/has_draft_tasks.rake"]
|
13
|
+
s.files = ["CHANGELOG", "has_draft_plugin.sqlite3", "init.rb", "install.rb", "lib/has_draft.rb", "Manifest", "MIT-LICENSE", "Rakefile", "README.rdoc", "tasks/has_draft_tasks.rake", "test/config/database.yml", "test/fixtures/article_drafts.yml", "test/fixtures/articles.yml", "test/has_draft_test.rb", "test/models/article.rb", "test/schema.rb", "test/test_helper.rb", "uninstall.rb", "has_draft.gemspec"]
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.homepage = %q{http://github.com/railsgarden/has_draft}
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Has_draft", "--main", "README.rdoc"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{has_draft}
|
19
|
+
s.rubygems_version = %q{1.3.1}
|
20
|
+
s.summary = %q{Allows for your ActiveRecord models to have drafts which are stored in a separate duplicate table.}
|
21
|
+
s.test_files = ["test/has_draft_test.rb", "test/test_helper.rb"]
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 2
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
else
|
29
|
+
end
|
30
|
+
else
|
31
|
+
end
|
32
|
+
end
|
data/init.rb
ADDED
data/install.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Install hook code here
|
data/lib/has_draft.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
module Rubiety
|
2
|
+
module HasDraft
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def has_draft(options = {}, &block)
|
9
|
+
return if self.included_modules.include?(HasDraft::InstanceMethods)
|
10
|
+
include HasDraft::InstanceMethods
|
11
|
+
|
12
|
+
cattr_accessor :draft_class_name, :draft_foreign_key, :draft_table_name, :draft_columns
|
13
|
+
|
14
|
+
self.draft_class_name = options[:class_name] || 'Draft'
|
15
|
+
self.draft_foreign_key = options[:foreign_key] || self.to_s.foreign_key
|
16
|
+
self.draft_table_name = options[:table_name] || "#{table_name_prefix}#{base_class.name.demodulize.underscore}_drafts#{table_name_suffix}"
|
17
|
+
|
18
|
+
# Create Relationship to Draft Copy
|
19
|
+
class_eval do
|
20
|
+
has_one :draft, :class_name => "#{self.to_s}::#{draft_class_name}",
|
21
|
+
:foreign_key => draft_foreign_key,
|
22
|
+
:dependent => :destroy
|
23
|
+
|
24
|
+
named_scope :with_draft, :include => [:draft], :conditions => "#{draft_table_name}.id IS NOT NULL"
|
25
|
+
named_scope :without_draft, :include => [:draft], :conditions => "#{draft_table_name}.id IS NULL"
|
26
|
+
end
|
27
|
+
|
28
|
+
# Dynamically Create Model::Draft Class
|
29
|
+
const_set(draft_class_name, Class.new(ActiveRecord::Base))
|
30
|
+
|
31
|
+
draft_class.cattr_accessor :original_class
|
32
|
+
draft_class.original_class = self
|
33
|
+
draft_class.set_table_name(draft_table_name)
|
34
|
+
|
35
|
+
# Draft Parent Association
|
36
|
+
draft_class.belongs_to self.to_s.demodulize.underscore.to_sym, :class_name => "::#{self.to_s}", :foreign_key => draft_foreign_key
|
37
|
+
|
38
|
+
# Block extension
|
39
|
+
draft_class.class_eval(&block) if block_given?
|
40
|
+
|
41
|
+
# Finally setup which columns to draft
|
42
|
+
self.draft_columns = draft_class.new.attributes.keys - [draft_class.primary_key, draft_foreign_key, 'created_at', 'updated_at', inheritance_column]
|
43
|
+
end
|
44
|
+
|
45
|
+
def draft_class
|
46
|
+
const_get(draft_class_name)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
module InstanceMethods
|
51
|
+
def has_draft?
|
52
|
+
!self.draft.nil?
|
53
|
+
end
|
54
|
+
|
55
|
+
def save_to_draft(perform_validation = true)
|
56
|
+
return false if perform_validation and !self.valid?
|
57
|
+
|
58
|
+
instantiate_draft! unless has_draft?
|
59
|
+
copy_attributes_to_draft
|
60
|
+
|
61
|
+
self.draft.save(perform_validation)
|
62
|
+
self.reload
|
63
|
+
end
|
64
|
+
|
65
|
+
def instantiate_draft
|
66
|
+
self.draft = self.build_draft
|
67
|
+
|
68
|
+
copy_attributes_to_draft
|
69
|
+
before_instantiate_draft
|
70
|
+
|
71
|
+
self.draft
|
72
|
+
end
|
73
|
+
|
74
|
+
def instantiate_draft!
|
75
|
+
returning instantiate_draft do |draft|
|
76
|
+
draft.save unless self.new_record?
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def copy_attributes_to_draft
|
81
|
+
self.class.draft_columns.each do |attribute|
|
82
|
+
self.draft.send("#{attribute}=", send(attribute))
|
83
|
+
end
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
def copy_attributes_from_draft
|
88
|
+
self.class.draft_columns.each do |attribute|
|
89
|
+
self.send("#{attribute}=", self.draft.send(attribute))
|
90
|
+
end
|
91
|
+
self
|
92
|
+
end
|
93
|
+
|
94
|
+
def before_instantiate_draft
|
95
|
+
end
|
96
|
+
|
97
|
+
def replace_with_draft!
|
98
|
+
copy_attributes_from_draft
|
99
|
+
|
100
|
+
before_replace_with_draft
|
101
|
+
|
102
|
+
self.save unless self.new_record?
|
103
|
+
self
|
104
|
+
end
|
105
|
+
|
106
|
+
def before_replace_with_draft
|
107
|
+
end
|
108
|
+
|
109
|
+
def destroy_draft!
|
110
|
+
before_destroy_draft
|
111
|
+
|
112
|
+
self.draft.destroy if self.draft
|
113
|
+
self.draft(true)
|
114
|
+
end
|
115
|
+
|
116
|
+
def before_destroy_draft
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
sqlite:
|
2
|
+
:adapter: sqlite
|
3
|
+
:dbfile: has_draft_plugin.sqlite
|
4
|
+
sqlite3:
|
5
|
+
:adapter: sqlite3
|
6
|
+
:dbfile: has_draft_plugin.sqlite3
|
7
|
+
postgresql:
|
8
|
+
:adapter: postgresql
|
9
|
+
:username: postgres
|
10
|
+
:password: postgres
|
11
|
+
:database: has_draft_plugin_test
|
12
|
+
:min_messages: ERROR
|
13
|
+
mysql:
|
14
|
+
:adapter: mysql
|
15
|
+
:host: localhost
|
16
|
+
:username: root
|
17
|
+
:password:
|
18
|
+
:database: has_draft_plugin_test
|
@@ -0,0 +1,12 @@
|
|
1
|
+
article_with_draft:
|
2
|
+
article_id: <%= Fixtures.identify('article_with_draft') %>
|
3
|
+
title: Article With Draft Changed
|
4
|
+
summary: >
|
5
|
+
Changed: Sed cursus cursus velit. Sed cursus cursus velit.
|
6
|
+
body: >
|
7
|
+
Changed: Nunc auctor bibendum eros. Maecenas porta accumsan mauris. Etiam enim enim, elementum sed, bibendum quis, rhoncus non,
|
8
|
+
metus. Fusce neque dolor, adipiscing sed, consectetuer et, lacinia sit amet, quam. Suspendisse wisi quam,
|
9
|
+
consectetuer in, blandit sed, suscipit eu, eros. Etiam ligula enim, tempor ut, blandit nec, mollis eu, lectus.
|
10
|
+
Nam cursus. Vivamus iaculis. Aenean risus purus, pharetra in, blandit quis, gravida a, turpis. Donec nisl.
|
11
|
+
Aenean eget mi. Fusce mattis est id diam. Phasellus faucibus interdum sapien. Duis quis nunc. Sed enim.
|
12
|
+
post_date: <%= Date.today.to_s(:db) %>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
article_without_draft:
|
2
|
+
title: Article Without Draft
|
3
|
+
summary: >
|
4
|
+
Sed cursus cursus velit. Sed cursus cursus velit.
|
5
|
+
body: >
|
6
|
+
Nunc auctor bibendum eros. Maecenas porta accumsan mauris. Etiam enim enim, elementum sed, bibendum quis, rhoncus non,
|
7
|
+
metus. Fusce neque dolor, adipiscing sed, consectetuer et, lacinia sit amet, quam. Suspendisse wisi quam,
|
8
|
+
consectetuer in, blandit sed, suscipit eu, eros. Etiam ligula enim, tempor ut, blandit nec, mollis eu, lectus.
|
9
|
+
Nam cursus. Vivamus iaculis. Aenean risus purus, pharetra in, blandit quis, gravida a, turpis. Donec nisl.
|
10
|
+
Aenean eget mi. Fusce mattis est id diam. Phasellus faucibus interdum sapien. Duis quis nunc. Sed enim.
|
11
|
+
post_date: <%= Date.today.to_s(:db) %>
|
12
|
+
|
13
|
+
article_with_draft:
|
14
|
+
title: Article With Draft
|
15
|
+
summary: >
|
16
|
+
Sed cursus cursus velit. Sed cursus cursus velit.
|
17
|
+
body: >
|
18
|
+
Nunc auctor bibendum eros. Maecenas porta accumsan mauris. Etiam enim enim, elementum sed, bibendum quis, rhoncus non,
|
19
|
+
metus. Fusce neque dolor, adipiscing sed, consectetuer et, lacinia sit amet, quam. Suspendisse wisi quam,
|
20
|
+
consectetuer in, blandit sed, suscipit eu, eros. Etiam ligula enim, tempor ut, blandit nec, mollis eu, lectus.
|
21
|
+
Nam cursus. Vivamus iaculis. Aenean risus purus, pharetra in, blandit quis, gravida a, turpis. Donec nisl.
|
22
|
+
Aenean eget mi. Fusce mattis est id diam. Phasellus faucibus interdum sapien. Duis quis nunc. Sed enim.
|
23
|
+
post_date: <%= Date.today.to_s(:db) %>
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
require File.join(File.dirname(__FILE__), 'models/article')
|
3
|
+
|
4
|
+
class ArticleTest < Test::Unit::TestCase
|
5
|
+
fixtures :articles, :article_drafts
|
6
|
+
set_fixture_class :article_drafts => Article::Draft
|
7
|
+
|
8
|
+
context "Article model" do
|
9
|
+
should_have_one :draft
|
10
|
+
should_have_named_scope :with_draft
|
11
|
+
should_have_named_scope :without_draft
|
12
|
+
|
13
|
+
should_have_class_methods :draft_class_name, :draft_foreign_key, :draft_table_name
|
14
|
+
|
15
|
+
should "default class name to Draft" do
|
16
|
+
assert_equal "Draft", Article.draft_class_name
|
17
|
+
end
|
18
|
+
|
19
|
+
should "expose draft class constant" do
|
20
|
+
assert_equal Article::Draft, Article.draft_class
|
21
|
+
end
|
22
|
+
|
23
|
+
should "default foreign key to article_id" do
|
24
|
+
assert_equal "article_id", Article.draft_foreign_key
|
25
|
+
end
|
26
|
+
|
27
|
+
should "default table name to article_drafts" do
|
28
|
+
assert_equal "article_drafts", Article.draft_table_name
|
29
|
+
end
|
30
|
+
|
31
|
+
context "Draft model" do
|
32
|
+
should "have a be defined under Article" do
|
33
|
+
assert Article.constants.include?('Draft')
|
34
|
+
end
|
35
|
+
|
36
|
+
should "load" do
|
37
|
+
assert_nothing_raised do
|
38
|
+
Article::Draft
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
should "expose original class name of Article" do
|
43
|
+
assert_equal Article, Article::Draft.original_class
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "an article" do
|
49
|
+
setup { @article = articles(:article_without_draft) }
|
50
|
+
|
51
|
+
context "when instantiating a new draft" do
|
52
|
+
setup { @article.instantiate_draft! }
|
53
|
+
|
54
|
+
should "create draft" do
|
55
|
+
assert_not_nil @article.draft
|
56
|
+
assert !@article.draft.new_record?
|
57
|
+
end
|
58
|
+
|
59
|
+
should "copy draft fields" do
|
60
|
+
Article.draft_columns.each do |column|
|
61
|
+
assert_equal @article.send(column), @article.draft.send(column)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "when destroying an existing draft" do
|
67
|
+
setup do
|
68
|
+
@article = articles(:article_with_draft)
|
69
|
+
@article.destroy_draft!
|
70
|
+
end
|
71
|
+
|
72
|
+
should "destroy associated draft" do
|
73
|
+
assert_nil @article.draft
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "when replacing with draft" do
|
78
|
+
setup do
|
79
|
+
@article = articles(:article_with_draft)
|
80
|
+
@article.replace_with_draft!
|
81
|
+
end
|
82
|
+
|
83
|
+
should "still have draft" do
|
84
|
+
assert_not_nil @article.draft
|
85
|
+
end
|
86
|
+
|
87
|
+
should "now have the same field values as draft" do
|
88
|
+
Article.draft_columns.each do |column|
|
89
|
+
assert_equal @article.send(column), @article.draft.send(column)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
data/test/schema.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
ActiveRecord::Schema.define(:version => 0) do
|
2
|
+
|
3
|
+
[:articles, :article_drafts].each do |table_name|
|
4
|
+
create_table table_name, :force => true do |t|
|
5
|
+
t.references :article if table_name == :article_drafts
|
6
|
+
|
7
|
+
t.string :title
|
8
|
+
t.text :summary
|
9
|
+
t.text :body
|
10
|
+
t.date :post_date
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'active_record'
|
4
|
+
require 'active_record/fixtures'
|
5
|
+
require 'shoulda/rails'
|
6
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../lib/has_draft'))
|
7
|
+
|
8
|
+
config = YAML::load(IO.read(File.join(File.dirname(__FILE__), 'config', '/database.yml')))
|
9
|
+
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
|
10
|
+
ActiveRecord::Base.configurations = {'test' => config[ENV['DB'] || 'sqlite3']}
|
11
|
+
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])
|
12
|
+
|
13
|
+
load(File.dirname(__FILE__) + "/schema.rb")
|
14
|
+
|
15
|
+
Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
|
16
|
+
$:.unshift(Test::Unit::TestCase.fixture_path)
|
17
|
+
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
|
18
|
+
|
19
|
+
class Test::Unit::TestCase
|
20
|
+
self.use_transactional_fixtures = true
|
21
|
+
self.use_instantiated_fixtures = false
|
22
|
+
end
|
23
|
+
|
24
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../init'))
|
data/uninstall.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Uninstall hook code here
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: railsgarden-has_draft
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ben Hughes
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-01-16 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Allows for your ActiveRecord models to have drafts which are stored in a separate duplicate table.
|
17
|
+
email: ben@railsgarden.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- CHANGELOG
|
24
|
+
- lib/has_draft.rb
|
25
|
+
- README.rdoc
|
26
|
+
- tasks/has_draft_tasks.rake
|
27
|
+
files:
|
28
|
+
- CHANGELOG
|
29
|
+
- has_draft_plugin.sqlite3
|
30
|
+
- init.rb
|
31
|
+
- install.rb
|
32
|
+
- lib/has_draft.rb
|
33
|
+
- Manifest
|
34
|
+
- MIT-LICENSE
|
35
|
+
- Rakefile
|
36
|
+
- README.rdoc
|
37
|
+
- tasks/has_draft_tasks.rake
|
38
|
+
- test/config/database.yml
|
39
|
+
- test/fixtures/article_drafts.yml
|
40
|
+
- test/fixtures/articles.yml
|
41
|
+
- test/has_draft_test.rb
|
42
|
+
- test/models/article.rb
|
43
|
+
- test/schema.rb
|
44
|
+
- test/test_helper.rb
|
45
|
+
- uninstall.rb
|
46
|
+
- has_draft.gemspec
|
47
|
+
has_rdoc: true
|
48
|
+
homepage: http://github.com/railsgarden/has_draft
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options:
|
51
|
+
- --line-numbers
|
52
|
+
- --inline-source
|
53
|
+
- --title
|
54
|
+
- Has_draft
|
55
|
+
- --main
|
56
|
+
- README.rdoc
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: "0"
|
64
|
+
version:
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: "1.2"
|
70
|
+
version:
|
71
|
+
requirements: []
|
72
|
+
|
73
|
+
rubyforge_project: has_draft
|
74
|
+
rubygems_version: 1.2.0
|
75
|
+
signing_key:
|
76
|
+
specification_version: 2
|
77
|
+
summary: Allows for your ActiveRecord models to have drafts which are stored in a separate duplicate table.
|
78
|
+
test_files:
|
79
|
+
- test/has_draft_test.rb
|
80
|
+
- test/test_helper.rb
|