siterest 0.1.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/Gemfile +9 -0
  2. data/Gemfile.lock +38 -0
  3. data/Rakefile +23 -0
  4. data/VERSION +1 -0
  5. data/bin/siterest +10 -0
  6. data/config.ru +6 -0
  7. data/lib/encoded_attachment/.gitignore +7 -0
  8. data/lib/encoded_attachment/Gemfile +11 -0
  9. data/lib/encoded_attachment/LICENSE +20 -0
  10. data/lib/encoded_attachment/README.md +107 -0
  11. data/lib/encoded_attachment/Rakefile +41 -0
  12. data/lib/encoded_attachment/encoded_attachment.gemspec +23 -0
  13. data/lib/encoded_attachment/lib/activerecord/base.rb +63 -0
  14. data/lib/encoded_attachment/lib/activeresource/base.rb +121 -0
  15. data/lib/encoded_attachment/lib/activeresource/connection.rb +7 -0
  16. data/lib/encoded_attachment/lib/encoded_attachment/version.rb +3 -0
  17. data/lib/encoded_attachment/lib/encoded_attachment.rb +47 -0
  18. data/lib/encoded_attachment/test/active_record_test.rb +136 -0
  19. data/lib/encoded_attachment/test/active_resource_test.rb +276 -0
  20. data/lib/encoded_attachment/test/avatars/.gitignore +0 -0
  21. data/lib/encoded_attachment/test/config/database.yml +19 -0
  22. data/lib/encoded_attachment/test/config/schema.rb +17 -0
  23. data/lib/encoded_attachment/test/fixtures/kitten.jpg +0 -0
  24. data/lib/encoded_attachment/test/fixtures/tapir.jpg +0 -0
  25. data/lib/encoded_attachment/test/test_helper.rb +73 -0
  26. data/lib/siterest/asset.rb +27 -0
  27. data/lib/siterest/client.rb +149 -0
  28. data/lib/siterest/command.rb +105 -0
  29. data/lib/siterest/server.rb +58 -0
  30. data/lib/siterest/site.rb +6 -0
  31. data/lib/siterest/template/filters/core_filters.rb +57 -0
  32. data/lib/siterest/template/filters/datetime_filters.rb +8 -0
  33. data/lib/siterest/template/filters/url_filters.rb +82 -0
  34. data/lib/siterest/template/objects/article.rb +35 -0
  35. data/lib/siterest/template/objects/page.rb +71 -0
  36. data/lib/siterest/template/objects/site.rb +51 -0
  37. data/lib/siterest/template.rb +6 -0
  38. data/lib/siterest/user.rb +6 -0
  39. data/lib/siterest.rb +56 -0
  40. data/lib/upfile.rb +51 -0
  41. data/readme.md +86 -0
  42. data/site/data/articles/2008-04-24-my-first-blog-post.md +12 -0
  43. data/site/data/pages/about-us/something.md +0 -0
  44. data/site/data/pages/about-us.md +12 -0
  45. data/site/data/pages/contact.md +12 -0
  46. data/site/data/pages/home.md +14 -0
  47. data/site/data/site.yaml +2 -0
  48. data/siterest.gemspec +101 -0
  49. metadata +203 -0
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "http://rubygems.org"
2
+ gem 'h2o'
3
+ gem 'activeresource', '~> 3.0.0.beta4'
4
+ gem 'launchy'
5
+ gem 'sinatra'
6
+ gem 'mime-types', :require => 'mime/types'
7
+ gem 'rest-client'
8
+ gem 'rdiscount'
9
+ # gem 'encoded_attachment', :git => 'http://github.com/nragaz/encoded_attachment.git'
data/Gemfile.lock ADDED
@@ -0,0 +1,38 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activemodel (3.0.0.rc)
5
+ activesupport (= 3.0.0.rc)
6
+ builder (~> 2.1.2)
7
+ i18n (~> 0.4.1)
8
+ activeresource (3.0.0.rc)
9
+ activemodel (= 3.0.0.rc)
10
+ activesupport (= 3.0.0.rc)
11
+ activesupport (3.0.0.rc)
12
+ builder (2.1.2)
13
+ configuration (1.1.0)
14
+ h2o (0.2)
15
+ i18n (0.4.1)
16
+ launchy (0.3.5)
17
+ configuration (>= 0.0.5)
18
+ rake (>= 0.8.1)
19
+ mime-types (1.16)
20
+ rack (1.2.1)
21
+ rake (0.8.7)
22
+ rdiscount (1.6.5)
23
+ rest-client (1.4.2)
24
+ mime-types (>= 1.16)
25
+ sinatra (1.0)
26
+ rack (>= 1.0)
27
+
28
+ PLATFORMS
29
+ ruby
30
+
31
+ DEPENDENCIES
32
+ activeresource (~> 3.0.0.beta4)
33
+ h2o
34
+ launchy
35
+ mime-types
36
+ rdiscount
37
+ rest-client
38
+ sinatra
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+
2
+ begin
3
+ require 'jeweler'
4
+ Jeweler::Tasks.new do |s|
5
+ s.name = "siterest"
6
+ s.summary = "Siterest client"
7
+ s.description = "Simple content service"
8
+ s.email = "taylor.luk@idealian.net"
9
+ s.homepage = "http://www.siterest.com"
10
+ s.authors = ["Taylor luk"]
11
+ s.add_dependency 'h2o'
12
+ s.add_dependency 'activeresource', '~> 3.0.0.beta4'
13
+ s.add_dependency 'launchy'
14
+ s.add_dependency 'sinatra'
15
+ s.add_dependency 'rest-client'
16
+ s.add_dependency 'rdiscount'
17
+ end
18
+ rescue LoadError
19
+ puts "Jeweler not available. Install it with: gem install jeweler"
20
+ end
21
+
22
+ desc "Default task is to run specs"
23
+ task :default => :spec
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0.pre1
data/bin/siterest ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
4
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
5
+
6
+ require 'siterest'
7
+ require 'siterest/command'
8
+
9
+ Siterest::Command.new(STDIN, STDOUT, *ARGV).run!
10
+
data/config.ru ADDED
@@ -0,0 +1,6 @@
1
+ lib = File.expand_path(File.dirname(__FILE__) + '/lib')
2
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
3
+
4
+ require 'siterest'
5
+
6
+ run Siterest::Server
@@ -0,0 +1,7 @@
1
+ .bundle
2
+ .rvmrc
3
+ .DS_Store
4
+ test/db/*.*
5
+ test/log/*.*
6
+ test/avatars/**/*
7
+ *.gem
@@ -0,0 +1,11 @@
1
+ source :gemcutter
2
+
3
+ gem "encoded_attachment", :path => File.expand_path("..", __FILE__)
4
+
5
+ gem "mime-types", :require => 'mime/types'
6
+ gem "sqlite3-ruby", :require => 'sqlite3'
7
+
8
+ gem "activerecord", :git => "git://github.com/rails/rails", :require => "active_record"
9
+ gem "activeresource", :git => "git://github.com/rails/rails", :require => "active_resource"
10
+ gem "activesupport", :git => "git://github.com/rails/rails", :require => "active_support"
11
+ gem "paperclip"
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Nick Ragaz
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.
@@ -0,0 +1,107 @@
1
+ EncodedAttachment
2
+ =================
3
+
4
+ This is the bestest and certainly the easiest way to handle file uploads/downloads to [Paperclip](http://github.com/thoughtbot/paperclip)-using Active Record-backed resources using Active Resource.
5
+
6
+ Rather than trying to create a multipart form submission, it just embeds the file's binary data in the Active Record model's <tt>to_xml</tt>. You can also embed binary data into XML to POST or PUT using Active Resource. These tags will automatically be parsed by Active Record and Active Resource to create files.
7
+
8
+
9
+ Usage
10
+ -----
11
+
12
+ In a Rails application:
13
+
14
+ # Gemfile
15
+ gem "encoded_attachment", :git => "git://github.com/nragaz/encoded_attachment"
16
+
17
+ This will load the class methods into both ActiveRecord and ActiveResource. Nothing will really "happen" unless you use the methods described below in your models.
18
+
19
+ Note that the ActiveRecord code is designed to be used with [Paperclip](http://github.com/thoughtbot/paperclip).
20
+
21
+ Outside of Rails, the gem can be required directly. It will load itself into ActiveRecord::Base and/or ActiveResource::Base if they have already been loaded. (You can manually include the needed methods using <tt>EncodedAttachment.setup_activerecord</tt> and <tt>EncodedAttachment.setup_activeresource</tt> if you really want to require this gem first.)
22
+
23
+
24
+ Functionality
25
+ =============
26
+
27
+ Active Record
28
+ -------------
29
+
30
+ Adds a class method called <tt>encode_attachment_in_xml</tt> to Active Record that can be used alongside Paperclip's <tt>has_attached_file</tt> to automatically generate useful and usable binary XML tags for the attachment's original file by wrapping <tt>to_xml</tt>.
31
+
32
+ These tags will not be generated on new or destroyed records (because the Paperclip file needs to be saved to disk before it is encoded). You can disable file generation at any time using <tt>to_xml(:include_attachments => false)</tt>.
33
+
34
+ Note that by default, the XML will *not* include Paperclip attributes such as <tt>attachment_file_name</tt>, <tt>attachment_file_size</tt>, <tt>attachment_content_type</tt> and <tt>attachment_updated_at</tt>. The file name and content type are in the XML tag as attributes. Using <tt>to_xml(:include_attachments => false)</tt> will restore these attributes to your XML.
35
+
36
+
37
+ Active Resource
38
+ ---------------
39
+
40
+ Adds a class method called <tt>has_encoded_attachment</tt> to Active Resource that generates a schema for the file's attributes and then embeds the file's binary content in <tt>to_xml</tt> if the file has been changed or the record is new.
41
+
42
+ You can force embedding using <tt>to_xml(:include_attachments => true)</tt>. File setters include <tt>file=</tt> and <tt>file_path=</tt>. MIME types are detected based on the file name.
43
+
44
+
45
+ Downloading Files using URLs
46
+ ----------------------------
47
+
48
+ To avoid transmitting huge XML files (particularly in index actions), you can choose to have Active Record send the URL of the file instead of the encoded path using:
49
+
50
+ encode_attachment_in_xml :attachment_name, :send_urls => true, :root_url => "http://yourdomain"
51
+
52
+ <tt>:root_url</tt> is optional.
53
+
54
+ You can force the file's binary data to be embedded using <tt>to_xml(:encode_attachments => true)</tt>.
55
+
56
+ The URL will be downloaded separately by the Active Resource object using the same protocol settings as its native connection (e.g. authentication will be preserved).
57
+
58
+ There are some limitations to this: your file URL must be on the same domain as the resource's base URL, and the URL must include the file name and extension (e.g. "/images/*rails.png*") for MIME type and file name detection.
59
+
60
+ There is no support for Active Resource submitting a file URL back to Active Record. Using the <tt>file=</tt> or <tt>file_path=</tt> methods on your Active Resource object will obliterate the <tt>file_url</tt> attribute so that it doesn't appear in your PUT.
61
+
62
+ Potential use cases include:
63
+
64
+ class MyModel < ActiveRecord::Base
65
+ encode_attachment_in_xml :my_file, :send_urls => true, :root_url => "http://yourdomain"
66
+ end
67
+
68
+ class MyModelsController < ActionController::Base
69
+ def index
70
+ MyModel.all.to_xml # sends URLs
71
+ end
72
+
73
+ def show
74
+ MyModel.find(params[:id]).to_xml(:encode_attachments => true) # sends encoded files
75
+ end
76
+ end
77
+
78
+
79
+ Example
80
+ =======
81
+
82
+ In Active Record:
83
+
84
+ class MyModel < ActiveRecord::Base
85
+ has_attached_file :pdf
86
+ encode_attachment_in_xml :pdf
87
+ end
88
+
89
+ my_model = MyModel.create(:pdf => File.open('example.pdf'))
90
+ my_model.to_xml => '<my-model>\n<pdf type="file" name="example.pdf" content-type="application/pdf">[binary data]</pdf>\n</my-model>'
91
+
92
+
93
+ In Active Resource:
94
+
95
+ class MyModelResource < ActiveResource::Base
96
+ self.element_name = "my_model"
97
+
98
+ has_encoded_attachment :pdf
99
+ end
100
+
101
+ my_model_resource = MyModelResource.new.from_xml(my_model.to_xml)
102
+ my_model_resource.pdf # => <StringIO> containing binary data
103
+ my_model_resource.save_pdf_as("my_downloaded_file.pdf")
104
+
105
+ my_model_resource.pdf = File.open('example-downloaded.pdf')
106
+ my_model_resource.pdf_file_name # => "example_downloaded.pdf"
107
+ my_model_resource.pdf_content_type # => "application/pdf"
@@ -0,0 +1,41 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Run unit tests'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.libs << 'test'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ t.verbose = true
14
+ end
15
+
16
+ desc 'Generate documentation'
17
+ Rake::RDocTask.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'EncodedAttachment'
20
+ rdoc.options << '--line-numbers' << '--inline-source'
21
+ rdoc.rdoc_files.include('README')
22
+ rdoc.rdoc_files.include('lib/**/*.rb')
23
+ end
24
+
25
+ namespace :gem do
26
+ desc 'Build gem'
27
+ task :build => :cleanup do
28
+ system "gem build encoded_attachment.gemspec"
29
+ end
30
+
31
+ desc 'Build and install gem'
32
+ task :install => :build do
33
+ require 'lib/encoded_attachment/version'
34
+ system "gem install encoded_attachment-#{EncodedAttachment::VERSION}.gem"
35
+ end
36
+
37
+ desc 'Remove built gem(s)'
38
+ task :cleanup do
39
+ system 'rm encoded_attachment-*.gem'
40
+ end
41
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path("../lib/encoded_attachment/version", __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "encoded_attachment"
5
+ s.version = EncodedAttachment::VERSION
6
+ s.platform = Gem::Platform::RUBY
7
+ s.authors = ["Nick Ragaz"]
8
+ s.email = ["nick.ragaz@gmail.com"]
9
+ s.homepage = "http://github.com/nragaz/encoded_attachment"
10
+ s.summary = "Handles downloading and uploading Paperclip attachments using Active Record and Active Resource"
11
+ s.description = "Adds methods to ActiveRecord::Base and ActiveResource::Base to transmit file attachments via REST, either as binary tags in XML or via a separate URL"
12
+
13
+ s.required_rubygems_version = ">= 1.3.6"
14
+ s.rubyforge_project = "encoded_attachment"
15
+
16
+ s.add_dependency "mime-types"
17
+ # s.add_dependency "paperclip", "~> 2.3"
18
+ # s.add_dependency "activerecord", "~> 2.3"
19
+ # s.add_dependency "activeresource", "~> 2.3"
20
+
21
+ s.files = Dir["{lib}/**/*.rb", "LICENSE", "*.md"]
22
+ s.require_path = 'lib'
23
+ end
@@ -0,0 +1,63 @@
1
+ module EncodedAttachment
2
+ module ActiveRecordClassMethods
3
+ def encode_attachment_in_xml(name, attachment_options={})
4
+ attachment_options[:send_urls] = false unless attachment_options[:send_urls]
5
+
6
+ @_attachment_handling ||= {}
7
+ @_attachment_handling[name] = {}
8
+ @_attachment_handling[name][:send_urls] = attachment_options[:send_urls]
9
+ @_attachment_handling[name][:root_url] = attachment_options[:root_url] || nil
10
+
11
+ if attachment_options[:send_urls]
12
+ # Placeholder method to avoid MethodMissing exceptions on Model.from_xml(Model.to_xml)
13
+ define_method "#{name}_url=" do |file_url|
14
+ nil
15
+ end
16
+ end
17
+
18
+ define_method "to_xml_with_encoded_#{name}" do |*args|
19
+ # You can exclude file tags completely by using :include_attachments => false
20
+ # If :send_urls => true, force file encoding using :encode => true
21
+ options, block = args
22
+
23
+ options ||= {}
24
+ options[:include_attachments] = true unless options.has_key?(:include_attachments)
25
+ options[:encode_attachments] = false unless options.has_key?(:encode_attachments)
26
+ options[:procs] ||= []
27
+ if options[:include_attachments]
28
+ # strip Paperclip methods
29
+ options[:except] ||= []
30
+ options[:except] = (options[:except] + [:"#{name}_file_name", :"#{name}_file_size",
31
+ :"#{name}_content_type", :"#{name}_updated_at"]).uniq
32
+
33
+ # get URL handling variables if :send_urls => true
34
+ send_urls = send(:class).instance_variable_get("@_attachment_handling")[name][:send_urls]
35
+ root_url = send(:class).instance_variable_get("@_attachment_handling")[name][:root_url] if send_urls
36
+
37
+ options[:procs] << Proc.new { |options, record|
38
+ file_options = { :type => 'file'}
39
+ if !(new_record? || frozen?) && send(name).file? && (!(send_urls) || options[:encode_attachments])
40
+ file_options.merge! :name => send("#{name}_file_name"), :"content-type" => send("#{name}_content_type")
41
+ options[:builder].tag!(name, file_options) { options[:builder].cdata! EncodedAttachment.encode(send(name)) }
42
+ elsif !(new_record? || frozen?) && send(name).file? && send_urls
43
+ file_options.merge! :type => :string
44
+ url = root_url ? URI.join(root_url, send(name).url(:original, false)) : send(name).url(:original, false)
45
+ options[:builder].tag! "#{name}_url", url, file_options
46
+ elsif send_urls && (new_record? || frozen? || !(send(name).file?))
47
+ file_options.merge! :type => :string, :nil => true
48
+ options[:builder].tag! "#{name}_url", nil, file_options
49
+ else
50
+ # the file can't be included if the record is not persisted yet, because of how Paperclip works
51
+ file_options.merge! :nil => true
52
+ options[:builder].tag! name, "", file_options
53
+ end
54
+ }
55
+ end
56
+
57
+ send("to_xml_without_encoded_#{name}", options, &block)
58
+ end
59
+
60
+ alias_method_chain :to_xml, :"encoded_#{name}"
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,121 @@
1
+ module EncodedAttachment
2
+ module ActiveResourceClassMethods
3
+ def has_encoded_attachment(name)
4
+ schema do
5
+ string "#{name}_file_name", "#{name}_content_type"
6
+ integer "#{name}_file_size"
7
+ attribute "#{name}_updated_at", "string"
8
+ attribute name, "string"
9
+ end
10
+
11
+ define_method "#{name}_updated_at" do
12
+ Time.parse(attributes["#{name}_updated_at"]) if attributes["#{name}_updated_at"].is_a?(String)
13
+ end
14
+
15
+ define_method "to_xml_with_encoded_#{name}" do |*args|
16
+ # Normally, the file's XML is only included if the file has been changed in the resource
17
+ # using file= or file_path= or file_url=
18
+ # You can force file tag generation (i.e. even if the file has not changed) by using to_xml(:include_files => true)
19
+ options, block = args
20
+
21
+ options ||= {}
22
+ options[:except] ||= []
23
+ options[:except] = (options[:except] + [:id, :path, :"#{name}", :"#{name}_updated_at", :"#{name}_file_size"]).uniq
24
+ options[:except] = (options[:except] + [:"#{name}_file_name", :"#{name}_content_type"]).uniq unless send("#{name}_changed?")
25
+ options[:procs] ||= []
26
+
27
+ options[:procs] << Proc.new { |options, record|
28
+ file_options = { :type => 'file'}
29
+ if send("#{name}_changed?") || options[:include_files] || (new_record? && !(send("#{name}").nil?))
30
+ file_options.merge! :name => send("#{name}_file_name"), :"content-type" => send("#{name}_content_type")
31
+ options[:builder].tag!(name, file_options) { options[:builder].cdata! EncodedAttachment.encode_io(send(name)) }
32
+ elsif send("#{name}_changed?") || options[:include_files]
33
+ file_options.merge! :nil => true
34
+ options[:builder].tag! name, "", file_options
35
+ end
36
+ }
37
+
38
+ send "to_xml_without_encoded_#{name}", options, &block
39
+ end
40
+ alias_method_chain :to_xml, :"encoded_#{name}"
41
+
42
+ define_method "load_with_attached_#{name}" do |attrs|
43
+ attrs = attrs.stringify_keys
44
+ if attrs.has_key?("#{name}")
45
+ send "#{name}=", attrs.delete("#{name}"), @attributes.has_key?(name)
46
+ elsif attrs.has_key?("#{name}_url")
47
+ send "#{name}_url=", attrs.delete("#{name}_url"), @attributes.has_key?(name)
48
+ end
49
+ send "load_without_attached_#{name}", attrs
50
+ end
51
+ alias_method_chain :load, :"attached_#{name}"
52
+
53
+ # Prevents someone from assigning the attachment attributes directly and skipping the handling methods
54
+ define_method "attributes=" do |attrs|
55
+ send :load, attrs
56
+ end
57
+
58
+ define_method "#{name}_changed=" do |bool|
59
+ instance_variable_set("@#{name}_changed", bool)
60
+ end
61
+
62
+ define_method "#{name}_changed?" do
63
+ instance_variable_get("@#{name}_changed") || false
64
+ end
65
+
66
+ define_method "#{name}_path=" do |file_path|
67
+ send "#{name}=", File.open(file_path)
68
+ send "#{name}_file_name=", File.basename(file_path)
69
+ send "#{name}_content_type=", MIME::Types.type_for(File.basename(file_path)).first.content_type
70
+ end
71
+
72
+ define_method "#{name}_url=" do |*args|
73
+ file_url, changed = args
74
+ changed = (changed.nil? || changed) ? true : false
75
+ if file_url
76
+ url = URI.parse(file_url.to_s)
77
+ content_type = MIME::Types.type_for(File.basename(url.path)).first.content_type
78
+
79
+ io = StringIO.new(connection.get_attachment(url.path, 'Accept' => content_type))
80
+ io.original_filename = File.basename(url.path)
81
+ io.content_type = content_type
82
+
83
+ send "#{name}=", io, changed
84
+ else
85
+ send "#{name}=", nil, changed
86
+ end
87
+ end
88
+
89
+ define_method "#{name}=" do |*args|
90
+ io, changed = args
91
+ changed = (changed.nil? || changed) ? true : false
92
+ attributes[name] = io
93
+ if io.respond_to?(:original_filename)
94
+ send "#{name}_file_name=", io.original_filename
95
+ send "#{name}_content_type=", MIME::Types.type_for(io.original_filename).first.content_type
96
+ elsif io.nil?
97
+ send "#{name}_file_name=", nil
98
+ send "#{name}_content_type=", nil
99
+ end
100
+ attributes.delete "#{name}_url"
101
+ attributes.delete "#{name}_file_size"
102
+ attributes.delete "#{name}_updated_at"
103
+ send "#{name}_changed=", changed
104
+ end
105
+
106
+ define_method "save_#{name}_as" do |*args|
107
+ raise "File not set - cannot be saved" if attributes[name].nil? || !(attributes[name].respond_to?(:read))
108
+ path, overwrite = args
109
+ overwrite = true if overwrite.nil?
110
+ unless !(overwrite) && File.exist?(path)
111
+ send(name).pos = 0
112
+ File.open(path, 'w') { |f| f << send(name).read }
113
+ return true
114
+ else
115
+ raise "File not saved - file already exists at #{path}"
116
+ end
117
+ end
118
+ end
119
+
120
+ end
121
+ end
@@ -0,0 +1,7 @@
1
+ module EncodedAttachment
2
+ module ActiveResourceConnectionMethods
3
+ def get_attachment(path, headers = {})
4
+ with_auth { request(:get, path, build_request_headers(headers, :get, self.site.merge(path))).body }
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module EncodedAttachment
2
+ VERSION = "0.1.7" unless defined? EncodedAttachment::VERSION
3
+ end
@@ -0,0 +1,47 @@
1
+ require 'base64'
2
+
3
+ module EncodedAttachment
4
+ class << self
5
+ def encode(attachment, style = :original)
6
+ encode_io( File.open(attachment.path(style)) )
7
+ end
8
+
9
+ def encode_io(io)
10
+ io.pos = 0
11
+ Base64.encode64(io.read)
12
+ end
13
+
14
+ def setup_activerecord
15
+ require File.dirname(__FILE__) + '/activerecord/base'
16
+ ActiveRecord::Base.extend ActiveRecordClassMethods
17
+ end
18
+
19
+ def setup_activeresource
20
+ require File.dirname(__FILE__) + '/activeresource/base'
21
+ require File.dirname(__FILE__) + '/activeresource/connection'
22
+ ActiveResource::Base.extend ActiveResourceClassMethods
23
+ ActiveResource::Connection.send :include, ActiveResourceConnectionMethods
24
+ end
25
+ end
26
+ end
27
+
28
+ # Initialization
29
+ if defined?(Rails::Railtie)
30
+ ActiveSupport.on_load(:active_record) do
31
+ EncodedAttachment.setup_activerecord
32
+ end
33
+
34
+ ActiveSupport.on_load(:active_resource) do
35
+ EncodedAttachment.setup_activeresource
36
+ end
37
+
38
+ ActiveSupport.on_load(:before_initialize) do
39
+ # workaround until above load hook works
40
+ EncodedAttachment.setup_activeresource \
41
+ unless !defined?(ActiveResource) || ActiveResource::Base.methods.include?('has_encoded_attachment')
42
+ end
43
+ else
44
+ # Load right away if required outside of Rails initialization
45
+ EncodedAttachment.setup_activerecord if defined?(ActiveRecord)
46
+ EncodedAttachment.setup_activeresource if defined?(ActiveResource)
47
+ end