hobo 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,48 @@
1
+ === Hobo 0.8.2 ===
2
+
3
+ Hobo models -- improvement to name-in-URL (#to_param)
4
+
5
+ Added missing input for time fields
6
+
7
+ Rapid forms -- added missing hours/minutes/seconds fields to datetime input
8
+
9
+ Reorg of Hobo Rakefile, in preprartion for move to Shoulda
10
+
11
+ Rapid -- fix to <create-button>
12
+
13
+ Echoe tasks -- adding workaround for developer-dependencies problem
14
+
15
+ Rapid -- fixes to css class named that had '_' instead of '-'
16
+
17
+ Rapid pages generators -- improvements to form submit button labels
18
+
19
+ ModelController - set the provided key on the record *before* the view permission check during a lifecycle
20
+ transition
21
+
22
+ Hobo Models -- Model.user_find can now take a block to perform actions on the record prior to the permission check
23
+
24
+ Added Rails dependency to hobofields gem
25
+
26
+ Fix to Rails dependency - any Rails >= 2.1 is ok
27
+
28
+ Reorganised generator tests
29
+
30
+ Hobo users now have an #account_active? method. Used in two places:
31
+
32
+ - This method rather than the return value of the block passed to hobo_login, is now used to figure out if an
33
+ account is active when logging in.
34
+
35
+ - After signing up, also log the user in iff account_active? is true. This is useful if there is a second step to
36
+ signing up, such as email activation
37
+
38
+ hobo_front_controller generator -- improved title of home page
39
+
40
+ Rapid generators -- fix to owner link on new-for-owner page
41
+
42
+ Fix to bug where validations were not happening during lifecycle creates/transitions
43
+
44
+
45
+
1
46
  === Hobo 0.8.1 ===
2
47
 
3
48
  Fixes to generating and loading subsite controllers
data/Manifest CHANGED
@@ -142,7 +142,7 @@ tasks/environments.rake
142
142
  tasks/fix_dryml.rake
143
143
  tasks/generate_tag_reference.rb
144
144
  tasks/hobo_tasks.rake
145
- test/test_generator_helper.rb
146
- test/test_helper.rb
147
- test/test_hobo_model_controller_generator.rb
145
+ test/generators/test_generator_helper.rb
146
+ test/generators/test_helper.rb
147
+ test/generators/test_hobo_model_controller_generator.rb
148
148
  uninstall.rb
data/Rakefile CHANGED
@@ -4,8 +4,21 @@ require 'rake/testtask'
4
4
 
5
5
  load "tasks/generate_tag_reference.rb"
6
6
 
7
- desc 'Default: run specs.'
8
- task :default => :spec
7
+ desc "Default Task"
8
+ task :default => [ :test ]
9
+
10
+
11
+ # --- Testing --- #
12
+
13
+ desc "Run all unit tests"
14
+ Rake::TestTask.new(:test) { |t|
15
+ t.libs << "test"
16
+ t.test_files=Dir.glob( "test/**/*_test.rb" ).sort
17
+ t.verbose = true
18
+ }
19
+
20
+
21
+ # --- RDoc --- #
9
22
 
10
23
  desc 'Generate documentation for the Hobo plugin.'
11
24
  Rake::RDocTask.new(:rdoc) do |rdoc|
@@ -16,6 +29,9 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
16
29
  rdoc.rdoc_files.include('lib/**/*.rb')
17
30
  end
18
31
 
32
+
33
+ # --- Packaging and Rubyforge --- #
34
+
19
35
  require 'echoe'
20
36
 
21
37
  Echoe.new('hobo') do |p|
@@ -26,91 +42,16 @@ Echoe.new('hobo') do |p|
26
42
  p.project = "hobo"
27
43
 
28
44
  p.changelog = "CHANGES.txt"
29
- p.version = "0.8.1"
45
+ p.version = "0.8.2"
30
46
 
31
47
  p.dependencies = [
32
- 'hobosupport >=0.8.1',
33
- 'hobofields >=0.8.1',
34
- 'rails =2.1',
48
+ 'hobosupport >=0.8.2',
49
+ 'hobofields >=0.8.2',
50
+ 'rails >=2.1',
35
51
  'mislav-will_paginate >=2.2.1']
52
+
53
+ p.development_dependencies = []
36
54
  end
37
55
 
38
56
 
39
57
 
40
-
41
- # --- RSpec --- #
42
-
43
- # In rails 1.2, plugins aren't available in the path until they're loaded.
44
- # Check to see if the rspec plugin is installed first and require
45
- # it if it is. If not, use the gem version.
46
- PLUGIN_DIR = File.dirname(__FILE__)
47
-
48
- rspec_base = File.expand_path(PLUGIN_DIR + '/spec/rails_root/vendor/plugins/rspec/lib')
49
- $LOAD_PATH.unshift(rspec_base) if File.exist?(rspec_base)
50
- require '../hobo_spec/rails_root/vendor/plugins/rspec/lib/spec/rake/spectask'
51
- require '../hobo_spec/rails_root/vendor/plugins/rspec/lib/spec/translator'
52
-
53
- spec_prereq = :noop # File.exist?(File.join(PLUGIN_DIR, 'config', 'database.yml')) ? "db:test:prepare" : :noop
54
- task :noop do
55
- end
56
-
57
- task :stats => "spec:statsetup"
58
-
59
- SPEC_HOME = "#{PLUGIN_DIR}/../hobo_spec"
60
-
61
- desc "Run all specs in spec directory (excluding plugin specs)"
62
- Spec::Rake::SpecTask.new(:spec => spec_prereq) do |t|
63
- t.spec_opts = ['--options', "\"#{SPEC_HOME}/spec.opts\""]
64
- t.spec_files = FileList["#{SPEC_HOME}/unit/**/*_spec.rb"]
65
- end
66
-
67
- namespace :spec do
68
- desc "Run all specs in spec directory with RCov (excluding plugin specs)"
69
- Spec::Rake::SpecTask.new(:rcov) do |t|
70
- t.spec_opts = ['--options', "\"#{SPEC_HOME}/spec.opts\""]
71
- t.spec_files = FileList["#{SPEC_HOME}/unit/**/*_spec.rb"]
72
- t.rcov = true
73
- t.rcov_opts = ['--exclude', 'spec', '--rails']
74
- end
75
-
76
- desc "Print Specdoc for all specs (excluding plugin specs)"
77
- Spec::Rake::SpecTask.new(:doc) do |t|
78
- t.spec_opts = ["--format", "specdoc", "--dry-run"]
79
- t.spec_files = FileList["#{SPEC_HOME}/unit/**/*_spec.rb"]
80
- end
81
-
82
- [:models, :controllers, :views, :helpers].each do |sub|
83
- desc "Run the specs under spec/#{sub}"
84
- Spec::Rake::SpecTask.new(sub => spec_prereq) do |t|
85
- t.spec_opts = ['--options', "\"#{SPEC_HOME}/spec.opts\""]
86
- t.spec_files = FileList["#{SPEC_HOME}/#{sub}/**/*_spec.rb"]
87
- end
88
- end
89
-
90
- # Setup specs for stats
91
- task :statsetup do
92
- require 'code_statistics'
93
- ::STATS_DIRECTORIES << %w(Model\ specs spec/models)
94
- ::STATS_DIRECTORIES << %w(View\ specs spec/views)
95
- ::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers)
96
- ::STATS_DIRECTORIES << %w(Helper\ specs spec/views)
97
- ::CodeStatistics::TEST_TYPES << "Model specs"
98
- ::CodeStatistics::TEST_TYPES << "View specs"
99
- ::CodeStatistics::TEST_TYPES << "Controller specs"
100
- ::CodeStatistics::TEST_TYPES << "Helper specs"
101
- ::STATS_DIRECTORIES.delete_if {|a| a[0] =~ /test/}
102
- end
103
-
104
- namespace :db do
105
- namespace :fixtures do
106
- desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y"
107
- task :load => :environment do
108
- require 'active_record/fixtures'
109
- ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
110
- (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(SPEC_HOME, 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
111
- Fixtures.create_fixtures("#{SPEC_HOME}/fixtures", File.basename(fixture_file, '.*'))
112
- end
113
- end
114
- end
115
- end
116
- end
@@ -57,7 +57,9 @@ new_link = linkable?(:new)
57
57
  </section>
58
58
 
59
59
  <section param="content-body">
60
- <form param/>
60
+ <form param>
61
+ <submit: label="Create <%= model_name :title %>"/>
62
+ </form>
61
63
  </section>
62
64
  </content:>
63
65
  </page>
@@ -77,7 +79,7 @@ if collection
77
79
  collection_class = model.reflections[collection].klass
78
80
  owner = model.reverse_reflection(collection)._?.name
79
81
  if owner
80
- add_link = collection &&linkable?(collection_class, :"new_for_#{owner}")
82
+ add_link = collection && linkable?(collection_class, :"new_for_#{owner}")
81
83
  add_form = !add_link && linkable?(collection_class, :"create_for_#{owner}", :method => :post)
82
84
  end
83
85
  end
@@ -174,7 +176,7 @@ name_attribute = model.name_attribute
174
176
  <%
175
177
  collection_name = model.reverse_reflection(owner).name.to_s
176
178
  owner_model = model.reflections[owner].klass
177
- owner_tag = linkable?(owner_model) ? "a" : "name"
179
+ owner_tag = linkable?(owner_model, :show) ? "a" : "name"
178
180
  owner = owner.to_s
179
181
  -%>
180
182
  <% if :index.in? actions -%>
@@ -228,6 +230,7 @@ new_link = :new.in?(actions)
228
230
  <section param="content-body">
229
231
  <form owner="<%= owner %>" method="post" param>
230
232
  <field-list: skip="<%= owner %>"/>
233
+ <submit: label="Create <%= model_name :title %>"/>
231
234
  </form>
232
235
  </section>
233
236
  </content:>
@@ -1,18 +1,18 @@
1
1
 
2
- # Gem::Specification for Hobo-0.8.1
2
+ # Gem::Specification for Hobo-0.8.2
3
3
  # Originally generated by Echoe
4
4
 
5
5
  --- !ruby/object:Gem::Specification
6
6
  name: hobo
7
7
  version: !ruby/object:Gem::Version
8
- version: 0.8.1
8
+ version: 0.8.2
9
9
  platform: ruby
10
10
  authors:
11
11
  - Tom Locke
12
12
  autorequire:
13
13
  bindir: bin
14
14
 
15
- date: 2008-09-08 00:00:00 +01:00
15
+ date: 2008-09-14 00:00:00 +01:00
16
16
  default_executable:
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
@@ -23,7 +23,7 @@ dependencies:
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 0.8.1
26
+ version: 0.8.2
27
27
  version:
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: hobofields
@@ -33,7 +33,7 @@ dependencies:
33
33
  requirements:
34
34
  - - ">="
35
35
  - !ruby/object:Gem::Version
36
- version: 0.8.1
36
+ version: 0.8.2
37
37
  version:
38
38
  - !ruby/object:Gem::Dependency
39
39
  name: rails
@@ -41,7 +41,7 @@ dependencies:
41
41
  version_requirement:
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
- - - "="
44
+ - - ">="
45
45
  - !ruby/object:Gem::Version
46
46
  version: "2.1"
47
47
  version:
@@ -55,16 +55,6 @@ dependencies:
55
55
  - !ruby/object:Gem::Version
56
56
  version: 2.2.1
57
57
  version:
58
- - !ruby/object:Gem::Dependency
59
- name: echoe
60
- type: :development
61
- version_requirement:
62
- version_requirements: !ruby/object:Gem::Requirement
63
- requirements:
64
- - - ">="
65
- - !ruby/object:Gem::Version
66
- version: "0"
67
- version:
68
58
  description: The web app builder for Rails
69
59
  email: tom@tomlocke.com
70
60
  executables:
@@ -281,9 +271,9 @@ files:
281
271
  - tasks/fix_dryml.rake
282
272
  - tasks/generate_tag_reference.rb
283
273
  - tasks/hobo_tasks.rake
284
- - test/test_generator_helper.rb
285
- - test/test_helper.rb
286
- - test/test_hobo_model_controller_generator.rb
274
+ - test/generators/test_generator_helper.rb
275
+ - test/generators/test_helper.rb
276
+ - test/generators/test_hobo_model_controller_generator.rb
287
277
  - uninstall.rb
288
278
  - hobo.gemspec
289
279
  has_rdoc: true
@@ -317,6 +307,7 @@ rubygems_version: 1.2.0
317
307
  specification_version: 2
318
308
  summary: The web app builder for Rails
319
309
  test_files:
320
- - test/test_generator_helper.rb
321
- - test/test_helper.rb
322
- - test/test_hobo_model_controller_generator.rb
310
+ - test/dryml/complilation_test.rb
311
+ - test/generators/test_generator_helper.rb
312
+ - test/generators/test_helper.rb
313
+ - test/generators/test_hobo_model_controller_generator.rb
@@ -26,7 +26,7 @@ class HoboError < RuntimeError; end
26
26
 
27
27
  module Hobo
28
28
 
29
- VERSION = "0.8.1"
29
+ VERSION = "0.8.2"
30
30
 
31
31
  class RawJs < String; end
32
32
 
@@ -151,6 +151,7 @@ module Hobo
151
151
 
152
152
 
153
153
  def context_map(enum = this)
154
+ # TODO: Calls to respond_to? in here can cause the full collection hiding behind a scoped collection to get loaded
154
155
  res = []
155
156
  empty = true
156
157
  if enum.respond_to?(:each_pair)
@@ -144,7 +144,7 @@ module Hobo
144
144
  end
145
145
 
146
146
 
147
- def become(state_name, validate=false)
147
+ def become(state_name, validate=true)
148
148
  state_name = state_name.to_s
149
149
  if self.state != state_name
150
150
  record.write_attribute self.class.state_field, state_name
@@ -133,6 +133,7 @@ module Hobo
133
133
 
134
134
  def user_find(user, *args)
135
135
  record = find(*args)
136
+ yield(record) if block_given?
136
137
  raise PermissionDeniedError unless Hobo.can_view?(user, record)
137
138
  record
138
139
  end
@@ -390,9 +391,9 @@ module Hobo
390
391
 
391
392
 
392
393
  def to_param
393
- name_attr = self.class.name_attribute
394
- if name_attr
395
- readable = send(name_attr).to_s.downcase.gsub(/[^a-z0-9]+/, '-').gsub(/-+$/, '').gsub(/^-+$/, '').split('-')[0..5].join('-')
394
+ name_attr = self.class.name_attribute and name = send(name_attr)
395
+ if name_attr && !name.blank?
396
+ readable = name.to_s.downcase.gsub(/[^a-z0-9]+/, '-').gsub(/-+$/, '').gsub(/^-+$/, '').split('-')[0..5].join('-')
396
397
  @to_param ||= "#{id}-#{readable}"
397
398
  else
398
399
  id
@@ -308,7 +308,9 @@ module Hobo
308
308
 
309
309
 
310
310
  def find_instance(options={})
311
- model.user_find(current_user, params[:id], options)
311
+ model.user_find(current_user, params[:id], options) do |record|
312
+ yield record if block_given?
313
+ end
312
314
  end
313
315
 
314
316
 
@@ -580,9 +582,11 @@ module Hobo
580
582
 
581
583
 
582
584
  def prepare_for_transition(name, options={})
583
- self.this = find_instance
584
- this.exempt_from_edit_checks = true
585
- this.lifecycle.provided_key = params[:key]
585
+ self.this = find_instance do |record|
586
+ # The block allows us to perform actions on the records before the permission check
587
+ record.exempt_from_edit_checks = true
588
+ record.lifecycle.provided_key = params[:key]
589
+ end
586
590
  @transition = this.lifecycle.find_transition(name, current_user)
587
591
  end
588
592
 
@@ -142,7 +142,6 @@ module Hobo::RapidHelper
142
142
  def standard_fields(model, include_timestamps=false)
143
143
  fields = model.attr_order.*.to_s & model.content_columns.*.name
144
144
  fields -= %w{created_at updated_at created_on updated_on deleted_at} unless include_timestamps
145
- debugger if model == User
146
145
  fields.reject! { |f| model.never_show? f }
147
146
  fields
148
147
  end
@@ -98,7 +98,7 @@ module Hobo
98
98
  end
99
99
 
100
100
  def account_active?
101
- state == 'active'
101
+ !self.class.has_lifecycle? || !'active'.in?(self.class::Lifecycle.state_names) || state == 'active'
102
102
  end
103
103
 
104
104
  # Encrypts the password with the user salt
@@ -64,13 +64,11 @@ module Hobo
64
64
  else
65
65
  old_user = current_user
66
66
  self.current_user = user
67
+
68
+ yield if block_given?
67
69
 
68
- # If supplied, a block can be used to test if this user is
69
- # allowed to log in (e.g. the account may be disabled)
70
- account_available = block_given? ? yield : true
71
-
72
- if !account_available
73
- # block returned false - cancel this login
70
+ if !user.account_active?
71
+ # account not activate - cancel this login
74
72
  self.current_user = old_user
75
73
  render :action => :account_disabled unless performed?
76
74
  else
@@ -88,7 +86,10 @@ module Hobo
88
86
 
89
87
  def hobo_do_signup(&b)
90
88
  do_creator_action(:signup) do
91
- flash[:notice] = "Thanks for signing up!" if valid?
89
+ if valid?
90
+ flash[:notice] = "Thanks for signing up!"
91
+ flash[:notice] << " You must activate your account before you can log in. Please check your email." unless this.account_active?
92
+ end
92
93
  response_block(&b) or if valid?
93
94
  self.current_user = this if this.account_active?
94
95
  redirect_back_or_default(home_page)
@@ -21,8 +21,6 @@ if Rails::VERSION::STRING.in? ["2.1.0", "2.1.1"]
21
21
  end
22
22
  end
23
23
 
24
- ActionController::Routing::Routes.reload!
25
-
26
24
  else
27
25
  RAILS_DEFAULT_LOGGER.info "****"
28
26
  RAILS_DEFAULT_LOGGER.info "**** The file config/initializers/patch_routing.rb is not in use"
@@ -1,4 +1,4 @@
1
- <page>
1
+ <page title="Home">
2
2
 
3
3
  <body: class="front-page"/>
4
4
 
@@ -435,7 +435,6 @@ var Hobo = {
435
435
 
436
436
 
437
437
  fixSectionGroup: function(e) {
438
- alert(e.outerHTML)
439
438
  rows = e.childElements().map(function(e, i) {
440
439
  cells = e.childElements().map(function(e, i) {
441
440
  return e.outerHTML.sub("<DIV", "<td valign='top'").sub(/<\/DIV>$/i, "</td>")
@@ -133,12 +133,15 @@
133
133
 
134
134
 
135
135
  <def tag="collection-name" attrs="singular, lowercase, dasherize"><%=
136
- name = (attr = this.try.origin_attribute and attr.to_s) || type_name(:plural => true)
137
- name = name.titleize
138
- name = name.singularize if singular
139
- name = name.downcase if lowercase
140
- name = name.underscore.gsub('_', '-') if dasherize
141
- name
136
+ if (attr = this.try.origin_attribute)
137
+ name = attr.to_s
138
+ name = dasherize ? name.underscore.dasherize : name.titleize
139
+ name = name.singularize if singular
140
+ name = name.downcase if lowercase
141
+ name
142
+ else
143
+ type_name(:plural => !singular, :lowercase => lowercase, :dasherize => dasherize)
144
+ end
142
145
  %></def>
143
146
 
144
147
 
@@ -188,7 +191,7 @@
188
191
  # This target is registered with ModelRouter as not linkable
189
192
  content
190
193
  else
191
- css_class = target.try.origin_attribute || target.class.name.underscore
194
+ css_class = target.try.origin_attribute || target.class.name.underscore.dasherize
192
195
  add_classes!(attributes, "#{css_class}-link")
193
196
 
194
197
  href.sub!(/\?|$/, ".#{format}\\0") unless format.blank?
@@ -21,7 +21,7 @@
21
21
  %></def>
22
22
 
23
23
 
24
- <def tag="form" polymorphic attrs="update, hidden-fields, action, method, web-method, lifecycle, owner, enctype"><%=
24
+ <def tag="form" polymorphic attrs="update, hidden-fields, action, method, web-method, lifecycle, owner"><%=
25
25
  ajax_attrs, html_attrs = attributes.partition_hash(Hobo::RapidHelper::AJAX_ATTRS)
26
26
 
27
27
  new_record = this.try.new_record?
@@ -90,14 +90,12 @@
90
90
 
91
91
  if action.nil? # don't add automatic css classes if the action was specified
92
92
  if web_method
93
- add_classes!(html_attrs, "#{type_id}_#{web_method}_form")
93
+ add_classes!(html_attrs, "#{type_id}-#{web_method}-form")
94
94
  else
95
- add_classes!(html_attrs, "#{'new_' if new_record}#{type_id}")
95
+ add_classes!(html_attrs, "#{'new-' if new_record}#{type_id}")
96
96
  end
97
97
  end
98
98
 
99
- html_attrs[:enctype] = enctype
100
-
101
99
  Hobo::Dryml.last_if = true
102
100
  element("form", html_attrs, body)
103
101
  end
@@ -161,8 +159,13 @@
161
159
  <%= select_date(this || Time.now, attributes.merge(:prefix => param_name_for_this, :order => order)) %>
162
160
  </def>
163
161
 
162
+ <def tag="input" for="time" attrs="order">
163
+ <% order = order.nil? ? [:year, :month, :day, :hour, :minute, :second] : comma_split(order).*.to_sym -%>
164
+ <%= select_date(this || Time.now, attributes.merge(:prefix => param_name_for_this, :order => order)) %>
165
+ </def>
166
+
164
167
  <def tag="input" for="datetime" attrs="order">
165
- <% order = order.nil? ? [:year, :month, :day ] : comma_split(order).*.to_sym -%>
168
+ <% order = order.nil? ? [:year, :month, :day, :hour, :minute, :second] : comma_split(order).*.to_sym -%>
166
169
  <%= select_datetime(this || Time.now, attributes.merge(:prefix => param_name_for_this, :order => order)) %>
167
170
  </def>
168
171
 
@@ -277,7 +280,7 @@
277
280
  ajax_attributes = { :message => message }
278
281
  class_name = new.class.name.underscore
279
282
  ajax_attributes[:params] = { class_name => fields } unless fields.empty?
280
- func = ajax_updater(object_url(new.class), update, ajax_attributes)
283
+ func = ajax_updater(object_url(new.class, :method => :post), update, ajax_attributes)
281
284
  element :input, add_classes(attributes.merge(:type =>'button', :onclick => func, :value => label),
282
285
  "button create-button create-#{class_name}-button"), nil, true, true
283
286
  end
@@ -1,6 +1,6 @@
1
1
  require 'fileutils'
2
2
  require 'hobosupport'
3
- Dependencies.load_paths << File.dirname(__FILE__) + "/../lib"
3
+ ActiveSupport::Dependencies.load_paths << File.dirname(__FILE__) + "/../lib"
4
4
 
5
5
  require 'rexml/xpath'
6
6
  XPath = REXML::XPath
@@ -0,0 +1,261 @@
1
+ require "#{File.dirname __FILE__}/dryml_test_case"
2
+
3
+ class CompilationTest < DrymlTestCase
4
+
5
+ should "compile tag calls as method calls" do
6
+ assert_compiles_to "<% _output(foo.to_s) %>", "<foo/>"
7
+ end
8
+
9
+ should "convert dashes in tag names to underscores in compiled method calls" do
10
+ assert_compiles_to "<% _output(foo_baa.to_s) %>", "<foo-baa/>"
11
+ end
12
+
13
+ should "compile attributes as keyword parameters" do
14
+ assert_compiles_to '<% _output(foo({:a => "1", :b => "2"}, {})) %>', "<foo a='1' b='2'/>"
15
+ end
16
+
17
+ should "convert attribute names with dashes in tag calls to symbols with underscores" do
18
+ assert_compiles_to "<% _output(foo({:my_attribute => \"1\"}, {})) %>", "<foo my-attribute='1'/>"
19
+ end
20
+
21
+ should "compile code attributes as ruby code" do
22
+ assert_compiles_to '<% _output(foo({:a => (1 + 2)}, {})) %>', "<foo a='&1 + 2'/>"
23
+ end
24
+
25
+ should "compile attributes with no RHS as passing `true`" do
26
+ assert_compiles_to '<% _output(foo({:a => (true)}, {})) %>', "<foo a/>"
27
+ end
28
+
29
+ should "compile content of a tag call as the default parameter" do
30
+ assert_compiles_to "<% _output(foo({}, { :default => proc { |_foo__default_content| new_context { %>the body<% } }, })) %>",
31
+ "<foo>the body</foo>"
32
+ end
33
+
34
+ should "support <param_content/> inside the content of a tag" do
35
+ src = "<foo>!!<param-content/>??</foo>"
36
+ assert_compiles_to "<% _output(foo({}, { :default => proc { |_foo__default_content| new_context { %>!!<%= _foo__default_content && _foo__default_content.call %>??<% } }, })) %>", src
37
+ end
38
+
39
+ should "support the 'for' attribute on <param-content/>" do
40
+ src = "<x><y>123<param-content for='x'/>456</y></x>"
41
+ assert_compiles_to(
42
+ "<% _output(x({}, { :default => proc { |_x__default_content| new_context { %><% _output(y({}, { :default => proc { |_y__default_content| new_context { %>" +
43
+ "123<%= _x__default_content && _x__default_content.call %>456" +
44
+ "<% } }, })) %><% } }, })) %>", src)
45
+ end
46
+
47
+ should "allow :foo as a shorthand for field='foo' on tags" do
48
+ assert_compiles_to '<% _output(foo({:field => "name"}, {})) %>', "<foo:name/>"
49
+ end
50
+
51
+ should "allow static tag names like :title as a shorthand for field='title'" do
52
+ assert_compiles_to '<% _output(foo({:field => "name"}, {})) %>', "<foo:name/>"
53
+ end
54
+
55
+ should "allow close tags to ommit the :field_name part" do
56
+ assert_compiles_to '<% _output(foo({:field => "name"}, { :default => proc { |_foo__default_content| new_context { %><% } }, })) %>', "<foo:name></foo>"
57
+
58
+ end
59
+
60
+ should "compile tag calls with merge-attrs" do
61
+ assert_compiles_to "<% _output(foo(merge_attrs({},(attributes) || {}), {})) %>", "<foo merge-attrs/>"
62
+ assert_compiles_to '<% _output(foo(merge_attrs({:a => "1"},(attributes) || {}), {})) %>', "<foo a='1' merge-attrs/>"
63
+ end
64
+
65
+
66
+ # --- Compilation: Defining Tags --- #
67
+
68
+ should "compile defs" do
69
+ assert_compiles_to(
70
+ "<% def foo(all_attributes={}, all_parameters={}); " +
71
+ "parameters = Hobo::Dryml::TagParameters.new(all_parameters, []); " +
72
+ "all_parameters = Hobo::Dryml::TagParameters.new(all_parameters); " +
73
+ "_tag_context(all_attributes) do attributes, = _tag_locals(all_attributes, []) %>" +
74
+ "<% _erbout; end; end %>",
75
+
76
+ "<def tag='foo'></def>")
77
+
78
+ end
79
+
80
+ should "compile attrs in defs as local variables" do
81
+ assert_compiles_to(
82
+ "<% def foo(all_attributes={}, all_parameters={}); " +
83
+ "parameters = Hobo::Dryml::TagParameters.new(all_parameters, []); " +
84
+ "all_parameters = Hobo::Dryml::TagParameters.new(all_parameters); " +
85
+ "_tag_context(all_attributes) do " +
86
+ "a, my_attr, attributes, = _tag_locals(all_attributes, [:a, :my_attr]) %>" +
87
+ "<% _erbout; end; end %>",
88
+
89
+ "<def tag='foo' attrs='a, my-attr'></def>")
90
+ end
91
+
92
+ should "dissallow `param` outside of tag definitions" do
93
+ assert_raise(DrymlException) { compile_dryml("<foo param/>") }
94
+ end
95
+
96
+ should "compile param-tag calls as calls to `call_tag_parameter`" do
97
+ assert_compiles_to '<% _output(call_tag_parameter(:foo, {:a => "1"}, {}, all_parameters, :foo)) %>',
98
+ "<foo param a='1'/>",
99
+ :in_def
100
+ end
101
+
102
+ should "compile with support for named params" do
103
+ assert_compiles_to "<% _output(call_tag_parameter(:foo, {}, {}, all_parameters, :zap)) %>", "<foo param='zap'/>", :in_def
104
+ end
105
+
106
+ should "compile a param tag-call with a body" do
107
+ assert_compiles_to "<% _output(call_tag_parameter(:foo, {}, { :default => proc { |_foo__default_content| new_context { %>abc<% } }, }, all_parameters, :foo)) %>",
108
+ "<foo param>abc</foo>",
109
+ :in_def
110
+ end
111
+
112
+ should "compile a param tag-call with a body and a call to <param_content/>" do
113
+ assert_compiles_to "<% _output(call_tag_parameter(:foo, {}, { :default => proc { |_foo__default_content| new_context { %>!!<%= _foo__default_content && _foo__default_content.call %>!!<% } }, }, all_parameters, :foo)) %>",
114
+ "<foo param>!!<param-content/>!!</foo>",
115
+ :in_def
116
+
117
+ end
118
+
119
+ should "compile param template-calls as calls to `call_tag_parameter`" do
120
+ assert_compiles_to "<% _output(call_tag_parameter(:foo, {}, {}, all_parameters, :foo)) %>",
121
+ "<foo param/>",
122
+ :in_def
123
+ end
124
+
125
+ should "compile param tag calls with parameters as calls to `call_tag_parameter`" do
126
+ assert_compiles_to '<% _output(call_tag_parameter(:foo, {}, {:a => proc { [{:x => "1"}, {}] }, }, all_parameters, :foo)) %>',
127
+ "<foo param><a: x='1'/></foo>",
128
+ :in_def
129
+ end
130
+
131
+ should "compile parameters with param" do
132
+ assert_compiles_to '<% _output(foo({}, {:abc => merge_tag_parameter(proc { [{}, {}] }, all_parameters[:abc]), })) %>',
133
+ "<foo><abc: param/></foo>",
134
+ :in_def
135
+ end
136
+
137
+ should "compile tag parameters with named params" do
138
+ assert_compiles_to '<% _output(foo({}, {:abc => merge_tag_parameter(proc { [{}, {}] }, all_parameters[:x]), })) %>',
139
+ "<foo><abc: param='x'/></foo>",
140
+ :in_def
141
+ end
142
+
143
+ should "compile tag parameters with param and attributes" do
144
+ assert_compiles_to '<% _output(foo({}, {:abc => merge_tag_parameter(proc { [{:a => "b"}, {}] }, all_parameters[:x]), })) %>',
145
+ "<foo><abc: param='x' a='b'/></foo>",
146
+ :in_def
147
+ end
148
+
149
+ should "compile tag parameters with param and a tag body" do
150
+ assert_compiles_to(
151
+ '<% _output(foo({}, {:abc => merge_tag_parameter(' +
152
+ 'proc { [{}, { :default => proc { |_abc__default_content| new_context { %>ha!<% } }, }] }, all_parameters[:abc]), })) %>',
153
+ "<foo><abc: param>ha!</abc></foo>",
154
+ :in_def)
155
+
156
+ end
157
+
158
+ should "compile tag parameters with param and nested parameters" do
159
+ assert_compiles_to(
160
+ '<% _output(foo({}, {:baa => merge_tag_parameter(' +
161
+ 'proc { [{}, {:x => proc { [{}, { :default => proc { |_x__default_content| new_context { %>hello<% } }, }] }, }] }, all_parameters[:baa]), })) %>',
162
+ "<foo><baa: param><x:>hello</x:></baa:></foo>",
163
+ :in_def)
164
+ end
165
+
166
+ # --- Compilation: Calling tags with parameters --- #
167
+
168
+ should "compile tag parameters as procs" do
169
+ assert_compiles_to(
170
+ '<% _output(foo({}, {' +
171
+ ':x => proc { [{}, { :default => proc { |_x__default_content| new_context { %>hello<% } }, }] }, ' +
172
+ ':y => proc { [{}, { :default => proc { |_y__default_content| new_context { %>world<% } }, }] }, })) %>',
173
+ "<foo><x:>hello</x><y:>world</y:></foo>"
174
+ )
175
+ end
176
+
177
+ should "compile tag parameters with attributes" do
178
+ assert_compiles_to(
179
+ '<% _output(foo({}, {:abc => proc { [{:x => "1"}, { :default => proc { |_abc__default_content| new_context { %>hello<% } }, }] }, })) %>',
180
+ "<foo><abc: x='1'>hello</abc></foo>"
181
+ )
182
+ end
183
+
184
+ should "allow :foo as a shorthand for field='foo' on template tags" do
185
+ assert_compiles_to '<% _output(foo({:field => "name"}, {})) %>', "<foo:name/>"
186
+ end
187
+
188
+ should "compile template parameters which are themselves templates" do
189
+ # Tag parameters with nested tag parameters are procs that return
190
+ # a pair of hashes, the first is the attributes, the second is the
191
+ # sub-template procs
192
+ assert_compiles_to(
193
+ '<% _output(foo({}, ' +
194
+ '{:baa => proc { [{:x => "1"}, {:a => proc { [{}, { :default => proc { |_a__default_content| new_context { %>hello<% } }, }] }, }] }, })) %>',
195
+ "<foo><baa: x='1'><a:>hello</a></baa></foo>")
196
+ end
197
+
198
+ should "compile 'replace' parameters" do
199
+ # A replace parameter is detected at runtime by the arity of the
200
+ # block == 1 (for a normal parameter it would be 0). See
201
+ # TemplateEnvironment#call_tag_parameter
202
+ assert_compiles_to(
203
+ '<% _output(page({}, {:head_replacement => proc { |_head_restore| new_context { %>abc<% } }, })) %>',
204
+ "<page><head: replace>abc</head></page>"
205
+ )
206
+ end
207
+
208
+ should "compile 'replace' parameters where the restore contains a default parameter call" do
209
+ assert_compiles_to(
210
+ '<% _output(page({}, {:head_replacement => proc { |_head_restore| new_context { %>abc ' +
211
+ '<% _output(_head_restore.call({}, { :default => proc { |_head__default_content| new_context { %>blah<% } }, })) %>' +
212
+ '<% } }, })) %>',
213
+
214
+ "<page><head: replace>abc <head restore>blah</head></head></page>"
215
+ )
216
+ end
217
+
218
+ should "compile 'replace' tag parameters with a default parameter call" do
219
+ assert_compiles_to(
220
+ '<% _output(page({}, {:head_replacement => proc { |_head_restore| new_context { %>abc ' +
221
+ '<% _output(_head_restore.call({}, {})) %>' +
222
+ '<% } }, })) %>',
223
+ "<page><head: replace>abc <head restore/></head></page>")
224
+ end
225
+
226
+
227
+ # --- Compilation: Syntax sugar for before, after, append, prepend --- #
228
+
229
+ should "compile 'before' parameters" do
230
+ assert_compiles_to(
231
+ '<% _output(page({}, {:head_replacement => proc { |_head_restore| new_context { %>abc' +
232
+ '<% _output(_head_restore.call({}, {})) %>' +
233
+ '<% } }, })) %>',
234
+ "<page><before-head:>abc</before-head></page>")
235
+ end
236
+
237
+ should "compile 'after' parameters" do
238
+ assert_compiles_to(
239
+ '<% _output(page({}, {:head_replacement => proc { |_head_restore| new_context { %>' +
240
+ '<% _output(_head_restore.call({}, {})) %>' +
241
+ 'abc<% } }, })) %>',
242
+ "<page><after-head:>abc</after-head></page>")
243
+ end
244
+
245
+ should "compile 'apppend' parameters" do
246
+ assert_compiles_to(
247
+ '<% _output(page({}, {:head => proc { [{}, { :default => proc { |_head__default_content| new_context { %>' +
248
+ '<%= _head__default_content && _head__default_content.call %>:o)' +
249
+ '<% } } } ] }, })) %>',
250
+ "<page><append-head:>:o)</append-head></page>")
251
+ end
252
+
253
+ should "compile 'prepend' parameters" do
254
+ assert_compiles_to(
255
+ '<% _output(page({}, {:head => proc { [{}, { :default => proc { |_head__default_content| new_context { %>' +
256
+ ':o)<%= _head__default_content && _head__default_content.call %>' +
257
+ '<% } } } ] }, })) %>',
258
+ "<page><prepend-head:>:o)</prepend-head></page>")
259
+ end
260
+
261
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hobo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Locke
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-09-08 00:00:00 +01:00
12
+ date: 2008-09-14 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 0.8.1
23
+ version: 0.8.2
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: hobofields
@@ -30,7 +30,7 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.8.1
33
+ version: 0.8.2
34
34
  version:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: rails
@@ -38,7 +38,7 @@ dependencies:
38
38
  version_requirement:
39
39
  version_requirements: !ruby/object:Gem::Requirement
40
40
  requirements:
41
- - - "="
41
+ - - ">="
42
42
  - !ruby/object:Gem::Version
43
43
  version: "2.1"
44
44
  version:
@@ -52,16 +52,6 @@ dependencies:
52
52
  - !ruby/object:Gem::Version
53
53
  version: 2.2.1
54
54
  version:
55
- - !ruby/object:Gem::Dependency
56
- name: echoe
57
- type: :development
58
- version_requirement:
59
- version_requirements: !ruby/object:Gem::Requirement
60
- requirements:
61
- - - ">="
62
- - !ruby/object:Gem::Version
63
- version: "0"
64
- version:
65
55
  description: The web app builder for Rails
66
56
  email: tom@tomlocke.com
67
57
  executables:
@@ -278,9 +268,9 @@ files:
278
268
  - tasks/fix_dryml.rake
279
269
  - tasks/generate_tag_reference.rb
280
270
  - tasks/hobo_tasks.rake
281
- - test/test_generator_helper.rb
282
- - test/test_helper.rb
283
- - test/test_hobo_model_controller_generator.rb
271
+ - test/generators/test_generator_helper.rb
272
+ - test/generators/test_helper.rb
273
+ - test/generators/test_hobo_model_controller_generator.rb
284
274
  - uninstall.rb
285
275
  - hobo.gemspec
286
276
  has_rdoc: true
@@ -315,6 +305,7 @@ signing_key:
315
305
  specification_version: 2
316
306
  summary: The web app builder for Rails
317
307
  test_files:
318
- - test/test_generator_helper.rb
319
- - test/test_helper.rb
320
- - test/test_hobo_model_controller_generator.rb
308
+ - test/dryml/complilation_test.rb
309
+ - test/generators/test_generator_helper.rb
310
+ - test/generators/test_helper.rb
311
+ - test/generators/test_hobo_model_controller_generator.rb