dryml 1.1.0 → 1.3.0.RC

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -2,26 +2,17 @@ require 'rake'
2
2
  require 'rake/rdoctask'
3
3
  require 'rake/testtask'
4
4
 
5
- $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), '/lib')
6
- $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), '/../hobosupport/lib')
7
- require 'dryml' # to get VERSION
8
-
9
5
  RUBY = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']).sub(/.*\s.*/m, '"\&"')
10
- if defined?(Bundler)
11
- RUBYDOCTEST = 'bundle exec rubydoctest'
12
- else
13
- RUBYDOCTEST = ENV['RUBYDOCTEST'] || "#{RUBY} -S rubydoctest"
14
- end
15
-
16
- desc "Default Task"
17
- task :default => [ :test ]
6
+ RUBYDOCTEST = ENV['RUBYDOCTEST'] || "#{RUBY} -S rubydoctest"
18
7
 
19
8
  # --- Testing --- #
20
9
 
21
- desc "Run all tests"
22
- task :test do |t|
23
- files=Dir['test/*.rdoctest'].map {|f| File.expand_path(f)}.join(' ')
24
- exit(1) if !system("#{RUBYDOCTEST} #{files}")
10
+ namespace "test" do
11
+ desc "Run the doctests"
12
+ task :doctest do |t|
13
+ files=Dir['test/**/*.rdoctest'].map {|f| File.expand_path(f)}.join(' ')
14
+ exit(1) if !system("#{RUBYDOCTEST} #{files}")
15
+ end
25
16
  end
26
17
 
27
18
  # --- RDOC --- #
@@ -30,19 +21,3 @@ require 'yard'
30
21
  YARD::Rake::YardocTask.new do |t|
31
22
  t.files = ['lib/**/*.rb', 'README', 'LICENSE.txt', 'CHANGES.txt']
32
23
  end
33
-
34
- # --- Packaging and Rubyforge & gemcutter & github--- #
35
-
36
- require 'jeweler'
37
- Jeweler::Tasks.new do |gemspec|
38
- gemspec.version = Dryml::VERSION
39
- gemspec.name = "dryml"
40
- gemspec.email = "tom@tomlocke.com"
41
- gemspec.summary = "The web app builder for Rails"
42
- gemspec.homepage = "http://hobocentral.net/"
43
- gemspec.authors = ["Tom Locke"]
44
- gemspec.rubyforge_project = "hobo"
45
- gemspec.add_dependency("hobosupport", ["= #{Dryml::VERSION}"])
46
- gemspec.add_dependency("actionpack", [">= 2.2.2", "< 3.0.0"])
47
- end
48
- Jeweler::GemcutterTasks.new
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.3.0.RC
data/dryml.gemspec CHANGED
@@ -1,72 +1,28 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
- # -*- encoding: utf-8 -*-
1
+ name = File.basename( __FILE__, '.gemspec' )
2
+ version = File.read(File.expand_path('../VERSION', __FILE__)).strip
3
+ require 'date'
5
4
 
6
5
  Gem::Specification.new do |s|
7
- s.name = %q{dryml}
8
- s.version = "1.1.0"
9
6
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Tom Locke"]
12
- s.date = %q{2011-11-15}
13
- s.email = %q{tom@tomlocke.com}
14
- s.extra_rdoc_files = [
15
- "README"
16
- ]
17
- s.files = [
18
- "CHANGES.txt",
19
- "LICENSE.txt",
20
- "README",
21
- "Rakefile",
22
- "TODO.txt",
23
- "dryml.gemspec",
24
- "lib/dryml.rb",
25
- "lib/dryml/dryml_builder.rb",
26
- "lib/dryml/dryml_doc.rb",
27
- "lib/dryml/dryml_generator.rb",
28
- "lib/dryml/dryml_support_controller.rb",
29
- "lib/dryml/helper.rb",
30
- "lib/dryml/parser.rb",
31
- "lib/dryml/parser/attribute.rb",
32
- "lib/dryml/parser/base_parser.rb",
33
- "lib/dryml/parser/document.rb",
34
- "lib/dryml/parser/element.rb",
35
- "lib/dryml/parser/elements.rb",
36
- "lib/dryml/parser/source.rb",
37
- "lib/dryml/parser/text.rb",
38
- "lib/dryml/parser/tree_parser.rb",
39
- "lib/dryml/part_context.rb",
40
- "lib/dryml/scoped_variables.rb",
41
- "lib/dryml/static_tags",
42
- "lib/dryml/tag_parameters.rb",
43
- "lib/dryml/taglib.rb",
44
- "lib/dryml/template.rb",
45
- "lib/dryml/template_environment.rb",
46
- "lib/dryml/template_handler.rb",
47
- "taglibs/core.dryml",
48
- "test/dryml.rdoctest"
49
- ]
50
- s.homepage = %q{http://hobocentral.net/}
7
+ s.authors = ['Tom Locke']
8
+ s.email = 'tom@tomlocke.com'
9
+ s.homepage = 'http://hobocentral.net'
10
+ s.rubyforge_project = 'hobo'
11
+ s.summary = "The Don't Repeat Yourself Markup Language"
12
+ s.description = "The Don't Repeat Yourself Markup Language"
13
+
14
+ s.add_runtime_dependency('actionpack', ["~> 3.0.0"])
15
+ s.add_runtime_dependency('hobo_support', ["= #{version}"])
16
+ s.add_development_dependency('rubydoctest', [">= 0"])
17
+
18
+ s.files = `git ls-files -x #{name}/* -z`.split("\0")
19
+
20
+ s.name = File.basename( __FILE__, '.gemspec' )
21
+ s.version = version
22
+ s.date = Date.today.to_s
23
+
24
+ s.required_rubygems_version = ">= 1.3.6"
51
25
  s.rdoc_options = ["--charset=UTF-8"]
52
26
  s.require_paths = ["lib"]
53
- s.rubyforge_project = %q{hobo}
54
- s.rubygems_version = %q{1.4.2}
55
- s.summary = %q{The web app builder for Rails}
56
-
57
- if s.respond_to? :specification_version then
58
- s.specification_version = 3
59
27
 
60
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
61
- s.add_runtime_dependency(%q<hobosupport>, ["= 1.1.0"])
62
- s.add_runtime_dependency(%q<actionpack>, [">= 2.2.2", "< 3.0.0"])
63
- else
64
- s.add_dependency(%q<hobosupport>, ["= 1.1.0"])
65
- s.add_dependency(%q<actionpack>, [">= 2.2.2", "< 3.0.0"])
66
- end
67
- else
68
- s.add_dependency(%q<hobosupport>, ["= 1.1.0"])
69
- s.add_dependency(%q<actionpack>, [">= 2.2.2", "< 3.0.0"])
70
- end
71
28
  end
72
-
@@ -58,19 +58,16 @@ module Dryml
58
58
  end
59
59
 
60
60
 
61
- def erb_process(erb_src, method_def=false)
61
+ def erb_process(erb_src)
62
62
  trim_mode = ActionView::TemplateHandlers::ERB.erb_trim_mode
63
63
  erb = ERB.new(erb_src, nil, trim_mode, "output_buffer")
64
- src = erb.src.split(';')[1..-2].join(';')
65
-
66
- if method_def
67
- src.sub /^\s*def.*?\(.*?\)/, '\0 __in_erb_template=true; '
68
- else
69
- "__in_erb_template=true; " + src
64
+ res = erb.src.split(';')[1..-2].join(';')
65
+ if res.respond_to? :force_encoding
66
+ res.force_encoding(erb_src.encoding)
70
67
  end
68
+ res
71
69
  end
72
70
 
73
-
74
71
  def build(local_names, auto_taglibs, src_mtime)
75
72
 
76
73
  auto_taglibs.each { |t| import_taglib(t) }
@@ -82,7 +79,7 @@ module Dryml
82
79
  @environment.class_eval(instruction[:src], template_path, instruction[:line_num])
83
80
 
84
81
  when :def
85
- src = erb_process(instruction[:src], true)
82
+ src = erb_process(instruction[:src])
86
83
  @environment.class_eval(src, template_path, instruction[:line_num])
87
84
 
88
85
  when :render_page
@@ -138,3 +135,4 @@ module Dryml
138
135
  end
139
136
  end
140
137
  end
138
+
@@ -4,20 +4,20 @@ require 'rexml/xpath'
4
4
 
5
5
  # DrymlDoc provides the facility to parse a directory tree of DRYML taglibs, building a collection of objects that provide metadata
6
6
  module DrymlDoc
7
-
7
+
8
8
  def self.load_taglibs(directory, taglib_class=DrymlDoc::Taglib)
9
9
  dryml_files = Dir["#{directory}/**/*.dryml"]
10
10
 
11
11
  dryml_files.map { |f| taglib_class.new(directory, f) }
12
12
  end
13
-
13
+
14
14
  CommentMethods = classy_module do
15
-
15
+
16
16
  def comment_intro
17
17
  comment && comment =~ /(.*?)^#/m ? $1 : comment
18
18
  end
19
19
 
20
-
20
+
21
21
  def comment_rest
22
22
  comment && comment[comment_intro.length..-1]
23
23
  end
@@ -25,20 +25,20 @@ require 'rexml/xpath'
25
25
  %w(comment comment_intro comment_rest).each do |m|
26
26
  class_eval "def #{m}_html; Maruku.new(#{m}).to_html.gsub(/&amp;/, '&'); end"
27
27
  end
28
-
28
+
29
29
  end
30
-
30
+
31
31
  class Taglib
32
-
32
+
33
33
  def initialize(home, filename, name=nil)
34
34
  @name = name || filename.sub(/.dryml$/, '')[home.length+1..-1]
35
35
  @source = File.read(filename)
36
36
  @doc = Dryml::Parser::Document.new(File.read(filename), filename)
37
37
  parse_tag_defs
38
38
  end
39
-
39
+
40
40
  attr_reader :name, :doc, :tag_defs, :source
41
-
41
+
42
42
  def comment
43
43
  first_node = doc[0][0]
44
44
  if first_node.is_a?(REXML::Comment)
@@ -48,41 +48,41 @@ require 'rexml/xpath'
48
48
  text.match(/<%#(.*?)%>/m)[1] rescue nil
49
49
  end
50
50
  end
51
-
51
+
52
52
  include CommentMethods
53
-
54
- private
55
-
53
+
54
+ private
55
+
56
56
  def tagdef_class
57
57
  self.class.parent.const_get('TagDef')
58
58
  end
59
-
59
+
60
60
  def parse_tag_defs
61
61
  @tag_defs = []
62
62
  REXML::XPath.match(doc, '/*/*[@tag]').each { |node| @tag_defs << tagdef_class.new(self, node) }
63
63
  end
64
-
64
+
65
65
  end
66
-
66
+
67
67
  class TagDef
68
-
68
+
69
69
  def initialize(taglib, node)
70
70
  @taglib = taglib
71
71
  @node = node
72
72
  end
73
-
73
+
74
74
  attr_reader :taglib, :node
75
75
  delegate :doc, :to => :taglib
76
-
77
-
76
+
77
+
78
78
  def name
79
79
  node.attributes['tag']
80
80
  end
81
-
81
+
82
82
  def source
83
83
  doc.restore_erb_scriptlets(node.to_s).strip
84
84
  end
85
-
85
+
86
86
  # The contents of the XML or ERB comment, if any, immediately above the tag definition
87
87
  def comment
88
88
  @comment ||= begin
@@ -98,19 +98,19 @@ require 'rexml/xpath'
98
98
  end
99
99
  end
100
100
  end
101
-
101
+
102
102
  include CommentMethods
103
-
103
+
104
104
  def no_doc?
105
105
  comment =~ /^nodoc\b/
106
106
  end
107
-
107
+
108
108
  # An array of the arrtibute names defined by this tag
109
109
  def attributes
110
110
  (node.attributes['attrs'] || "").split(/\s*,\s*/).where_not.blank?
111
111
  end
112
-
113
-
112
+
113
+
114
114
  # Returns a recursive array srtucture, where each item in the array is a pair: [parameter_name, sub_parameters]
115
115
  # (sub-parameters is the same kind of structure)
116
116
  def parameters(element=node)
@@ -125,40 +125,40 @@ require 'rexml/xpath'
125
125
  end
126
126
  result
127
127
  end
128
-
129
-
128
+
129
+
130
130
  # Is this the base definition of a polymorphic tag
131
131
  def polymorphic?
132
132
  node.attributes['polymorphic'].present?
133
133
  end
134
-
134
+
135
135
  # Is this an <extend>?
136
136
  def extension?
137
137
  node.name == "extend"
138
138
  end
139
-
140
-
139
+
140
+
141
141
  # The definition's 'for' attribute
142
142
  def for_type
143
143
  node.attributes['for']
144
144
  end
145
-
145
+
146
146
 
147
147
  # The name of the tag, if any, that this definition merges its parameters into
148
148
  # That is, the tag with 'merge' or 'merge-params' declared
149
149
  def merge_params
150
150
  REXML::XPath.first(node, ".//*[@merge|@merge-params]")._?.name
151
151
  end
152
-
152
+
153
153
  # The name of the tag, if any, that this definition merges its attributes into
154
- # That is, the tag with 'merge' or 'merge-attrs' declared
154
+ # That is, the tag with 'merge' or 'merge-attrs' declared
155
155
  def merge_attrs
156
156
  REXML::XPath.first(node, ".//*[@merge|@merge-attrs]")._?.name
157
157
  end
158
-
158
+
159
159
  end
160
-
161
-
160
+
161
+
162
162
  end
163
-
163
+
164
164
  end
@@ -2,82 +2,56 @@
2
2
  require 'set'
3
3
  require 'fileutils'
4
4
 
5
- require 'action_controller/dispatcher'
6
-
7
5
  module Dryml
8
-
6
+
9
7
  class DrymlGenerator
10
-
8
+
11
9
  HEADER = "<!-- AUTOMATICALLY GENERATED FILE - DO NOT EDIT -->\n\n"
12
-
10
+
13
11
  class << self
14
- attr_accessor :run_on_every_request
15
12
  attr_accessor :output_directory
16
13
  end
17
-
14
+
18
15
  def self.enable(generator_directories = [], output_directory = nil)
19
16
  @output_directory = output_directory
20
- @output_directory ||= "#{RAILS_ROOT}/app/views/taglibs/auto" if defined? :RAILS_ROOT
17
+ @output_directory ||= "#{Rails.root}/app/views/taglibs/auto" if Object.const_defined?(:Rails)
21
18
  @generator_directories = generator_directories
22
-
23
- # Unfortunately the dispatcher callbacks don't give us the hook we need (after routes are reloaded)
24
- # so we have to alias_method_chain
25
- ActionController::Dispatcher.class_eval do
26
-
27
- if respond_to? :reload_application
28
- #Rails 2.3
29
- class << self
30
- def reload_application_with_dryml_generators
31
- reload_application_without_dryml_generators
32
- DrymlGenerator.run unless Dryml::DrymlGenerator.run_on_every_request == false || Rails.env.production?
33
- end
34
- alias_method_chain :reload_application, :dryml_generators
35
- end
36
- else
37
- #Rails <= 2.2
38
- def reload_application_with_dryml_generators
39
- reload_application_without_dryml_generators
40
- DrymlGenerator.run unless Dryml::DrymlGenerator.run_on_every_request == false || Rails.env.production?
41
- end
42
- alias_method_chain :reload_application, :dryml_generators
43
- end
44
- end
45
19
  end
46
-
20
+
47
21
  def self.run(generator_directories=nil, output_directory=nil)
48
22
  @generator_directories ||= generator_directories
49
23
  @output_directory ||= output_directory
50
- @generator ||= DrymlGenerator.new(generator_directories || @generator_directories)
24
+ @generator ||= new(generator_directories || @generator_directories)
51
25
  @generator.run
52
26
  end
53
-
54
-
27
+
28
+
55
29
  def initialize(generator_directories=nil)
56
30
  @templates = {}
57
31
  @digests = {}
58
32
  generator_directories ||= Dryml::DrymlGenerator.generator_directories
59
33
  load_templates(generator_directories)
60
34
  end
61
-
35
+
62
36
  attr_accessor :subsite
63
-
64
-
37
+
38
+
65
39
  def load_templates(generator_directories)
66
- generator_directories.each do |dir|
67
- Dir["#{dir}/**/*.dryml.erb"].each do |f|
40
+ generator_directories.each do |path|
41
+ dir = path.to_s
42
+ Dir.glob("#{dir}/**/*.dryml.erb").each do |f|
68
43
  name = f[dir.length + 1..-11]
69
44
  erb = File.read(f)
70
45
  @templates[name] = ERB.new(erb, nil, '-').src
71
-
72
46
  # Create output directories and parents as required
73
- [nil, *Hobo.subsites].each do |s|
47
+ [nil, *Hobo.subsites].each do |s|
74
48
  FileUtils.mkdir_p(File.dirname("#{output_dir s}/#{name}"))
75
49
  end
76
50
  end
77
51
  end
78
52
  end
79
-
80
-
53
+
54
+
81
55
  def run
82
56
  # FIXME
83
57
  # Ensure all view hints loaded before running
@@ -89,21 +63,21 @@ require 'action_controller/dispatcher'
89
63
 
90
64
  subsites.each { |s| run_for_subsite(s) }
91
65
  end
92
-
93
-
66
+
67
+
94
68
  def run_for_subsite(subsite)
95
69
  self.subsite = subsite
96
70
  @templates.each_pair do |name, src|
97
71
  run_one(name, src)
98
- end
72
+ end
99
73
  end
100
-
101
-
74
+
75
+
102
76
  def output_dir(s=subsite)
103
77
  s ? "#{Dryml::DrymlGenerator.output_directory}/#{s}" : Dryml::DrymlGenerator.output_directory
104
78
  end
105
-
106
-
79
+
80
+
107
81
  def run_one(name, src)
108
82
  dryml = instance_eval(src, name)
109
83
  if dryml_changed?(name, dryml)
@@ -111,8 +85,8 @@ require 'action_controller/dispatcher'
111
85
  File.open("#{output_dir}/#{name}.dryml", 'w') { |f| f.write(out) }
112
86
  end
113
87
  end
114
-
115
-
88
+
89
+
116
90
  def dryml_changed?(name, dryml)
117
91
  key = "#{subsite}/#{name}"
118
92
  d = digest dryml
@@ -123,27 +97,27 @@ require 'action_controller/dispatcher'
123
97
  false
124
98
  end
125
99
  end
126
-
127
-
100
+
101
+
128
102
  def digest(s)
129
103
  OpenSSL::Digest::SHA1.hexdigest(s)
130
104
  end
131
-
132
-
105
+
106
+
133
107
  # --- Helper methods for the templates --- #
134
-
108
+
135
109
  attr_reader :controller
136
-
137
-
110
+
111
+
138
112
  def controllers
139
- Hobo::ModelController.all_controllers(subsite).sort_by &:name
113
+ Hobo::Controller::Model.all_controllers(subsite).sort_by &:name
140
114
  end
141
-
142
-
143
- def models
115
+
116
+
117
+ def models
144
118
  Hobo::Model.all_models.sort_by &:name
145
119
  end
146
-
120
+
147
121
  def each_controller
148
122
  controllers.each do |controller|
149
123
  @controller = controller
@@ -151,8 +125,8 @@ require 'action_controller/dispatcher'
151
125
  end
152
126
  @controller = nil
153
127
  end
154
-
155
-
128
+
129
+
156
130
  def each_model
157
131
  models.each do |model|
158
132
  @model = model
@@ -160,15 +134,17 @@ require 'action_controller/dispatcher'
160
134
  end
161
135
  @model = nil
162
136
  end
163
-
164
-
137
+
138
+
165
139
  def model
166
140
  @model || @controller.model
167
141
  end
168
-
169
-
142
+
143
+ # This method is used only to generate static default Model names in english only
144
+ # it does not provide any translation
145
+ # Localized apps will override the defaults by setting the specific keys in their locale files
170
146
  def model_name(*options)
171
- name = :plural.in?(options) ? model.view_hints.model_name_plural : model.view_hints.model_name
147
+ name = :plural.in?(options) ? model.model_name.human(:count=>2, :locale=>:en) : model.model_name.human(:locale=>:en)
172
148
  name = name.titleize.downcase if :lowercase.in?(options)
173
149
  name = name.camelize if :camel.in?(options)
174
150
  name
@@ -179,18 +155,18 @@ require 'action_controller/dispatcher'
179
155
  def sq_escape(s)
180
156
  s.gsub(/[\\]/, "\\\\\\\\").gsub(/'/, "\\\\'")
181
157
  end
182
-
183
-
158
+
159
+
184
160
  def model_class
185
161
  model.name.underscore.gsub('_', '-').gsub('/', '--')
186
162
  end
187
-
188
-
163
+
164
+
189
165
  def view_hints
190
166
  model.view_hints
191
167
  end
192
168
 
193
-
169
+
194
170
  def through_collection_names(klass=model)
195
171
  klass.reflections.values.select do |refl|
196
172
  refl.macro == :has_many && refl.options[:through]
@@ -206,8 +182,8 @@ require 'action_controller/dispatcher'
206
182
  else
207
183
  args
208
184
  end
209
- Hobo::ModelRouter.linkable?(klass, action, options)
210
- end
185
+ Hobo::Routes.linkable?(klass, action, options)
186
+ end
211
187
 
212
188
 
213
189
  def sortable_collection?(collection, model=self.model)
@@ -218,20 +194,21 @@ require 'action_controller/dispatcher'
218
194
  if defined? ActiveRecord::Acts::List::InstanceMethods
219
195
  refl = model.reflections[collection]
220
196
  klass = refl.klass
221
- klass < ActiveRecord::Acts::List::InstanceMethods &&
197
+ klass < ActiveRecord::Acts::List::InstanceMethods &&
198
+ klass.table_exists? &&
222
199
  klass.new.position_column == refl.options[:order].to_s
223
200
  end
224
201
  end
225
-
226
-
202
+
203
+
227
204
  def standard_fields(*args)
228
205
  klass = args.first.is_a?(Class) ? args.shift : model
229
206
  extras = args
230
-
231
- fields = klass.attr_order.*.to_s & klass.content_columns.*.name
207
+
208
+ fields = klass.attr_order.*.to_s & (klass.table_exists? ? klass.content_columns.*.name : [])
232
209
 
233
210
  fields -= %w{created_at updated_at created_on updated_on deleted_at} unless extras.include?(:include_timestamps)
234
-
211
+
235
212
  bt = extras.include?(:belongs_to)
236
213
  hm = extras.include?(:has_many)
237
214
  klass.reflections.values.sort_by { |refl| refl.name.to_s }.map do |refl|
@@ -242,30 +219,30 @@ require 'action_controller/dispatcher'
242
219
  fields.reject! { |f| model.never_show? f }
243
220
  fields
244
221
  end
245
-
246
-
222
+
223
+
247
224
  def creators
248
225
  defined?(model::Lifecycle) ? model::Lifecycle.publishable_creators : []
249
226
  end
250
-
227
+
251
228
  def transitions
252
229
  defined?(model::Lifecycle) ? model::Lifecycle.publishable_transitions : []
253
230
  end
254
-
231
+
255
232
  def creator_names
256
233
  creators.map { |c| c.name.to_s }
257
234
  end
258
-
235
+
259
236
  def transition_names
260
237
  transitions.map { |t| t.name.to_s }.uniq
261
238
  end
262
-
263
-
239
+
240
+
264
241
  def a_or_an(word)
265
242
  (word =~ /^[aeiou]/i ? "an " : "a ") + word
266
243
  end
267
-
244
+
268
245
  end
269
-
246
+
270
247
  end
271
248