hobo 0.8.1 → 0.8.2

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.
@@ -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