jakewendt-simply_documents 1.3.4
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/README.rdoc +70 -0
- data/app/controllers/documents_controller.rb +99 -0
- data/app/models/document.rb +28 -0
- data/app/views/documents/_document.html.erb +15 -0
- data/app/views/documents/_form.html.erb +13 -0
- data/app/views/documents/edit.html.erb +14 -0
- data/app/views/documents/index.html.erb +15 -0
- data/app/views/documents/new.html.erb +11 -0
- data/app/views/documents/preview.html.erb +17 -0
- data/config/document.yml +54 -0
- data/config/routes.rb +5 -0
- data/generators/simply_documents/USAGE +0 -0
- data/generators/simply_documents/simply_documents_generator.rb +87 -0
- data/generators/simply_documents/templates/autotest_simply_documents.rb +2 -0
- data/generators/simply_documents/templates/functional/documents_controller_test.rb +220 -0
- data/generators/simply_documents/templates/javascripts/documents.js +0 -0
- data/generators/simply_documents/templates/migrations/add_attachments_document_to_document.rb +19 -0
- data/generators/simply_documents/templates/migrations/create_documents.rb +19 -0
- data/generators/simply_documents/templates/migrations/polymorphicize_document_owner.rb +13 -0
- data/generators/simply_documents/templates/simply_documents.rake +6 -0
- data/generators/simply_documents/templates/stylesheets/documents.css +4 -0
- data/generators/simply_documents/templates/unit/document_test.rb +18 -0
- data/lib/jakewendt-simply_documents.rb +1 -0
- data/lib/simply_documents.rb +54 -0
- data/lib/simply_documents/autotest.rb +26 -0
- data/lib/simply_documents/factories.rb +4 -0
- data/lib/simply_documents/file_utils_extension.rb +18 -0
- data/lib/simply_documents/owner.rb +12 -0
- data/lib/simply_documents/tasks.rb +1 -0
- data/lib/simply_documents/test_tasks.rb +56 -0
- data/lib/tasks/application.rake +40 -0
- data/lib/tasks/database.rake +52 -0
- data/lib/tasks/documentation.rake +68 -0
- data/lib/tasks/rcov.rake +44 -0
- data/lib/tasks/simply_authorized.rake +2 -0
- data/lib/tasks/simply_helpful.rake +2 -0
- data/lib/tasks/simply_sessions.rake +5 -0
- data/lib/tasks/ucb_ccls_engine_tasks.rake +50 -0
- data/rails/init.rb +1 -0
- data/test/app/controllers/application_controller.rb +41 -0
- data/test/app/controllers/home_controller.rb +10 -0
- data/test/app/models/user.rb +3 -0
- data/test/assets/edit_save_wireframe.pdf +0 -0
- data/test/config/routes.rb +9 -0
- data/test/functional/documents/documents_controller_test.rb +222 -0
- data/test/unit/documents/document_test.rb +18 -0
- metadata +271 -0
data/README.rdoc
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
= SimplyDocuments
|
2
|
+
|
3
|
+
== ToDo
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
== Required Gem Sources
|
8
|
+
|
9
|
+
gem sources -a http://rubygems.org
|
10
|
+
gem sources -a http://gems.github.com
|
11
|
+
|
12
|
+
|
13
|
+
== Required Gems
|
14
|
+
|
15
|
+
* {jakewendt-assert_this_and_that}[http://github.com/jakewendt/assert_this_and_that]
|
16
|
+
* {jakewendt-ruby_extension}[http://github.com/jakewendt/ruby_extension] - modifications, updates and patches for ruby.
|
17
|
+
* rails ~> 2
|
18
|
+
* chronic
|
19
|
+
* ruby-hmac
|
20
|
+
* aws-s3
|
21
|
+
* ssl_requirement
|
22
|
+
* ryanb-acts-as-list
|
23
|
+
* RedCloth
|
24
|
+
* paperclip
|
25
|
+
* thoughtbot-factory_girl
|
26
|
+
* {jakewendt-simply_helpful}[http://github.com/jakewendt/simply_helpful]
|
27
|
+
* {jakewendt-simply_authorized}[http://github.com/jakewendt/simply_authorized]
|
28
|
+
* {jakewendt-calnet_authenticated}[http://github.com/jakewendt/calnet_authenticated]
|
29
|
+
|
30
|
+
|
31
|
+
== Installation and Usage
|
32
|
+
|
33
|
+
cp config/s3.yml.example config/s3.yml
|
34
|
+
# Add your own s3 access keys. Leave 'test' as it is.
|
35
|
+
|
36
|
+
config.gem 'jakewendt-simply_documents',
|
37
|
+
:source => 'http://rubygems.org'
|
38
|
+
|
39
|
+
class User (or whatever)
|
40
|
+
document_owner
|
41
|
+
end
|
42
|
+
|
43
|
+
script/generate simply_documents
|
44
|
+
|
45
|
+
User.find_create_and_update_by_uid('859908').deputize
|
46
|
+
|
47
|
+
== Testing (as an app)
|
48
|
+
|
49
|
+
rake db:migrate
|
50
|
+
rake db:fixtures:load
|
51
|
+
rake test
|
52
|
+
script/server
|
53
|
+
|
54
|
+
|
55
|
+
== Gemified with Jeweler
|
56
|
+
|
57
|
+
vi Rakefile
|
58
|
+
rake version:write
|
59
|
+
|
60
|
+
rake version:bump:patch
|
61
|
+
rake version:bump:minor
|
62
|
+
rake version:bump:major
|
63
|
+
|
64
|
+
rake gemspec
|
65
|
+
|
66
|
+
rake install
|
67
|
+
rake release
|
68
|
+
|
69
|
+
|
70
|
+
Copyright (c) 2010 [Jake Wendt], released under the MIT license
|
@@ -0,0 +1,99 @@
|
|
1
|
+
class DocumentsController < ApplicationController
|
2
|
+
|
3
|
+
before_filter :login_required
|
4
|
+
|
5
|
+
before_filter :may_maintain_pages_required
|
6
|
+
before_filter :document_required, :only => :show
|
7
|
+
before_filter :id_required,
|
8
|
+
:only => [ :edit, :update, :destroy, :preview ]
|
9
|
+
|
10
|
+
def show
|
11
|
+
if @document.document.path.blank?
|
12
|
+
flash[:error] = "Does not contain a document"
|
13
|
+
redirect_to preview_document_path(@document)
|
14
|
+
elsif @document.document.exists?
|
15
|
+
#puts "Document exists!"
|
16
|
+
if @document.document.options[:storage] == :filesystem # &&
|
17
|
+
# File.exists?(@document.document.path)
|
18
|
+
# basically development or non-s3 setup
|
19
|
+
send_file @document.document.path
|
20
|
+
else
|
21
|
+
#puts "Storage is S3?"
|
22
|
+
|
23
|
+
# Privacy filters are still not active
|
24
|
+
# basically a private s3 file
|
25
|
+
# redirect_to @document.s3_url
|
26
|
+
redirect_to @document.document.expiring_url
|
27
|
+
|
28
|
+
end
|
29
|
+
else
|
30
|
+
flash[:error] = "Document does not exist at the expected location."
|
31
|
+
redirect_to preview_document_path(@document)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def preview
|
36
|
+
# # otherwise looks for template for pdf, jpg or whatever
|
37
|
+
# params[:format] = 'html'
|
38
|
+
end
|
39
|
+
|
40
|
+
def index
|
41
|
+
@documents = Document.all
|
42
|
+
end
|
43
|
+
|
44
|
+
def new
|
45
|
+
@document = Document.new
|
46
|
+
end
|
47
|
+
|
48
|
+
def create
|
49
|
+
@document = Document.new(params[:document])
|
50
|
+
@document.save!
|
51
|
+
redirect_to preview_document_path(@document)
|
52
|
+
rescue ActiveRecord::RecordInvalid
|
53
|
+
flash.now[:error] = "Error"
|
54
|
+
render :action => 'new'
|
55
|
+
end
|
56
|
+
|
57
|
+
def update
|
58
|
+
@document.update_attributes!(params[:document])
|
59
|
+
redirect_to preview_document_path(@document)
|
60
|
+
rescue ActiveRecord::RecordInvalid
|
61
|
+
flash.now[:error] = "Error"
|
62
|
+
render :action => 'edit'
|
63
|
+
end
|
64
|
+
|
65
|
+
def destroy
|
66
|
+
@document.destroy
|
67
|
+
redirect_to documents_path
|
68
|
+
end
|
69
|
+
|
70
|
+
protected
|
71
|
+
|
72
|
+
def id_required
|
73
|
+
if !params[:id].blank? and Document.exists?(params[:id])
|
74
|
+
@document = Document.find(params[:id])
|
75
|
+
else
|
76
|
+
access_denied("Valid document id required!", documents_path)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def document_required
|
81
|
+
if !params[:id].blank? and Document.exists?(params[:id])
|
82
|
+
@document = Document.find(params[:id])
|
83
|
+
elsif !params[:id].blank? and Document.exists?(
|
84
|
+
:document_file_name => "#{params[:id]}.#{params[:format]}")
|
85
|
+
documents = Document.find(:all, :conditions => {
|
86
|
+
:document_file_name => "#{params[:id]}.#{params[:format]}"})
|
87
|
+
# Due to the unique index, there can be only one!
|
88
|
+
# if documents.length > 1
|
89
|
+
# access_denied("More than one document matches #{params[:id]}!",
|
90
|
+
# documents_path)
|
91
|
+
# else
|
92
|
+
@document=documents[0]
|
93
|
+
# end
|
94
|
+
else
|
95
|
+
access_denied("Valid document id required!", documents_path)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'hmac-sha1'
|
2
|
+
#
|
3
|
+
# http://amazon.rubyforge.org/
|
4
|
+
#
|
5
|
+
class Document < ActiveRecord::Base
|
6
|
+
belongs_to :owner, :polymorphic => true
|
7
|
+
|
8
|
+
validates_presence_of :title
|
9
|
+
validates_length_of :title, :minimum => 4
|
10
|
+
|
11
|
+
validates_uniqueness_of :document_file_name, :allow_nil => true
|
12
|
+
|
13
|
+
before_validation :nullify_blank_document_file_name
|
14
|
+
|
15
|
+
has_attached_file :document,
|
16
|
+
YAML::load(ERB.new(IO.read(File.expand_path(
|
17
|
+
File.join(File.dirname(__FILE__),'../..','config/document.yml')
|
18
|
+
))).result)[Rails.env]
|
19
|
+
|
20
|
+
def nullify_blank_document_file_name
|
21
|
+
self.document_file_name = nil if document_file_name.blank?
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
title
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<% content_tag_for( :tr, document, :class => 'row' ) do %>
|
2
|
+
<td class='title'>
|
3
|
+
<%= link_to document.title, preview_document_path(document) %>
|
4
|
+
</td>
|
5
|
+
<td class='path'>
|
6
|
+
<%= document.document_file_name %>
|
7
|
+
</td>
|
8
|
+
<td class='manage'>
|
9
|
+
<%= button_link_to 'Edit', edit_document_path(document) %>
|
10
|
+
<% destroy_link_to 'Destroy', document_path(document) do %>
|
11
|
+
<%= hidden_field_tag 'confirm', "Destroy document '#{document}'?",
|
12
|
+
:id => nil %>
|
13
|
+
<% end %>
|
14
|
+
</td>
|
15
|
+
<% end %><!-- class='document row' -->
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<% stylesheets('documents') %>
|
2
|
+
|
3
|
+
<%= f.wrapped_text_field :title %>
|
4
|
+
|
5
|
+
<div>
|
6
|
+
<div class='document'>
|
7
|
+
<%= f.wrapped_file_field :document %>
|
8
|
+
<% unless @document.new_record? -%>
|
9
|
+
(<%= @document.document.url -%>)
|
10
|
+
<% end -%><br />
|
11
|
+
</div>
|
12
|
+
</div>
|
13
|
+
<%= f.wrapped_text_area :abstract %>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<h2>Editing Document</h2>
|
2
|
+
|
3
|
+
<% form_for(@document,
|
4
|
+
:html => { :multipart => true }) do |f| %>
|
5
|
+
<%= f.error_messages %>
|
6
|
+
<%= render 'form',:f => f %>
|
7
|
+
<p>
|
8
|
+
<%= f.submit( "Update this Document" )%>
|
9
|
+
<%= button_link_to 'Preview this Document',
|
10
|
+
preview_document_path(@document) %>
|
11
|
+
<%= button_link_to 'Download this Document', @document %>
|
12
|
+
<%= button_link_to 'Back to Documents', documents_path %>
|
13
|
+
</p>
|
14
|
+
<% end %>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<% javascripts('simply_helpful') %>
|
2
|
+
<% stylesheets('documents') %>
|
3
|
+
|
4
|
+
<h2>Documents</h2>
|
5
|
+
<% if @documents.length > 0 %>
|
6
|
+
<table id='documents'><tbody>
|
7
|
+
<%= render :partial => 'document', :collection => @documents %>
|
8
|
+
</tbody></table><!-- id='documents' -->
|
9
|
+
<% else %>
|
10
|
+
Sorry, but no documents yet.
|
11
|
+
<% end %>
|
12
|
+
|
13
|
+
<p>
|
14
|
+
<%= button_link_to 'Create New Document', new_document_path %>
|
15
|
+
</p>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<h2>New Document</h2>
|
2
|
+
|
3
|
+
<% form_for(@document,
|
4
|
+
:html => { :multipart => true }) do |f| %>
|
5
|
+
<%= f.error_messages %>
|
6
|
+
<%= render 'form',:f => f %>
|
7
|
+
<p>
|
8
|
+
<%= f.submit( "Create new Document" )%>
|
9
|
+
<%= button_link_to 'Back to Documents', documents_path %>
|
10
|
+
</p>
|
11
|
+
<% end %>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<%# stylesheets('document') %>
|
2
|
+
|
3
|
+
<p>
|
4
|
+
<b>Title:</b>
|
5
|
+
<%=h @document.title %>
|
6
|
+
</p>
|
7
|
+
|
8
|
+
<p>
|
9
|
+
<b>Abstract:</b>
|
10
|
+
<%=h @document.abstract %>
|
11
|
+
</p>
|
12
|
+
|
13
|
+
<%= button_link_to 'Download this Document',
|
14
|
+
document_path(@document) %>
|
15
|
+
<%= button_link_to 'Edit this Document',
|
16
|
+
edit_document_path(@document) %>
|
17
|
+
<%= button_link_to 'Back to Documents', documents_path %>
|
data/config/document.yml
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
#DEFAULTS: &DEFAULTS
|
2
|
+
# :styles:
|
3
|
+
# :full: '900'
|
4
|
+
# :large: '800'
|
5
|
+
# :medium: '600'
|
6
|
+
# :small: '150x50'
|
7
|
+
|
8
|
+
# :attachment is the attachment name NOT the model name
|
9
|
+
# for document they are the same
|
10
|
+
|
11
|
+
<% common = "documents/:id/:filename" %>
|
12
|
+
|
13
|
+
#>> Rails.root.to_s.split('/')
|
14
|
+
#=> ["", "var", "lib", "tomcat5", "webapps", "clic", "WEB-INF"]
|
15
|
+
|
16
|
+
#>> Rails.root.to_s.split('/')
|
17
|
+
#=> ["", "Users", "jakewendt", "github_repo", "jakewendt", "ucb_ccls_clic"]
|
18
|
+
|
19
|
+
<%
|
20
|
+
app_name = ( defined?(RAILS_APP_NAME) ) ?
|
21
|
+
RAILS_APP_NAME :
|
22
|
+
Rails.root.to_s.split('/').reject{|x|x == "WEB-INF"}.last
|
23
|
+
%>
|
24
|
+
|
25
|
+
development:
|
26
|
+
:path: <%= "#{Rails.root}/development/#{common}" %>
|
27
|
+
# <<: *DEFAULTS
|
28
|
+
|
29
|
+
test:
|
30
|
+
:path: <%= "#{Rails.root}/test/#{common}" %>
|
31
|
+
# <<: *DEFAULTS
|
32
|
+
|
33
|
+
#production:
|
34
|
+
# :path: <%= "/home/tomcat/#{app_name}/:attachment/:id/:filename" %>
|
35
|
+
## # <<: *DEFAULTS
|
36
|
+
|
37
|
+
production:
|
38
|
+
# Set the storage class to RRS which is cheaper than
|
39
|
+
# the default of STANDARD
|
40
|
+
:s3_headers:
|
41
|
+
x-amz-storage-class: REDUCED_REDUNDANCY
|
42
|
+
# public_read or private
|
43
|
+
:s3_permissions: :private
|
44
|
+
:storage: :s3
|
45
|
+
:s3_protocol: https
|
46
|
+
:s3_credentials: <%="#{Rails.root}/config/s3.yml" %>
|
47
|
+
:bucket: <%= app_name %>
|
48
|
+
# common has a : as the first char so it needs special care
|
49
|
+
# or the string will magically be turned into a symbol
|
50
|
+
# which isn't what we want
|
51
|
+
# Not anymore.
|
52
|
+
:path: <%= common %>
|
53
|
+
# S3 must have a defined path or will generate
|
54
|
+
# "Stack level too deep" errors
|
data/config/routes.rb
ADDED
File without changes
|
@@ -0,0 +1,87 @@
|
|
1
|
+
class SimplyDocumentsGenerator < Rails::Generator::Base
|
2
|
+
|
3
|
+
def manifest
|
4
|
+
# See Rails::Generator::Commands::Create
|
5
|
+
# rails-2.3.10/lib/rails_generator/commands.rb
|
6
|
+
# for code methods for record (Manifest)
|
7
|
+
record do |m|
|
8
|
+
m.directory('config/autotest')
|
9
|
+
m.file('autotest_simply_documents.rb', 'config/autotest/simply_documents.rb')
|
10
|
+
m.directory('lib/tasks')
|
11
|
+
m.file('simply_documents.rake', 'lib/tasks/simply_documents.rake')
|
12
|
+
|
13
|
+
# File.open('Rakefile','a'){|f|
|
14
|
+
# f.puts <<-EOF
|
15
|
+
## From `script/generate simply_documents` ...
|
16
|
+
#require 'simply_documents/test_tasks'
|
17
|
+
# EOF
|
18
|
+
# }
|
19
|
+
#
|
20
|
+
# File.open('.autotest','a'){|f|
|
21
|
+
# f.puts <<-EOF
|
22
|
+
## From `script/generate simply_documents` ...
|
23
|
+
#require 'simply_documents/autotest'
|
24
|
+
# EOF
|
25
|
+
# }
|
26
|
+
|
27
|
+
%w( create_documents
|
28
|
+
add_attachments_document_to_document
|
29
|
+
polymorphicize_document_owner
|
30
|
+
).each do |migration|
|
31
|
+
m.migration_template "migrations/#{migration}.rb",
|
32
|
+
'db/migrate', :migration_file_name => migration
|
33
|
+
end
|
34
|
+
|
35
|
+
m.directory('public/javascripts')
|
36
|
+
Dir["#{File.dirname(__FILE__)}/templates/javascripts/*js"].each{|file|
|
37
|
+
f = file.split('/').slice(-2,2).join('/')
|
38
|
+
m.file(f, "public/javascripts/#{File.basename(file)}")
|
39
|
+
}
|
40
|
+
m.directory('public/stylesheets')
|
41
|
+
Dir["#{File.dirname(__FILE__)}/templates/stylesheets/*css"].each{|file|
|
42
|
+
f = file.split('/').slice(-2,2).join('/')
|
43
|
+
m.file(f, "public/stylesheets/#{File.basename(file)}")
|
44
|
+
}
|
45
|
+
# m.directory('test/functional/documents')
|
46
|
+
# Dir["#{File.dirname(__FILE__)}/templates/functional/*rb"].each{|file|
|
47
|
+
# f = file.split('/').slice(-2,2).join('/')
|
48
|
+
# m.file(f, "test/functional/documents/#{File.basename(file)}")
|
49
|
+
# }
|
50
|
+
# m.directory('test/unit/documents')
|
51
|
+
# Dir["#{File.dirname(__FILE__)}/templates/unit/*rb"].each{|file|
|
52
|
+
# f = file.split('/').slice(-2,2).join('/')
|
53
|
+
# m.file(f, "test/unit/documents/#{File.basename(file)}")
|
54
|
+
# }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
module Rails::Generator::Commands
|
60
|
+
class Create
|
61
|
+
def migration_template(relative_source,
|
62
|
+
relative_destination, template_options = {})
|
63
|
+
migration_directory relative_destination
|
64
|
+
migration_file_name = template_options[
|
65
|
+
:migration_file_name] || file_name
|
66
|
+
if migration_exists?(migration_file_name)
|
67
|
+
puts "Another migration is already named #{migration_file_name}: #{existing_migrations(migration_file_name).first}: Skipping"
|
68
|
+
else
|
69
|
+
template(relative_source, "#{relative_destination}/#{next_migration_string}_#{migration_file_name}.rb", template_options)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end # Create
|
73
|
+
class Base
|
74
|
+
protected
|
75
|
+
# the loop through migrations happens so fast
|
76
|
+
# that they all have the same timestamp which
|
77
|
+
# won't work when you actually try to migrate.
|
78
|
+
# All the timestamps MUST be unique.
|
79
|
+
def next_migration_string(padding = 3)
|
80
|
+
@s = (!@s.nil?)? @s.to_i + 1 : if ActiveRecord::Base.timestamped_migrations
|
81
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
82
|
+
else
|
83
|
+
"%.#{padding}d" % next_migration_number
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end # Base
|
87
|
+
end
|