technicalpickles-has_markup 0.1.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/lib/has_markup.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'has_markup/markdown'
2
+ require 'has_markup/active_record'
@@ -0,0 +1,74 @@
1
+ module HasMarkup
2
+ # Modules to extend ActiveRecord
3
+ module ActiveRecord #:nodoc:
4
+ # Methods that are added to ActiveRecord::Base
5
+ module ClassMethods
6
+ # Adds the following methods for dealing with markup, using <tt>has_markup :content</tt> as an example:
7
+ # * <tt>content_html</tt> for generating the html of <tt>:content</tt>.
8
+ #
9
+ # Options are:
10
+ # * <tt>:required</tt> - column is required
11
+ # * <tt>:syntax</tt> - syntax of the markup. Currently supports only :markdown, which is the default.
12
+ # * <tt>:cache_html</tt> - html generated from the markup should be cached in a column. Following the
13
+ # example of using <tt>:content</tt>, it would require a column named <tt>:cached_content_html</tt>.
14
+ # It also adds a before_save hook <tt>:cache_content_html</tt> for generating the html before saving.
15
+ #
16
+ # For adding additional syntaxes, see has_markup/markdown and has_markup/textile. Basically:
17
+ #
18
+ # * Create HasMarkup::SyntaxNameHere
19
+ # * Define sprinkle_syntax_name_here_magic which takes a column name, like <tt>:content</tt>
20
+ # * In sprinkle_syntax_name_here_magic, create <tt>"#{column}_html"</tt>, which handles the actual generation
21
+ def has_markup(column, options = {})
22
+ options = HasMarkup::default_has_markup_options.merge(options)
23
+
24
+ validates_presence_of column if options[:required]
25
+
26
+ syntax = options[:syntax]
27
+ if supported? syntax
28
+ extend markup_syntax_module(syntax)
29
+ send("sprinkle_#{syntax}_magic", column)
30
+ else
31
+ raise "Unsupported syntax #{syntax.inspect}."
32
+ end
33
+ sprinkle_html_caching_magic column if options[:cache_html]
34
+ end
35
+
36
+ # Is the given syntax supported?
37
+ def supported?(syntax)
38
+ begin
39
+ markup_syntax_module(syntax)
40
+ return true
41
+ rescue NameError
42
+ return false
43
+ end
44
+ end
45
+
46
+ def markup_syntax_module(syntax)
47
+ "HasMarkup::#{syntax.to_s.camelize}".constantize
48
+ end
49
+
50
+
51
+ # Sprinkles the magic for caching the html of the given
52
+ def sprinkle_html_caching_magic(column)
53
+ define_method "set_cached_#{column}_html" do
54
+ html = self.send("#{column}_html")
55
+ self.send("cached_#{column}_html=", html)
56
+ end
57
+ before_save "set_cached_#{column}_html".to_sym
58
+ end
59
+ end
60
+ end
61
+
62
+ def self.default_has_markup_options
63
+ {
64
+ :syntax => :markdown,
65
+ :required => false,
66
+ :cache_html => false
67
+ }
68
+ end
69
+ end
70
+
71
+ require 'active_record'
72
+ ActiveRecord::Base.class_eval do
73
+ extend HasMarkup::ActiveRecord::ClassMethods
74
+ end
@@ -0,0 +1,38 @@
1
+ module HasMarkup
2
+ # Provides HasMarkup with markdown[http://daringfireball.net/projects/markdown/] support.
3
+ module Markdown
4
+ # Sprinkles the magic needed to support markdown. In particular, it will validate the markdown syntax
5
+ # on the column, and define a method <tt>column_html</tt> which uses BlueCloth to generate HTML.
6
+ def sprinkle_markdown_magic(column)
7
+ require 'bluecloth'
8
+
9
+ extend HasMarkup::Markdown::ClassMethods
10
+ include HasMarkup::Markdown::InstanceMethods
11
+
12
+ validates_markdown_syntax column
13
+ define_method "#{column}_html" do
14
+ markdown = self.send(column)
15
+ self.generate_html_from_markdown(markdown)
16
+ end
17
+ end
18
+
19
+ module InstanceMethods
20
+ def generate_html_from_markdown(markdown)
21
+ BlueCloth.new(markdown).to_html unless markdown.blank?
22
+ end
23
+ end
24
+
25
+ module ClassMethods
26
+ # Validates the markdown syntax of the given columns.
27
+ def validates_markdown_syntax(*columns)
28
+ validates_each(*columns) do |record, column, value|
29
+ begin
30
+ record.generate_html_from_markdown(value)
31
+ rescue BlueCloth::FormatError => e
32
+ errors.add column, "has #{e}"
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,42 @@
1
+ require 'shoulda'
2
+
3
+ module HasMarkup # :nodoc:
4
+ # Shoulda macros for has_markup. These get added to <tt>Test::Unit::TestCase</tt>.
5
+ module Shoulda
6
+ # Ensure that markup is cached.
7
+ #
8
+ # should_cache_markup :content
9
+ def should_cache_markup(column)
10
+ should_have_db_column "cached_#{column}_html"
11
+ should_have_instance_methods "set_cached_#{column}_html"
12
+ # TODO test that there's before_save action happening
13
+ end
14
+
15
+ # Ensure that markup is required.
16
+ #
17
+ # should_require_markup :content
18
+ def should_require_markup(column)
19
+ should_require_attributes column
20
+ end
21
+
22
+ # Ensure that the model has markup. Accepts all the same options that has_markup does.
23
+ #
24
+ # should_have_markup :content
25
+ def should_have_markup(column, options = {})
26
+ options = HasMarkup::default_has_markup_options.merge(options)
27
+ should_have_instance_methods "#{column}_html"
28
+
29
+ should_require_markup column if options[:required]
30
+
31
+ should_cache_markup column if options[:cache_html]
32
+ end
33
+ end
34
+ end
35
+
36
+ module Test # :nodoc: all
37
+ module Unit
38
+ class TestCase
39
+ extend HasMarkup::Shoulda
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,38 @@
1
+ module HasMarkup
2
+ # Provides HasMarkup with textile[http://hobix.com/textile/] support
3
+ module Textile
4
+ # Sprinkles the magic needed to support textile. In particular, it will define a method <tt>column_html</tt> which uses RedCloth to
5
+ # generate HTML.
6
+ def sprinkle_textile_magic(column)
7
+ require 'redcloth'
8
+
9
+ extend HasMarkup::Textile::ClassMethods
10
+ include HasMarkup::Textile::InstanceMethods
11
+
12
+ validates_textile_syntax column
13
+ define_method "#{column}_html" do
14
+ markdown = self.send(column)
15
+ self.generate_html_from_markdown(markdown)
16
+ end
17
+ end
18
+
19
+ module InstanceMethods
20
+ def generate_html_from_markdown(textile)
21
+ RedCloth.new(textile).to_html unless textile.blank?
22
+ end
23
+ end
24
+
25
+ module ClassMethods
26
+ # Validates the markdown syntax of the given columns.
27
+ def validates_textile_syntax(*columns)
28
+ validates_each(*columns) do |record, column, value|
29
+ begin
30
+ record.generate_html_from_markdown(value)
31
+ rescue e
32
+ errors.add column, "has #{e}"
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,7 @@
1
+ module HasMarkup
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 1
5
+ PATCH = 1
6
+ end
7
+ end
data/test/database.yml ADDED
@@ -0,0 +1,3 @@
1
+ plugin_test:
2
+ adapter: sqlite3
3
+ database: ':memory:'
data/test/post.rb ADDED
@@ -0,0 +1,3 @@
1
+ class Post < ActiveRecord::Base
2
+ has_markup :content, :required => true, :syntax => :markdown, :cache_html => true
3
+ end
data/test/post_test.rb ADDED
@@ -0,0 +1,32 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class PostTest < Test::Unit::TestCase
4
+ should_have_markup :content, :required => true, :syntax => :markdown, :cache_html => true
5
+
6
+ context 'A new project without content' do
7
+ setup do
8
+ @post = Post.new
9
+ end
10
+
11
+ context "caching the content, when it's blank" do
12
+ setup do
13
+ @post.set_cached_content_html
14
+ end
15
+
16
+ should "not have cached html" do
17
+ assert_nil @post.cached_content_html
18
+ end
19
+ end
20
+
21
+ context "updating the content" do
22
+ setup do
23
+ @post.update_attributes(:content => 'hi')
24
+ end
25
+
26
+ should "now have cached html" do
27
+ assert_equal '<p>hi</p>', @post.cached_content_html
28
+ end
29
+ end
30
+
31
+ end
32
+ end
data/test/schema.rb ADDED
@@ -0,0 +1,6 @@
1
+ ActiveRecord::Schema.define(:version => 0) do
2
+ create_table :posts, :force => true do |t|
3
+ t.text :content
4
+ t.text :cached_content_html
5
+ end
6
+ end
@@ -0,0 +1,29 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'rubygems'
4
+
5
+ # Use vendored gem because of limited gem availability on runcoderun
6
+ # This is loosely based on 'vendor everything'.
7
+ Dir[File.join(File.dirname(__FILE__), '..', 'vendor', 'gems', '**')].each do |dir|
8
+ lib = "#{dir}/lib"
9
+ $LOAD_PATH.unshift(lib) if File.directory?(lib)
10
+ end
11
+
12
+ require 'test/unit'
13
+ require 'active_record'
14
+ require 'shoulda'
15
+ require 'shoulda/active_record'
16
+ require 'factory_girl'
17
+
18
+ RAILS_ROOT = File.dirname(__FILE__)
19
+ require 'logger'
20
+ RAILS_DEFAULT_LOGGER = Logger.new("#{RAILS_ROOT}/test.log")
21
+
22
+ require File.dirname(__FILE__) + '/../init'
23
+ require File.dirname(__FILE__) + '/post.rb'
24
+
25
+ config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
26
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
27
+ ActiveRecord::Base.establish_connection(config[ENV['DB'] || 'plugin_test'])
28
+
29
+ load(File.dirname(__FILE__) + "/schema.rb") if File.exist?(File.dirname(__FILE__) + "/schema.rb")
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: technicalpickles-has_markup
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Josh Nichols
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-10-13 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Manage markup close to home... right in the model! Caching, validation, etc
17
+ email: josh@technicalpickles.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/has_markup
26
+ - lib/has_markup/active_record.rb
27
+ - lib/has_markup/markdown.rb
28
+ - lib/has_markup/shoulda.rb
29
+ - lib/has_markup/textile.rb
30
+ - lib/has_markup/version.rb
31
+ - lib/has_markup.rb
32
+ - test/database.yml
33
+ - test/debug.log
34
+ - test/post.rb
35
+ - test/post_test.rb
36
+ - test/schema.rb
37
+ - test/test.log
38
+ - test/test_helper.rb
39
+ has_rdoc: false
40
+ homepage: http://github.com/technicalpickles/has_markup
41
+ post_install_message:
42
+ rdoc_options: []
43
+
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ requirements: []
59
+
60
+ rubyforge_project:
61
+ rubygems_version: 1.2.0
62
+ signing_key:
63
+ specification_version: 2
64
+ summary: Manage markup close to home... right in the model! Caching, validation, etc
65
+ test_files: []
66
+