has_draft 1.0.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.rdoc +10 -0
- data/LICENSE +20 -0
- data/README.rdoc +154 -0
- data/Rakefile +14 -0
- data/init.rb +3 -0
- data/lib/has_draft/railtie.rb +19 -0
- data/lib/has_draft/version.rb +3 -0
- data/lib/has_draft.rb +120 -0
- data/spec/db/database.yml +21 -0
- data/spec/db/schema.rb +14 -0
- data/spec/db/test.sqlite3 +0 -0
- data/spec/factories/article.rb +20 -0
- data/spec/has_draft_spec.rb +79 -0
- data/spec/spec_helper.rb +25 -0
- metadata +113 -0
data/CHANGELOG.rdoc
ADDED
data/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/README.rdoc
ADDED
@@ -0,0 +1,154 @@
|
|
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
|
+
This was built to be able to be tacked on to existing models, so the data schema doesn't need to change
|
9
|
+
at all for the model this is applied to. Drafts are actually stored in a nearly-identical table
|
10
|
+
and there is a has_one relationship to this. This separation allows the base model to really be treated
|
11
|
+
just as before without having to apply conditions in queries to make sure you are really getting the
|
12
|
+
"live" (non-draft) copy: Page.all will still only return the non-draft pages. This separate table is backed by
|
13
|
+
a model created on the fly as a constant on the original model class. For example if a Page has_draft,
|
14
|
+
a Page::Draft class will exist as the model for the page_drafts table.
|
15
|
+
|
16
|
+
== Installation
|
17
|
+
|
18
|
+
This gem requires ActiveRecord 3.0.
|
19
|
+
|
20
|
+
In your Gemfile:
|
21
|
+
|
22
|
+
gem "has_draft"
|
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
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "rake"
|
3
|
+
require "rake/rdoctask"
|
4
|
+
|
5
|
+
desc "Generate documentation for the plugin."
|
6
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
7
|
+
rdoc.rdoc_dir = "rdoc"
|
8
|
+
rdoc.title = "has_draft"
|
9
|
+
rdoc.options << "--line-numbers" << "--inline-source"
|
10
|
+
rdoc.rdoc_files.include('README')
|
11
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
12
|
+
end
|
13
|
+
|
14
|
+
Dir["#{File.dirname(__FILE__)}/lib/tasks/*.rake"].sort.each { |ext| load ext }
|
data/init.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module HasDraft
|
2
|
+
if defined?(Rails::Railtie)
|
3
|
+
require "rails"
|
4
|
+
|
5
|
+
class Railtie < Rails::Railtie
|
6
|
+
initializer "has_draft.extend_active_record" do
|
7
|
+
ActiveSupport.on_load(:active_record) do
|
8
|
+
HasDraft::Railtie.insert
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Railtie
|
15
|
+
def self.insert
|
16
|
+
ActiveRecord::Base.send(:include, HasDraft)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/has_draft.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
module HasDraft
|
2
|
+
def self.included(base)
|
3
|
+
base.extend ClassMethods
|
4
|
+
end
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
def has_draft(options = {}, &block)
|
8
|
+
return if self.included_modules.include?(HasDraft::InstanceMethods)
|
9
|
+
include HasDraft::InstanceMethods
|
10
|
+
|
11
|
+
cattr_accessor :draft_class_name, :draft_foreign_key, :draft_table_name, :draft_columns
|
12
|
+
|
13
|
+
self.draft_class_name = options[:class_name] || 'Draft'
|
14
|
+
self.draft_foreign_key = options[:foreign_key] || self.to_s.foreign_key
|
15
|
+
self.draft_table_name = options[:table_name] || "#{table_name_prefix}#{base_class.name.demodulize.underscore}_drafts#{table_name_suffix}"
|
16
|
+
|
17
|
+
# Create Relationship to Draft Copy
|
18
|
+
class_eval do
|
19
|
+
has_one :draft, :class_name => "#{self.to_s}::#{draft_class_name}",
|
20
|
+
:foreign_key => draft_foreign_key,
|
21
|
+
:dependent => :destroy
|
22
|
+
|
23
|
+
named_scope :with_draft, :include => [:draft], :conditions => "#{draft_table_name}.id IS NOT NULL"
|
24
|
+
named_scope :without_draft, :include => [:draft], :conditions => "#{draft_table_name}.id IS NULL"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Dynamically Create Model::Draft Class
|
28
|
+
const_set(draft_class_name, Class.new(ActiveRecord::Base))
|
29
|
+
|
30
|
+
draft_class.cattr_accessor :original_class
|
31
|
+
draft_class.original_class = self
|
32
|
+
draft_class.set_table_name(draft_table_name)
|
33
|
+
|
34
|
+
# Draft Parent Association
|
35
|
+
draft_class.belongs_to self.to_s.demodulize.underscore.to_sym, :class_name => "::#{self.to_s}", :foreign_key => draft_foreign_key
|
36
|
+
|
37
|
+
# Block extension
|
38
|
+
draft_class.class_eval(&block) if block_given?
|
39
|
+
|
40
|
+
# Finally setup which columns to draft
|
41
|
+
self.draft_columns = draft_class.new.attributes.keys - [draft_class.primary_key, draft_foreign_key, 'created_at', 'updated_at', inheritance_column]
|
42
|
+
end
|
43
|
+
|
44
|
+
def draft_class
|
45
|
+
const_get(draft_class_name)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
module InstanceMethods
|
50
|
+
def has_draft?
|
51
|
+
!self.draft.nil?
|
52
|
+
end
|
53
|
+
|
54
|
+
def save_to_draft(perform_validation = true)
|
55
|
+
return false if perform_validation and !self.valid?
|
56
|
+
|
57
|
+
instantiate_draft! unless has_draft?
|
58
|
+
copy_attributes_to_draft
|
59
|
+
|
60
|
+
self.draft.save(perform_validation)
|
61
|
+
self.reload
|
62
|
+
end
|
63
|
+
|
64
|
+
def instantiate_draft
|
65
|
+
self.draft = self.build_draft
|
66
|
+
|
67
|
+
copy_attributes_to_draft
|
68
|
+
before_instantiate_draft
|
69
|
+
|
70
|
+
self.draft
|
71
|
+
end
|
72
|
+
|
73
|
+
def instantiate_draft!
|
74
|
+
returning instantiate_draft do |draft|
|
75
|
+
draft.save unless self.new_record?
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def copy_attributes_to_draft
|
80
|
+
self.class.draft_columns.each do |attribute|
|
81
|
+
self.draft.send("#{attribute}=", send(attribute))
|
82
|
+
end
|
83
|
+
self
|
84
|
+
end
|
85
|
+
|
86
|
+
def copy_attributes_from_draft
|
87
|
+
self.class.draft_columns.each do |attribute|
|
88
|
+
self.send("#{attribute}=", self.draft.send(attribute))
|
89
|
+
end
|
90
|
+
self
|
91
|
+
end
|
92
|
+
|
93
|
+
def before_instantiate_draft
|
94
|
+
end
|
95
|
+
|
96
|
+
def replace_with_draft!
|
97
|
+
copy_attributes_from_draft
|
98
|
+
|
99
|
+
before_replace_with_draft
|
100
|
+
|
101
|
+
self.save unless self.new_record?
|
102
|
+
self
|
103
|
+
end
|
104
|
+
|
105
|
+
def before_replace_with_draft
|
106
|
+
end
|
107
|
+
|
108
|
+
def destroy_draft!
|
109
|
+
before_destroy_draft
|
110
|
+
|
111
|
+
self.draft.destroy if self.draft
|
112
|
+
self.draft(true)
|
113
|
+
end
|
114
|
+
|
115
|
+
def before_destroy_draft
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
require "has_draft/railtie"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
sqlite:
|
2
|
+
adapter: sqlite
|
3
|
+
database: spec/db/test.sqlite
|
4
|
+
|
5
|
+
sqlite3:
|
6
|
+
adapter: sqlite3
|
7
|
+
database: spec/db/test.sqlite3
|
8
|
+
|
9
|
+
postgresql:
|
10
|
+
adapter: postgresql
|
11
|
+
username: postgres
|
12
|
+
password: postgres
|
13
|
+
database: has_draft_plugin_test
|
14
|
+
min_messages: ERROR
|
15
|
+
|
16
|
+
mysql:
|
17
|
+
adapter: mysql
|
18
|
+
host: localhost
|
19
|
+
username: root
|
20
|
+
password:
|
21
|
+
database: has_draft_plugin_test
|
data/spec/db/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
|
Binary file
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "factory_girl"
|
2
|
+
|
3
|
+
Factory.define(:article) do |f|
|
4
|
+
f.title { Faker::Lorem.sentence }
|
5
|
+
f.summary { Faker::Lorem.paragraphs.first }
|
6
|
+
f.body { Faker::Lorem.paragraphs.join("\n\n") }
|
7
|
+
f.post_date { 1.day.ago.to_date }
|
8
|
+
end
|
9
|
+
|
10
|
+
Factory.define(:article_draft, :class => Article::Draft) do |f|
|
11
|
+
f.association(:article)
|
12
|
+
f.title { Faker::Lorem.sentence }
|
13
|
+
f.summary { Faker::Lorem.paragraphs.first }
|
14
|
+
f.body { Faker::Lorem.paragraphs.join("\n\n") }
|
15
|
+
f.post_date { 1.day.ago.to_date }
|
16
|
+
end
|
17
|
+
|
18
|
+
Factory.define(:article_with_draft, :parent => :article) do |f|
|
19
|
+
f.association(:draft, :factory => :article_draft)
|
20
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe HasDraft do
|
4
|
+
context "Model with has_draft" do
|
5
|
+
it "should expose #draft_class_name as Draft" do
|
6
|
+
Article.draft_class_name.should == "Draft"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should expose #draft_class as Article::Draft" do
|
10
|
+
Article.draft_class.should == Article::Draft
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should default #draft_foreign_key as article_id" do
|
14
|
+
Article.draft_foreign_key.should == "article_id"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should default #draft_table_name as article_drafts" do
|
18
|
+
Article.draft_table_name.should == "article_drafts"
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "Draft Model" do
|
22
|
+
it "should be defined under the Article namespace" do
|
23
|
+
Article.constants.should include('Draft')
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should expose #original_class as Article" do
|
27
|
+
Article::Draft.original_class.should == Article
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "an article" do
|
33
|
+
before { @article = Factory.create(:article) }
|
34
|
+
|
35
|
+
context "when instantiating a new draft" do
|
36
|
+
before { @article.instantiate_draft! }
|
37
|
+
|
38
|
+
it "should create draft" do
|
39
|
+
@article.draft.should_not be_nil
|
40
|
+
@article.draft.should_not be_new_record
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should copy draft fields" do
|
44
|
+
Article.draft_columns.each do |column|
|
45
|
+
@article.send(column).should == @article.draft.send(column)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "when destroying an existing draft" do
|
51
|
+
before do
|
52
|
+
@article = Factory.create(:article_with_draft)
|
53
|
+
@article.destroy_draft!
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should associated draft" do
|
57
|
+
@article.draft.should be_nil
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when replacing with draft" do
|
62
|
+
before do
|
63
|
+
@article = Factory.create(:article_with_draft)
|
64
|
+
@article.replace_with_draft!
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should still have draft" do
|
68
|
+
@article.draft.should_not be_nil
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should now have the same field values as draft" do
|
72
|
+
Article.draft_columns.each do |column|
|
73
|
+
@article.send(column).should == @article.draft.send(column)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "rspec"
|
3
|
+
require "factory_girl"
|
4
|
+
require "faker"
|
5
|
+
require "rails"
|
6
|
+
require "active_record"
|
7
|
+
require "active_support"
|
8
|
+
|
9
|
+
# Establish DB Connection
|
10
|
+
config = YAML::load(IO.read(File.join(File.dirname(__FILE__), 'db', 'database.yml')))
|
11
|
+
ActiveRecord::Base.configurations = {'test' => config[ENV['DB'] || 'sqlite3']}
|
12
|
+
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])
|
13
|
+
|
14
|
+
# Load Test Schema into the Database
|
15
|
+
load(File.dirname(__FILE__) + "/db/schema.rb")
|
16
|
+
|
17
|
+
require File.dirname(__FILE__) + '/../init'
|
18
|
+
|
19
|
+
# Example has_draft Model:
|
20
|
+
class Article < ActiveRecord::Base
|
21
|
+
has_draft
|
22
|
+
end
|
23
|
+
|
24
|
+
# Load Factories:
|
25
|
+
Dir[File.join(File.dirname(__FILE__), "factories/**/*.rb")].each {|f| require f}
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: has_draft
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 21
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 1.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Ben Hughes
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-10-15 00:00:00 +08:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: activesupport
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 7
|
30
|
+
segments:
|
31
|
+
- 3
|
32
|
+
- 0
|
33
|
+
- 0
|
34
|
+
version: 3.0.0
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: activerecord
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 7
|
46
|
+
segments:
|
47
|
+
- 3
|
48
|
+
- 0
|
49
|
+
- 0
|
50
|
+
version: 3.0.0
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
description: Allows for your ActiveRecord models to have drafts which are stored in a separate duplicate table.
|
54
|
+
email: ben@railsgarden.com
|
55
|
+
executables: []
|
56
|
+
|
57
|
+
extensions: []
|
58
|
+
|
59
|
+
extra_rdoc_files: []
|
60
|
+
|
61
|
+
files:
|
62
|
+
- lib/has_draft/railtie.rb
|
63
|
+
- lib/has_draft/version.rb
|
64
|
+
- lib/has_draft.rb
|
65
|
+
- spec/db/database.yml
|
66
|
+
- spec/db/schema.rb
|
67
|
+
- spec/db/test.sqlite3
|
68
|
+
- spec/factories/article.rb
|
69
|
+
- spec/has_draft_spec.rb
|
70
|
+
- spec/spec_helper.rb
|
71
|
+
- CHANGELOG.rdoc
|
72
|
+
- LICENSE
|
73
|
+
- Rakefile
|
74
|
+
- README.rdoc
|
75
|
+
- init.rb
|
76
|
+
has_rdoc: true
|
77
|
+
homepage: http://github.com/rubiety/has_draft
|
78
|
+
licenses: []
|
79
|
+
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
hash: 3
|
91
|
+
segments:
|
92
|
+
- 0
|
93
|
+
version: "0"
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
hash: 19
|
100
|
+
segments:
|
101
|
+
- 1
|
102
|
+
- 3
|
103
|
+
- 4
|
104
|
+
version: 1.3.4
|
105
|
+
requirements: []
|
106
|
+
|
107
|
+
rubyforge_project: has_draft
|
108
|
+
rubygems_version: 1.3.7
|
109
|
+
signing_key:
|
110
|
+
specification_version: 3
|
111
|
+
summary: Attached draft model to your ActiveRecord models.
|
112
|
+
test_files: []
|
113
|
+
|