renderable 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 85e3db025cfa6d26e33ad8a230b69c9e06fd0690
4
+ data.tar.gz: 346cce3206106a17fe0ed335e6c0742e3eb5943c
5
+ SHA512:
6
+ metadata.gz: 143acf4807cbf9dff01253bdc42066ed7a247d9081c48b6d7e551142f1dcfb31f293a88b07d4e0b2ccda393f575f86f2f8b6bc8adf5798fa9ff7b430748d3b53
7
+ data.tar.gz: 705a08ab8cb1b1e191e1aa62fcb1b677c99835306306e69e0ce227326de373356311429abf8018162c550250420ac55da1e22e8a5ce21aa693db1b0f7024b8d2
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Declare your gem's dependencies in acts_as_renderable.gemspec.
4
+ # Bundler will treat runtime dependencies like base dependencies, and
5
+ # development dependencies will be added by default to the :development group.
6
+ gemspec
7
+
data/MIT-LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013–2017 Jon Pearse
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,111 @@
1
+ h1. renderable
2
+
3
+ @renderable@ is a wee gem I threw together fairly quickly to [a] scratch an itch, and [b] teach myself some new things.
4
+
5
+ It provides a nice simple hook for automagically converting the content of fields containing "Textile":http://textile.sitemonks.com/ into HTML whenever your ActiveRecord model is saved.
6
+
7
+ h2. Installation
8
+
9
+ Is fairly simple.
10
+
11
+ *1. add @renderable@ to your Gemfile*
12
+
13
+ <pre>gem "renderable"</pre>
14
+
15
+ _(you may also need to add RedCloth to your Gemfile… there’s a weird nuance here I’ve not quite understood)_
16
+
17
+ *2. add appropriate fields to your database*
18
+
19
+ Each renderable property of your model requires two database fields—one to store the original Textile content, and the other to store the rendered HTML. By default, this second field has the same name as the first, only with a ‘_rendered’ suffix.
20
+
21
+ I have created a couple of migration tasks, though, so you can either do this:
22
+
23
+ <pre><code lang="ruby">create_table :my_models do |t|
24
+ t.string :foo
25
+ t.renderable :bar
26
+ t.integer :baz, null: false
27
+ end</code></pre>
28
+
29
+ Or this:
30
+
31
+ <pre><code lang="ruby">add_renderable :my_models, :my_field</code></pre>
32
+
33
+ In both cases, a @:string@ type is created by default, but you can override this by specifying the required field type as an additional parameter (@t.renderable :foo, :text@ and @add_renderable :my_models, :my_field, :text@). Additional options (limit, nullability, etc) can be specified as normal.
34
+
35
+ *3. hook into your model*
36
+
37
+ Simply add a call to @acts_as_renderable@ in your model:
38
+
39
+ <pre><code lang="ruby">class MyModel < ActiveRecord::Base
40
+
41
+ # automatically render ‘body’ and ‘description’ fields
42
+ acts_as_renderable fields: [ :body, :description ]
43
+
44
+ end</code></pre>
45
+
46
+ *4. use*
47
+
48
+ Your model will now have additional properties containing rendered HTML versions of your textile-ed content. Thus, for the above example:
49
+
50
+ <pre><code lang="haml">
51
+ -# output the rendered HTML
52
+ .content
53
+ ~ @my_model.body_rendered.html_safe
54
+ </code></pre>
55
+
56
+ h2. Why?
57
+
58
+ Why not?
59
+
60
+
61
+
62
+ Seriously though, I love Textile and find myself using it all over the place. In a normal path for most Rails developers, I came across "RedCloth":http://redcloth.org and merrily set about writing code.
63
+
64
+ However after a while, I found myself copy-pasting the same @:before_save@ hook into each of my models—grab a textile field, shove it through RedCloth, and dump the result into a ‘_rendered’ field. It wasn’t very DRY, but it worked.
65
+
66
+ @renderable@ was the next logical step—I wanted to abstract everything into one place, and I wanted to see what all this ‘gem’ malarkey is about. The result is an insanely simple gem—I think there’s more hook code than business logic—but it works.
67
+
68
+
69
+ h2. You’re doing it wrong!/What about %{gem}?
70
+
71
+ Oh, more than likely. And I’d be _very_ surprised if there wasn’t already something out there that did this for me… but ultimately, I fancied a bit of a challenge and I learned a lot.
72
+
73
+ h2. Version history
74
+
75
+ h3. 1.0.7 (2017-05-28)
76
+
77
+ * Releasing as a real gem
78
+
79
+ h3. 1.0.6 (2016-10-09)
80
+
81
+ * *[FIX]* made a tweak to the callback terminator that now means `before_*`` callbacks are correctly called _(seems only to affect Rails 5… no idea why)_
82
+
83
+ h3. 1.0.5 (2015-09-06)
84
+
85
+ * *[FIX]* fixing exception thrown when options are specified without a field type
86
+
87
+ h3. 1.0.4 (2014-09-11)
88
+
89
+ * adjusting rendering process to only run if a field has been updated
90
+
91
+ h3. 1.0.3 (2014-08-02)
92
+
93
+ * now compatible with Rails ~> 4.1.0
94
+
95
+ h3. 1.0.2 (2014-02-05 - _I was busy…_)
96
+
97
+ * adding @before_:field_render@ and @after_:field_render@ callbacks
98
+ * making callbacks work in a more Rails-esque way (I’m still learnin’)
99
+
100
+ h3. 1.0.1 (2014-02-05)
101
+
102
+ * added @restrictions@ option to @acts_as_renderable@, allowing the ability to pass restrictions (eg @:filter_html@, @:lite_mode@) to RedCloth
103
+ * added clean-up code to make output of @:lite_mode@ a little more sane
104
+
105
+ h3. 1.0.0 (2013-08-17)
106
+
107
+ Initial release.
108
+
109
+
110
+
111
+ Share and enjoy!
@@ -0,0 +1,34 @@
1
+ module Renderable
2
+ module Callbacks
3
+ def self.included(base)
4
+ base.extend(Defining)
5
+ end
6
+
7
+ module Defining
8
+ def define_renderable_callbacks(*callbacks)
9
+ define_callbacks *[callbacks, {:terminator => renderable_terminator }].flatten
10
+ callbacks.each do |callback|
11
+ eval <<-end_callbacks
12
+ def before_#{callback}(*args, &blk)
13
+ set_callback(:#{callback}, :before, *args, &blk)
14
+ end
15
+ def after_#{callback}(*args, &blk)
16
+ set_callback(:#{callback}, :after, *args, &blk)
17
+ end
18
+ end_callbacks
19
+ end
20
+ end
21
+
22
+ private
23
+ def renderable_terminator
24
+ lambda do |_, result|
25
+ if result.respond_to?(:call)
26
+ result.call == false
27
+ else
28
+ result == false
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,13 @@
1
+ require 'renderable/schema'
2
+
3
+ module Renderable
4
+ module Glue
5
+ def self.included base
6
+ base.extend ClassMethods
7
+ base.send :include, Callbacks
8
+ base.send :include, Schema if defined? ActiveRecord
9
+
10
+ base.class_attribute :renderable_options
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,42 @@
1
+ module Renderable
2
+ module InstanceMethods
3
+
4
+ private
5
+ def renderable_render
6
+
7
+ suff = renderable_options[:suffix]
8
+ renderable_options[:fields].each do |field|
9
+
10
+ # skip if the field is unchanged
11
+ next unless self.changed.include? field.to_s
12
+
13
+ # actually render
14
+ run_callbacks(:render) do
15
+ run_callbacks(:"#{field}_render") do
16
+
17
+ # a. call out
18
+ content = self[field.to_sym]
19
+ content = content.nil? ? nil : RedCloth.new(content, renderable_options[:restrictions]).to_html
20
+
21
+ # b. if we're using RedCloth's lite_mode, let's make the HTML sane again...
22
+ if renderable_options[:restrictions].include?(:lite_mode)
23
+
24
+ # for reasons best known to RedCloth, lite_mode replaces all newlines with a BR tag. This is butt-ugly and
25
+ # we can do better.
26
+ #
27
+ # So, let's find all instances of multiple BRs and replace them with Ps.
28
+ content = '<p>'+content.gsub( /(<br\s?\/?>\n){2,}/, "</p>\n\n<p>" )+'</p>';
29
+
30
+ end
31
+
32
+ # c. copy it back
33
+ self["#{field}#{suff}".to_sym] = content
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,22 @@
1
+ require 'renderable'
2
+ require 'renderable/schema'
3
+
4
+ module Renderable
5
+ require 'rails'
6
+
7
+ class Railtie < Rails::Railtie
8
+ initializer 'renderable.insert_into_active_record' do |app|
9
+ ActiveSupport.on_load :active_record do
10
+ Renderable::Railtie.insert
11
+ end
12
+ end
13
+ end
14
+
15
+ class Railtie
16
+ def self.insert
17
+ if defined?(ActiveRecord)
18
+ ActiveRecord::Base.send :include, Renderable::Glue
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,104 @@
1
+ module Renderable
2
+
3
+ module Schema
4
+ def self.included( base )
5
+
6
+ ActiveRecord::ConnectionAdapters::Table.send :include, TableDefinition
7
+ ActiveRecord::ConnectionAdapters::TableDefinition.send :include, TableDefinition
8
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.send :include, Statements
9
+
10
+ end
11
+ end
12
+
13
+ module Statements
14
+
15
+ # Adds a renderable column to the specified table.
16
+ #
17
+ # This is reasonably intelligent, and will create any required fields. Thus, if you are adding renderable
18
+ # functionality to an existing field, it will only add the ‘rendered’ version of the field.
19
+ #
20
+ # === Parameters
21
+ #
22
+ # [table_name] the name of the table to which to add the field(s)
23
+ # [field_name] the base name of the field that will be added
24
+ # [field_type] the type of the field that will be added (defaults to @:string@)
25
+ # [options] any additional options to be passed to add_column
26
+ #
27
+ def add_renderable( table_name, field_name, field_type = :string, options = {})
28
+ raise ArgumentError "Please specify name of table in add_renderable call in your migration" if table_name.blank?
29
+ raise ArgumentError "Please specify name of field in add_renderable call in your migration" if field_name.blank?
30
+
31
+ # do we have a suffix specified
32
+ suffix = options.delete(:suffix) { |k| '_rendered' }
33
+
34
+ # bugfix: if we don’t specify a field type but do specify options, it snarfs things up, so resolve that here
35
+ # @TODO: is there a better way of doing this in Ruby?
36
+ if field_type.is_a? Hash
37
+
38
+ # copy field_type hash to options
39
+ options = field_type
40
+
41
+ # default field_type again
42
+ field_type = :string
43
+
44
+ end
45
+
46
+ # add base column
47
+ add_column table_name, field_name, field_type, options unless column_exists?(table_name, field_name)
48
+
49
+ # rendered column
50
+ add_column table_name, "#{field_name}#{suffix}", field_type, options
51
+ end
52
+
53
+ # Removes a renderable field from the specified table.
54
+ #
55
+ # === Parameters
56
+ #
57
+ # [table_name] the name of the table from which to remove the field
58
+ # [field_name] the name of the field to remove
59
+ # [suffix] the custom suffix used when creating the field, if used at all
60
+ #
61
+ def remove_renderable( table_name, field_name, suffix = '_rendered' )
62
+
63
+ remove_column table_name, field_name if column_exists?(table_name, field_name)
64
+ remove_column table_name, "#{field_name}#{suffix}" if column_exists?(table_name, field_name)
65
+
66
+ end
67
+
68
+ end
69
+
70
+ module TableDefinition
71
+
72
+ # Adds a renderable field to the current table. This is used inside a create_table block.
73
+ #
74
+ # === Parameters
75
+ #
76
+ # [field_name] the name of the field to add
77
+ # [field_type] the type of the field to add
78
+ # [options] any additional options to be passed to add_column
79
+ #
80
+ def renderable( field_name, field_type = :string, options = {} )
81
+ raise ArgumentError "Please specify name of field in renderable call in your migration" if field_name.blank?
82
+
83
+ # get suffix
84
+ suffix = options.delete(:suffix) { |k| '_rendered' }
85
+
86
+ # bugfix: if we don’t specify a field type but do specify options, it snarfs things up, so resolve that here
87
+ # @TODO: is there a better way of doing this in Ruby?
88
+ if field_type.is_a? Hash
89
+
90
+ # copy field_type hash to options
91
+ options = field_type
92
+
93
+ # default field_type again
94
+ field_type = :string
95
+
96
+ end
97
+
98
+ # add columns
99
+ column field_name, field_type, options
100
+ column "#{field_name}#{suffix}", field_type, options
101
+
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,3 @@
1
+ module Renderable
2
+ VERSION = "1.0.7"
3
+ end
data/lib/renderable.rb ADDED
@@ -0,0 +1,58 @@
1
+ require 'renderable/callbacks'
2
+ require 'renderable/glue'
3
+ require 'renderable/instance_methods'
4
+ require 'renderable/version'
5
+
6
+ require 'renderable/railtie' if defined?(Rails)
7
+
8
+ module Renderable
9
+
10
+ module ClassMethods
11
+
12
+ # Add auto-rendering behaviour to an ActiveRecord object. This will automatically set up accessors on both original
13
+ # and rendered fields, using attr_accessor
14
+ #
15
+ # === Parameters
16
+ #
17
+ # [options] a Hash containing options for Renderable (see below)
18
+ #
19
+ # === Options
20
+ #
21
+ # [:fields] an array of ActiveRecord fields you wish to make renderable
22
+ # [:suffix] the suffix to use for ‘rendered’ versions of fields. (default: ‘_rendered’)
23
+ #
24
+ def acts_as_renderable( options = {} )
25
+ include InstanceMethods
26
+
27
+ # sanity check
28
+ if options[:fields].blank?
29
+ return
30
+ end
31
+
32
+ # default options
33
+ options[:suffix] ||= '_rendered'
34
+ options[:restrictions] ||= []
35
+
36
+ # store the options
37
+ self.renderable_options = options
38
+
39
+ # set accessible on fields
40
+ options[:fields].each do |field|
41
+ if ::Rails::VERSION::STRING < '4.0'
42
+ attr_accessible field, "#{field}#{options[:suffix]}"
43
+ end
44
+
45
+ define_renderable_callbacks :"#{field}_render"
46
+ end
47
+
48
+ # set up callbacks
49
+ define_renderable_callbacks :render
50
+
51
+ # hook
52
+ before_save :renderable_render
53
+
54
+ end
55
+
56
+ end
57
+
58
+ end
@@ -0,0 +1,20 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ # Maintain your gem's version:
4
+ require "renderable/version"
5
+
6
+ # Describe your gem and declare its dependencies:
7
+ Gem::Specification.new do |gem|
8
+ gem.authors = "Jon Pearse"
9
+ gem.email = "jon@jonpearse.net"
10
+ gem.summary = "Textile->HTML pre-rendering for ActiveRecord via RedCloth"
11
+ gem.description = "renderable provides a simple hook for ActiveRecord that converts Textile to HTML when the object is saved"
12
+ gem.homepage = "https://github.com/jonpearse/renderable"
13
+ gem.license = "MIT"
14
+
15
+ gem.files = `git ls-files`.split($\)
16
+ gem.name = "renderable"
17
+ gem.version = Renderable::VERSION
18
+
19
+ gem.add_dependency('redcloth', '~> 0')
20
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: renderable
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.7
5
+ platform: ruby
6
+ authors:
7
+ - Jon Pearse
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: redcloth
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: renderable provides a simple hook for ActiveRecord that converts Textile
28
+ to HTML when the object is saved
29
+ email: jon@jonpearse.net
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - Gemfile
35
+ - MIT-LICENSE.txt
36
+ - README.textile
37
+ - lib/renderable.rb
38
+ - lib/renderable/callbacks.rb
39
+ - lib/renderable/glue.rb
40
+ - lib/renderable/instance_methods.rb
41
+ - lib/renderable/railtie.rb
42
+ - lib/renderable/schema.rb
43
+ - lib/renderable/version.rb
44
+ - renderable.gemspec
45
+ homepage: https://github.com/jonpearse/renderable
46
+ licenses:
47
+ - MIT
48
+ metadata: {}
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubyforge_project:
65
+ rubygems_version: 2.6.11
66
+ signing_key:
67
+ specification_version: 4
68
+ summary: Textile->HTML pre-rendering for ActiveRecord via RedCloth
69
+ test_files: []