From c6882bae3c6de74f98e985e14c75512458a951ce Mon Sep 17 00:00:00 2001 From: Espen Antonsen Date: Fri, 22 May 2009 22:38:52 +0200 Subject: [PATCH] tagging. princely --- app/models/album.rb | 11 ++- app/models/photo.rb | 13 ++++ app/models/photo_tag.rb | 4 + app/models/tag.rb | 4 + db/migrate/20090522190515_create_tags.rb | 12 +++ .../20090522190622_create_photo_tags.rb | 13 ++++ db/schema.rb | 15 +++- test/fixtures/photo_tags.yml | 7 ++ test/fixtures/tags.yml | 7 ++ test/unit/photo_tag_test.rb | 8 ++ test/unit/tag_test.rb | 8 ++ vendor/plugins/princely/MIT-LICENSE | 20 +++++ vendor/plugins/princely/README | 50 +++++++++++++ vendor/plugins/princely/Rakefile | 15 ++++ vendor/plugins/princely/init.rb | 6 ++ vendor/plugins/princely/lib/pdf_helper.rb | 55 ++++++++++++++ vendor/plugins/princely/lib/prince.rb | 75 +++++++++++++++++++ 17 files changed, 321 insertions(+), 2 deletions(-) create mode 100644 app/models/photo_tag.rb create mode 100644 app/models/tag.rb create mode 100644 db/migrate/20090522190515_create_tags.rb create mode 100644 db/migrate/20090522190622_create_photo_tags.rb create mode 100644 test/fixtures/photo_tags.yml create mode 100644 test/fixtures/tags.yml create mode 100644 test/unit/photo_tag_test.rb create mode 100644 test/unit/tag_test.rb create mode 100644 vendor/plugins/princely/MIT-LICENSE create mode 100644 vendor/plugins/princely/README create mode 100644 vendor/plugins/princely/Rakefile create mode 100644 vendor/plugins/princely/init.rb create mode 100644 vendor/plugins/princely/lib/pdf_helper.rb create mode 100644 vendor/plugins/princely/lib/prince.rb diff --git a/app/models/album.rb b/app/models/album.rb index a2bde29..b423feb 100644 --- a/app/models/album.rb +++ b/app/models/album.rb @@ -1,6 +1,15 @@ class Album < ActiveRecord::Base - has_many :photos + has_many :photos, :dependent => :destroy validates_uniqueness_of :path, :message => "Album already exsists on disc" + + before_destroy :destroy_directory + private + + def destroy_directory + #puts "DELETE DIRECTORY " + APP_CONFIG[:photos_path] + self.path + #Dir.delete( APP_CONFIG[:photos_path] + self.path + "/" ) if File.exists?( APP_CONFIG[:photos_path] + self.path ) + #Dir.delete( APP_CONFIG[:thumbs_path] + self.path ) if File.exists?( APP_CONFIG[:thumbs_path] + self.path ) + end end diff --git a/app/models/photo.rb b/app/models/photo.rb index aa7c516..c732266 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -1,5 +1,18 @@ class Photo < ActiveRecord::Base belongs_to :album + has_many :photo_tags, :dependent => :destroy + has_many :tags, :through => :photo_tags validates_uniqueness_of :path, :message => "Photo already exsists on disc" + + before_destroy :destroy_file + + private + + def destroy_file + puts "DELETE FILE " + APP_CONFIG[:photos_path] + self.path + File.delete( APP_CONFIG[:photos_path] + self.path ) if File.exists?( APP_CONFIG[:photos_path] + self.path ) + File.delete( APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_small" + File.extname( APP_CONFIG[:photos_path] + self.path ) ) if File.exists?( APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_small" + File.extname( APP_CONFIG[:photos_path] + self.path ) ) + File.delete( APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_large" + File.extname( APP_CONFIG[:photos_path] + self.path ) ) if File.exists?( APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_large" + File.extname( APP_CONFIG[:photos_path] + self.path ) ) + end end diff --git a/app/models/photo_tag.rb b/app/models/photo_tag.rb new file mode 100644 index 0000000..1d34668 --- /dev/null +++ b/app/models/photo_tag.rb @@ -0,0 +1,4 @@ +class PhotoTag < ActiveRecord::Base + belongs_to :tag + belongs_to :photo +end diff --git a/app/models/tag.rb b/app/models/tag.rb new file mode 100644 index 0000000..0cb1278 --- /dev/null +++ b/app/models/tag.rb @@ -0,0 +1,4 @@ +class Tag < ActiveRecord::Base + has_many :photo_tags + has_many :photos, :through => :photo_tags +end diff --git a/db/migrate/20090522190515_create_tags.rb b/db/migrate/20090522190515_create_tags.rb new file mode 100644 index 0000000..0064c57 --- /dev/null +++ b/db/migrate/20090522190515_create_tags.rb @@ -0,0 +1,12 @@ +class CreateTags < ActiveRecord::Migration + def self.up + create_table :tags do |t| + t.string :title, :length => 150, :null => false + t.timestamps + end + end + + def self.down + drop_table :tags + end +end diff --git a/db/migrate/20090522190622_create_photo_tags.rb b/db/migrate/20090522190622_create_photo_tags.rb new file mode 100644 index 0000000..7d8b292 --- /dev/null +++ b/db/migrate/20090522190622_create_photo_tags.rb @@ -0,0 +1,13 @@ +class CreatePhotoTags < ActiveRecord::Migration + def self.up + create_table :photo_tags do |t| + t.references :tag + t.references :photo + t.timestamps + end + end + + def self.down + drop_table :photo_tags + end +end diff --git a/db/schema.rb b/db/schema.rb index 25613bd..2adb275 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -9,7 +9,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20090522131931) do +ActiveRecord::Schema.define(:version => 20090522190622) do create_table "albums", :force => true do |t| t.string "title", :null => false @@ -19,6 +19,13 @@ ActiveRecord::Schema.define(:version => 20090522131931) do t.text "path" end + create_table "photo_tags", :force => true do |t| + t.integer "tag_id" + t.integer "photo_id" + t.datetime "created_at" + t.datetime "updated_at" + end + create_table "photos", :force => true do |t| t.string "title", :null => false t.text "description" @@ -28,6 +35,12 @@ ActiveRecord::Schema.define(:version => 20090522131931) do t.text "path" end + create_table "tags", :force => true do |t| + t.string "title", :null => false + t.datetime "created_at" + t.datetime "updated_at" + end + create_table "users", :force => true do |t| t.string "email", :null => false t.string "crypted_password", :null => false diff --git a/test/fixtures/photo_tags.yml b/test/fixtures/photo_tags.yml new file mode 100644 index 0000000..5bf0293 --- /dev/null +++ b/test/fixtures/photo_tags.yml @@ -0,0 +1,7 @@ +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +# one: +# column: value +# +# two: +# column: value diff --git a/test/fixtures/tags.yml b/test/fixtures/tags.yml new file mode 100644 index 0000000..5bf0293 --- /dev/null +++ b/test/fixtures/tags.yml @@ -0,0 +1,7 @@ +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +# one: +# column: value +# +# two: +# column: value diff --git a/test/unit/photo_tag_test.rb b/test/unit/photo_tag_test.rb new file mode 100644 index 0000000..34a2204 --- /dev/null +++ b/test/unit/photo_tag_test.rb @@ -0,0 +1,8 @@ +require 'test_helper' + +class PhotoTagTest < ActiveSupport::TestCase + # Replace this with your real tests. + test "the truth" do + assert true + end +end diff --git a/test/unit/tag_test.rb b/test/unit/tag_test.rb new file mode 100644 index 0000000..04498b2 --- /dev/null +++ b/test/unit/tag_test.rb @@ -0,0 +1,8 @@ +require 'test_helper' + +class TagTest < ActiveSupport::TestCase + # Replace this with your real tests. + test "the truth" do + assert true + end +end diff --git a/vendor/plugins/princely/MIT-LICENSE b/vendor/plugins/princely/MIT-LICENSE new file mode 100644 index 0000000..570ecf8 --- /dev/null +++ b/vendor/plugins/princely/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2007 [name of plugin creator] + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/plugins/princely/README b/vendor/plugins/princely/README new file mode 100644 index 0000000..fb20dab --- /dev/null +++ b/vendor/plugins/princely/README @@ -0,0 +1,50 @@ +Princely +======== + +Princely is a simple wrapper for the Prince XML PDF generation library +(http://www.princexml.com). It is almost entirely based on the SubImage +Prince library found on this blog post: + +http://sublog.subimage.com/articles/2007/05/29/html-css-to-pdf-using-ruby-on-rails + +I have taken the helpers and made them a little bit more generalized and +reusable, and created a render option set for pdf generation. The plugin +will also automatically register the PDF MimeType so that you can use +pdf in controller respond_to blocks. + +Example +======= + +class Provider::EstimatesController < Provider::BaseController + def show + respond_to do |format| + format.html + format.pdf do + render :pdf => "file_name", + :template => "controller/action.pdf.erb", + :stylesheets => ["application","prince"] + :layout => "pdf" + end + end + end + + def pdf + make_and_send_pdf("file_name") + end +end + +Render Defaults +=============== + +The defaults for the render options are as follows: + +layout: false +template: the template for the current controller/action +stylesheets: none + +Resources +========= + +Trac: http://trac.intridea.com/trac/public/ + +Copyright (c) 2007 Michael Bleigh and Intridea, Inc., released under the MIT license diff --git a/vendor/plugins/princely/Rakefile b/vendor/plugins/princely/Rakefile new file mode 100644 index 0000000..85ed38c --- /dev/null +++ b/vendor/plugins/princely/Rakefile @@ -0,0 +1,15 @@ +require 'rake' +require 'rake/testtask' +require 'rake/rdoctask' + +desc 'Default: run unit tests.' +task :default => :test + +desc 'Generate documentation for the princely plugin.' +Rake::RDocTask.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'Princely' + rdoc.options << '--line-numbers' << '--inline-source' + rdoc.rdoc_files.include('README') + rdoc.rdoc_files.include('lib/**/*.rb') +end diff --git a/vendor/plugins/princely/init.rb b/vendor/plugins/princely/init.rb new file mode 100644 index 0000000..99f748a --- /dev/null +++ b/vendor/plugins/princely/init.rb @@ -0,0 +1,6 @@ +require 'prince' +require 'pdf_helper' + +Mime::Type.register 'application/pdf', :pdf + +ActionController::Base.send(:include, PdfHelper) \ No newline at end of file diff --git a/vendor/plugins/princely/lib/pdf_helper.rb b/vendor/plugins/princely/lib/pdf_helper.rb new file mode 100644 index 0000000..63720db --- /dev/null +++ b/vendor/plugins/princely/lib/pdf_helper.rb @@ -0,0 +1,55 @@ +module PdfHelper + require 'prince' + + def self.included(base) + base.class_eval do + alias_method_chain :render, :princely + end + end + + def render_with_princely(options = nil, *args, &block) + if options.is_a?(Hash) && options.has_key?(:pdf) + options[:name] ||= options.delete(:pdf) + make_and_send_pdf(options.delete(:name), options) + else + render_without_princely(options, *args, &block) + end + end + + private + + def make_pdf(options = {}) + options[:stylesheets] ||= [] + options[:layout] ||= false + options[:template] ||= File.join(controller_path,action_name) + + prince = Prince.new() + # Sets style sheets on PDF renderer + prince.add_style_sheets(*options[:stylesheets].collect{|style| stylesheet_file_path(style)}) + + html_string = render_to_string(:template => options[:template], :layout => options[:layout]) + + # Make all paths relative, on disk paths... + html_string.gsub!(".com:/",".com/") # strip out bad attachment_fu URLs + html_string.gsub!( /src=["']+([^:]+?)["']/i ) { |m| "src=\"#{RAILS_ROOT}/public/" + $1 + '"' } # re-route absolute paths + + # Remove asset ids on images with a regex + html_string.gsub!( /src=["'](\S+\?\d*)["']/i ) { |m| 'src="' + $1.split('?').first + '"' } + + # Send the generated PDF file from our html string. + return prince.pdf_from_string(html_string) + end + + def make_and_send_pdf(pdf_name, options = {}) + send_data( + make_pdf(options), + :filename => pdf_name + ".pdf", + :type => 'application/pdf' + ) + end + + def stylesheet_file_path(stylesheet) + stylesheet = stylesheet.to_s.gsub(".css","") + File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR,"#{stylesheet}.css") + end +end diff --git a/vendor/plugins/princely/lib/prince.rb b/vendor/plugins/princely/lib/prince.rb new file mode 100644 index 0000000..b46dc59 --- /dev/null +++ b/vendor/plugins/princely/lib/prince.rb @@ -0,0 +1,75 @@ +# Prince XML Ruby interface. +# http://www.princexml.com +# +# Library by Subimage Interactive - http://www.subimage.com +# +# +# USAGE +# ----------------------------------------------------------------------------- +# prince = Prince.new() +# html_string = render_to_string(:template => 'some_document') +# send_data( +# prince.pdf_from_string(html_string), +# :filename => 'some_document.pdf' +# :type => 'application/pdf' +# ) +# +require 'logger' + +class Prince + attr_accessor :exe_path, :style_sheets, :log_file, :logger + + # Initialize method + # + def initialize() + # Finds where the application lives, so we can call it. + @exe_path = `which prince`.chomp + @style_sheets = '' + @log_file = "#{RAILS_ROOT}/log/prince.log" + @logger = RAILS_DEFAULT_LOGGER + end + + # Sets stylesheets... + # Can pass in multiple paths for css files. + # + def add_style_sheets(*sheets) + for sheet in sheets do + @style_sheets << " -s #{sheet} " + end + end + + # Returns fully formed executable path with any command line switches + # we've set based on our variables. + # + def exe_path + # Add any standard cmd line arguments we need to pass + @exe_path << " --input=html --server --log=#{@log_file} " + @exe_path << @style_sheets + return @exe_path + end + + # Makes a pdf from a passed in string. + # + # Returns PDF as a stream, so we can use send_data to shoot + # it down the pipe using Rails. + # + def pdf_from_string(string) + path = self.exe_path() + # Don't spew errors to the standard out...and set up to take IO + # as input and output + path << ' --silent - -o -' + + # Show the command used... + logger.info "\n\nPRINCE XML PDF COMMAND" + logger.info path + logger.info '' + + # Actually call the prince command, and pass the entire data stream back. + pdf = IO.popen(path, "w+") + pdf.puts(string) + pdf.close_write + result = pdf.gets(nil) + pdf.close_read + return result + end +end \ No newline at end of file