hobo 1.4.0.pre8 → 2.0.0.pre1

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.
Files changed (60) hide show
  1. data/CHANGES-1.4.txt +87 -3
  2. data/TODO-1.4.txt +3 -11
  3. data/VERSION +1 -1
  4. data/app/helpers/hobo_route_helper.rb +61 -20
  5. data/lib/generators/hobo/admin_subsite/USAGE +3 -11
  6. data/lib/generators/hobo/admin_subsite/admin_subsite_generator.rb +4 -1
  7. data/lib/generators/hobo/admin_subsite/templates/{site.css.erb → site.scss.erb} +0 -0
  8. data/lib/generators/hobo/assets/assets_generator.rb +2 -2
  9. data/lib/generators/hobo/assets/templates/{application.css → application.scss} +0 -0
  10. data/lib/generators/hobo/assets/templates/{front.css → front.scss} +0 -0
  11. data/lib/generators/hobo/model/templates/model_injection.rb.erb +1 -0
  12. data/lib/generators/hobo/plugin.rb +3 -1
  13. data/lib/generators/hobo/routes/router.rb +115 -0
  14. data/lib/generators/hobo/routes/templates/hobo_routes.rb.erb +42 -3
  15. data/lib/generators/hobo/setup_wizard/setup_wizard_generator.rb +35 -2
  16. data/lib/generators/hobo/subsite.rb +1 -1
  17. data/lib/generators/hobo/subsite/USAGE +3 -11
  18. data/lib/generators/hobo/subsite/subsite_generator.rb +3 -0
  19. data/lib/generators/hobo/subsite/templates/{site.css.erb → site.scss.erb} +0 -0
  20. data/lib/generators/hobo/subsite_taglib/subsite_taglib_generator.rb +4 -1
  21. data/lib/generators/hobo/user_mailer/templates/activation.erb +1 -1
  22. data/lib/generators/hobo/user_mailer/templates/forgot_password.erb +1 -1
  23. data/lib/generators/hobo/user_mailer/templates/invite.erb +1 -1
  24. data/lib/generators/hobo/user_model/templates/model_injection.rb.erb +1 -0
  25. data/lib/hobo.rb +2 -2
  26. data/lib/hobo/controller.rb +3 -11
  27. data/lib/hobo/controller/model.rb +89 -89
  28. data/lib/hobo/engine.rb +12 -0
  29. data/lib/hobo/extensions/active_record/permissions.rb +15 -24
  30. data/lib/hobo/model.rb +3 -0
  31. data/lib/hobo/model/permissions.rb +1 -1
  32. data/lib/hobo/rapid/generators/rapid/cards.dryml.erb +10 -3
  33. data/lib/hobo/rapid/generators/rapid/forms.dryml.erb +9 -2
  34. data/lib/hobo/rapid/generators/rapid/pages.dryml.erb +11 -4
  35. data/lib/hobo/routes.rb +2 -0
  36. data/test/doctest/hobo/hobo_helper.rdoctest +23 -20
  37. data/test/doctest/hobo/lifecycles.rdoctest +1 -0
  38. data/test/doctest/hobo/model.rdoctest +4 -0
  39. data/test/doctest/hobo/multi_model_forms.rdoctest +2 -0
  40. data/test/doctest/hobo/scopes.rdoctest +18 -5
  41. data/test/doctest/prepare_testapp.rb +4 -2
  42. data/test/irt/generators/admin_subsite.irt +2 -6
  43. data/test/irt/generators/assets.irt +1 -7
  44. data/test/irt/generators/front_controller.irt +1 -3
  45. data/test/irt/generators/model.irt +1 -2
  46. data/test/irt/generators/partials/_account_user_model_tests.rb +1 -3
  47. data/test/irt/generators/partials/_accounts_users_controller_tests.rb +1 -3
  48. data/test/irt/generators/partials/_default_user_model_tests.rb +1 -3
  49. data/test/irt/generators/partials/_default_users_controller_tests.rb +1 -3
  50. data/test/irt/generators/partials/_house_controller_tests.rb +1 -3
  51. data/test/irt/generators/partials/_user_mailer_tests.rb +1 -3
  52. data/test/irt/generators/subsite.irt +5 -6
  53. data/test/irt/generators/user_mailer.irt +2 -0
  54. metadata +12 -18
  55. data/lib/generators/hobo/rapid/templates/themes/clean-sidemenu/public/images/100-ACD3E6-DBE1E5-H.png +0 -0
  56. data/lib/generators/hobo/rapid/templates/themes/clean-sidemenu/public/images/100-DBE1E5-FCFEF5-H.png +0 -0
  57. data/lib/generators/hobo/rapid/templates/themes/clean-sidemenu/public/images/300-3B5F87-ACD3E6-H.png +0 -0
  58. data/lib/generators/hobo/rapid/templates/themes/clean-sidemenu/public/images/spinner.gif +0 -0
  59. data/lib/generators/hobo/rapid/templates/themes/clean-sidemenu/public/stylesheets/clean-sidemenu.css +0 -81
  60. data/lib/generators/hobo/rapid/templates/themes/clean-sidemenu/views/clean-sidemenu.dryml +0 -30
@@ -86,5 +86,17 @@ module Hobo
86
86
  end
87
87
  end
88
88
 
89
+ # hobo_field's rich types let you refer to rich type with symbols:
90
+ # fields do; shout :loud; end.
91
+ # The problem comes if you never use LoudText in your code, rails
92
+ # autoloader will never kick in and autoload
93
+ # app/rich_types/loud_text.rb, so let's preemptively require
94
+ # everything in that directory.
95
+ initializer 'hobo.rich_types' do |app|
96
+ Dir["#{Rails.root}/app/rich_types/*"].each do |file|
97
+ require_dependency file
98
+ end
99
+ end
100
+
89
101
  end
90
102
  end
@@ -68,34 +68,25 @@ ActiveRecord::Associations::HasManyThroughAssociation.class_eval do
68
68
  end
69
69
 
70
70
 
71
- def create!(attrs = nil)
71
+ def create_record_with_user_create(attrs, options, raise = false, &block)
72
72
  klass = @reflection.klass
73
73
  user = acting_user if klass < Hobo::Model
74
- klass.transaction do
75
- object = if attrs
76
- klass.send(:with_scope, :create => attrs) { user ? klass.user_create!(user) : klass.create! }
77
- else
78
- user ? klass.user_create!(user) : klass.create!
79
- end
80
- self << object
81
- object
82
- end
83
- end
84
-
85
-
86
- def create(attrs = nil)
87
- klass = @reflection.klass
88
- user = acting_user if klass < Hobo::Model
89
- klass.transaction do
90
- object = if attrs
91
- klass.send(:with_scope, :create => attrs) { user ? klass.user_create(user) : klass.create }
92
- else
93
- user ? klass.user_create(user) : klass.create
94
- end
95
- self << object
96
- object
74
+ if user
75
+ if attributes.is_a?(Array)
76
+ attributes.collect { |attr| create_record(attr, options, raise, &block) }
77
+ else
78
+ transaction do
79
+ add_to_target(klass.user_create(attributes)) do |record|
80
+ yield(record) if block_given?
81
+ insert_record(record, true, raise)
82
+ end
83
+ end
84
+ end
85
+ else
86
+ create_record_without_user_create(attrs, options, raise, &block)
97
87
  end
98
88
  end
89
+ alias_method_chain :create_record, :user_create
99
90
 
100
91
 
101
92
  def insert_record_with_owner_attributes(record, force = true, raise = false)
@@ -20,6 +20,9 @@ module Hobo
20
20
  inheriting_cattr_reader :default_order
21
21
  alias_method_chain :attributes=, :hobo_type_conversion
22
22
 
23
+ cattr_accessor :hobo_controller
24
+ self.hobo_controller = {}
25
+
23
26
  include Permissions
24
27
  include Lifecycles::ModelExtensions
25
28
  include FindFor
@@ -257,7 +257,7 @@ module Hobo
257
257
  def attribute_protected?(attribute)
258
258
  attribute = attribute.to_s
259
259
 
260
- return true if self.class.attributes_protected_by_default.include? attribute
260
+ return true if self.class.send(:attributes_protected_by_default).include? attribute
261
261
 
262
262
  if !self.class.accessible_attributes.empty?
263
263
  return true if !self.class.accessible_attributes.include?(attribute)
@@ -1,3 +1,10 @@
1
+ <% # routing's not available yet, so we just guess based on presence
2
+ # of methods
3
+ def linkable?(model, action)
4
+ model.hobo_controller[subsite] && model.hobo_controller[subsite].public_instance_methods.include?(action)
5
+ end
6
+
7
+ %>
1
8
  <% each_model do -%>
2
9
  <%
3
10
  name_attribute = model.name_attribute
@@ -10,9 +17,9 @@ if creator_attribute
10
17
  creator_link = creator_refl && linkable?(creator_refl.klass, :show)
11
18
  end
12
19
 
13
- show_link = linkable?(:show)
14
- edit_link = !show_link && linkable?(:edit)
15
- delete_button = !show_link && !edit_link && linkable?(:destroy, :method => :delete)
20
+ show_link = linkable?(model, :show)
21
+ edit_link = !show_link && linkable?(model, :edit)
22
+ delete_button = !show_link && !edit_link && linkable?(model, :destroy)
16
23
 
17
24
  has_actions = edit_link || delete_button
18
25
  has_body = (!show_link && description_attribute) || creator_link || creator_attribute || primary_collection
@@ -1,10 +1,17 @@
1
+ <% # routing's not available yet, so we just guess based on presence
2
+ # of methods
3
+ def linkable?(model, action)
4
+ model.hobo_controller[subsite] && model.hobo_controller[subsite].public_instance_methods.include?(action)
5
+ end
6
+
7
+ %>
1
8
  <% each_controller do -%>
2
9
  <%
3
10
  next unless @controller < Hobo::Controller::Model
4
11
  form_fields = standard_fields :belongs_to, :has_many
5
12
 
6
- cancel_to_show_page = linkable?(:show)
7
- cancel_to_index_page = !cancel_to_index_page && linkable?(:index)
13
+ cancel_to_show_page = linkable?(model, :show)
14
+ cancel_to_index_page = !cancel_to_index_page && linkable?(model, :index)
8
15
  model_key = model.to_s.underscore
9
16
  -%>
10
17
  <def tag="form" for="<%= model.name %>">
@@ -1,3 +1,10 @@
1
+ <% # routing's not available yet, so we just guess based on presence
2
+ # of methods
3
+ def linkable?(model, action)
4
+ model.hobo_controller[subsite] && model.hobo_controller[subsite].public_instance_methods.include?(action)
5
+ end
6
+
7
+ %>
1
8
  <!-- ====== Main Navigation ====== -->
2
9
 
3
10
  <def tag="main-nav">
@@ -15,8 +22,8 @@
15
22
  <% next unless @controller < Hobo::Controller::Model %>
16
23
  <!-- ====== <%= model.name %> Pages ====== -->
17
24
  <%
18
- new_link = linkable?(:new)
19
- new_form = !new_link && linkable?(model, :create, :method => :post)
25
+ new_link = linkable?(model, :new)
26
+ new_form = !new_link && linkable?(model, :create)
20
27
  model_key = model.to_s.underscore
21
28
  -%>
22
29
 
@@ -106,7 +113,7 @@ back_link_human_name = back_link_human_name && back_link_human_name.model_name.h
106
113
  boolean_fields = model.table_exists? ? (model.columns.select { |c| c.type == :boolean }.*.name - model.view_hints.inline_booleans) : []
107
114
  creator = model.creator_attribute
108
115
  creator_link = creator && model.reflections[creator] && linkable?(model.reflections[creator].klass, :show)
109
- edit_link = linkable?(:edit)
116
+ edit_link = linkable?(model, :edit)
110
117
  main_content = model.primary_content_attribute
111
118
  show_fields = standard_fields(:belongs_to).*.to_s - [model.name_attribute, main_content, creator, back_link, *boolean_fields].*.to_s
112
119
 
@@ -118,7 +125,7 @@ if collection
118
125
  owner = model.reverse_reflection(collection)._?.name
119
126
  if owner
120
127
  add_link = collection && linkable?(collection_class, :"new_for_#{owner}")
121
- add_form = !add_link && linkable?(collection_class, :"create_for_#{owner}", :method => :post)
128
+ add_form = !add_link && linkable?(collection_class, :"create_for_#{owner}")
122
129
  end
123
130
  end
124
131
 
@@ -17,10 +17,12 @@ module Hobo
17
17
  end
18
18
 
19
19
  def linkable?(klass, action, options={})
20
+ #raise Hobo::Error, "deprecated"
20
21
  @linkable_keys.member? linkable_key(klass, action, options)
21
22
  end
22
23
 
23
24
  def models_with(wanted_action)
25
+ raise Hobo::Error, "deprecated"
24
26
  @linkable_keys.map do |k|
25
27
  subsite, class_name, action, method = k.split('/')
26
28
  (action == wanted_action.to_s) ? class_name.constantize : nil
@@ -1,5 +1,6 @@
1
1
  doctest: prepare testapp environment
2
2
  doctest_require: '../prepare_testapp'
3
+ doctest_require: 'mocha'
3
4
 
4
5
  # Hobo::Helper
5
6
 
@@ -22,35 +23,37 @@ Useful stuff
22
23
  >> def init_mocha; $stubba = Mocha::Central.new; end
23
24
  >> def mock; Mocha::Mockery.instance.named_mock 'mock'; end
24
25
 
25
- ## `object_url`
26
+ # object_url now uses polymorphic_url, so this is completely out of date. FIXME
26
27
 
27
- Returns a canonical restful URL for a given object. THe Hobo routing is checked and URLs are only returned for routes that exist.
28
+ # ## `object_url`
28
29
 
29
- Note that `object_url` doesn't perform "reverse routing". It knows nothing about attractive URLs you may have declared in your routes file.
30
+ # Returns a canonical restful URL for a given object. THe Hobo routing is checked and URLs are only returned for routes that exist.
30
31
 
31
- Something to link to:
32
+ # Note that `object_url` doesn't perform "reverse routing". It knows nothing about attractive URLs you may have declared in your routes file.
32
33
 
33
- >> init_mocha
34
- >> class Thing; end
35
- >> thing = Thing.new
36
- >> thing.expects(:to_url_path).at_least_once.returns("things/1")
34
+ # Something to link to:
37
35
 
38
- ### Simple 'show' URLs
36
+ # >> init_mocha
37
+ # >> class Thing; end
38
+ # >> thing = Thing.new
39
+ # >> thing.expects(:to_url_path).at_least_once.returns("things/1")
39
40
 
40
- >> Hobo::Routes.expects(:linkable?).with(Thing, :show, {:subsite => ''}).returns(true)
41
- >> View.object_url(thing)
42
- => "/things/1"
41
+ # ### Simple 'show' URLs
43
42
 
44
- Returns nil if Routes says it's not linkable
43
+ # >> Hobo::Routes.expects(:linkable?).with(Thing, :show, {:subsite => ''}).returns(true)
44
+ # >> View.object_url(thing)
45
+ # => "/things/1"
45
46
 
46
- >> Hobo::Routes.expects(:linkable?).with(Thing, :show, {:subsite => ''}).returns(false)
47
- >> View.object_url(thing)
48
- => nil
47
+ # Returns nil if Routes says it's not linkable
49
48
 
50
- A URL to the 'edit' page:
49
+ # >> Hobo::Routes.expects(:linkable?).with(Thing, :show, {:subsite => ''}).returns(false)
50
+ # >> View.object_url(thing)
51
+ # => nil
51
52
 
52
- >> Hobo::Routes.expects(:linkable?).with(Thing, :edit, {:subsite => ''}).returns(true)
53
- >> View.object_url(thing, :edit)
54
- => "/things/1/edit"
53
+ # A URL to the 'edit' page:
54
+
55
+ # >> Hobo::Routes.expects(:linkable?).with(Thing, :edit, {:subsite => ''}).returns(true)
56
+ # >> View.object_url(thing, :edit)
57
+ # => "/things/1/edit"
55
58
 
56
59
 
@@ -26,6 +26,7 @@ A user model for our example:
26
26
  fields do
27
27
  name :string
28
28
  end
29
+ attr_accessible :name
29
30
  end
30
31
 
31
32
  Now the friendship. For now we'll just declare the *invite* part of the lifecycle. We first declare the *states* -- there's only one for now. We then declare the *invite* action. This is the action that first creates the friendship, so we declare it with `create`:
@@ -44,6 +44,7 @@ declaration:
44
44
  title :string, :name => true, :index => true
45
45
  content :text, :primary_content => true
46
46
  end
47
+ attr_accessible :title, :content, :poster, :poster_id
47
48
 
48
49
  belongs_to :poster, :class_name => "User", :creator => true
49
50
 
@@ -122,6 +123,7 @@ object. In this case, you can provide your own name method instead:
122
123
  first_name :string
123
124
  last_name :string
124
125
  end
126
+ attr_accessible :first_name, :last_name
125
127
 
126
128
  def name
127
129
  first_name + ' ' + last_name
@@ -185,6 +187,7 @@ used elsewhere.
185
187
  fields do
186
188
  email_address :string, :login => true, :unique => true
187
189
  end
190
+ attr_accessible :email_address
188
191
  end
189
192
 
190
193
  >> User.login_attribute
@@ -214,6 +217,7 @@ case the `login_attribute` is saved to the field:
214
217
  fields do
215
218
  creator_login :string, :creator => true
216
219
  end
220
+ attr_accessible :creator_login
217
221
  end
218
222
 
219
223
  >> Foo2.creator_attribute
@@ -54,12 +54,14 @@ are the models:
54
54
  hobo_model
55
55
  fields { name :string }
56
56
  has_many :bars, :accessible => true
57
+ attr_accessible :name, :bars
57
58
  end
58
59
  >>
59
60
  class Bar < ActiveRecord::Base
60
61
  hobo_model
61
62
  fields { name :string }
62
63
  belongs_to :foo
64
+ attr_accessible :name, :foo, :foo_id
63
65
  end
64
66
  >> migrate
65
67
 
@@ -36,7 +36,8 @@ Nobody but the computer needs to read the rest of this section.
36
36
 
37
37
  Let's set up a few models for our testing:
38
38
 
39
- >>
39
+ >> File.open("#{Rails.root}/app/models/person.rb", "w") do |f|
40
+ f.write("""
40
41
  class Person < ActiveRecord::Base
41
42
  hobo_model
42
43
 
@@ -47,6 +48,7 @@ Let's set up a few models for our testing:
47
48
  male :boolean
48
49
  timestamps
49
50
  end
51
+ attr_accessible :name, :born_at, :code, :male
50
52
 
51
53
  lifecycle(:key_timestamp_field => false) do
52
54
  state :inactive, :active
@@ -55,19 +57,30 @@ Let's set up a few models for our testing:
55
57
  has_many :friendships
56
58
  has_many :friends, :through => :friendships
57
59
  end
58
-
59
- >>
60
+ """)
61
+ end
62
+ >> File.open("#{Rails.root}/app/models/friendship.rb", "w") do |f|
63
+ f.write("""
60
64
  class Friendship < ActiveRecord::Base
61
65
  hobo_model
62
66
  fields
67
+ attr_accessible :person, :friend
63
68
  belongs_to :person
64
- belongs_to :friend, :class_name => "Person"
69
+ belongs_to :friend, :class_name => 'Person'
70
+ end
71
+ """)
65
72
  end
66
73
 
67
74
  Generate a migration and run it:
68
75
  {.hidden}
69
76
 
70
- >> ActiveRecord::Migration.class_eval(Generators::Hobo::Migration::Migrator.run[0])
77
+ >> File.open("m.txt", "w") {|f| f.write("m\n\n")}
78
+ >> system("rails g hobo:migration < m.txt")
79
+ >> ActionDispatch::Reloader.cleanup!
80
+ >> ActionDispatch::Reloader.prepare!
81
+ >> Person.connection.clear_cache!
82
+ >> Person.connection.schema_cache.clear!
83
+ >> Person.reset_column_information
71
84
  >> Person.columns.*.name
72
85
  => ["id", "name", "born_at", "code", "male", "created_at", "updated_at", "state"]
73
86
  {.hidden}
@@ -3,9 +3,11 @@ require 'tmpdir'
3
3
 
4
4
  TESTAPP_PATH = ENV['TESTAPP_PATH'] || File.join(Dir.tmpdir, 'hobo_testapp')
5
5
  system %(rake test:prepare_testapp TESTAPP_PATH=#{TESTAPP_PATH})
6
- system %(echo "gem 'mocha'" >> #{TESTAPP_PATH}/Gemfile)
6
+ system %(echo "gem 'mocha', :require => false" >> #{TESTAPP_PATH}/Gemfile)
7
+ system %(echo "gem 'test-unit'" >> #{TESTAPP_PATH}/Gemfile)
7
8
  FileUtils.chdir TESTAPP_PATH
8
9
  require "#{TESTAPP_PATH}/config/environment"
9
10
  require 'rails/generators'
10
- Rails::Generators.configure!
11
+ Rails::Generators.configure!(Rails.application.config.generators)
12
+
11
13
 
@@ -1,9 +1,5 @@
1
1
  invoke 'hobo:assets', %w[ -q ]
2
- invoke 'hobo:admin_subsite', %w[ -q --make-front-site=false ]
2
+ invoke 'hobo:admin_subsite', %w[ -q ]
3
3
  desc "Admin Subsite files exist"
4
- files_exist? %w[ app/controllers/admin/admin_site_controller.rb
5
- app/controllers/admin/users_controller.rb
6
- app/helpers/admin/users_helper.rb
7
- app/views/taglibs/admin_site.dryml
8
- ]
4
+ files_exist? %w( app/controllers/admin/admin_site_controller.rb app/controllers/admin/users_controller.rb app/helpers/admin/users_helper.rb app/views/taglibs/admin_site.dryml )
9
5
  test_value_eql? true
@@ -1,11 +1,5 @@
1
1
  desc "hobo:assets invoke"
2
2
  invoke 'hobo:assets', %w(-q)
3
3
 
4
- files_exist? %w[ app/views/taglibs/application.dryml
5
- app/assets/stylesheets/application.css
6
- app/assets/stylesheets/front.css
7
- app/assets/javascripts/application.js
8
- app/assets/javascripts/front.js
9
- app/models/guest.rb
10
- ]
4
+ files_exist? %w( app/views/taglibs/application.dryml app/assets/stylesheets/application.scss app/assets/stylesheets/front.scss app/assets/javascripts/application.js app/assets/javascripts/front.js app/models/guest.rb )
11
5
  test_value_eql? true
@@ -1,8 +1,6 @@
1
1
  invoke 'hobo:front_controller', %w[ -q ]
2
2
  desc "All files exist"
3
- files_exist? %w[ app/controllers/front_controller.rb
4
- app/helpers/front_helper.rb
5
- app/views/front/index.dryml ]
3
+ files_exist? %w( app/controllers/front_controller.rb app/helpers/front_helper.rb app/views/front/index.dryml )
6
4
  test_value_eql? true
7
5
 
8
6
  desc "public/index.html removed"
@@ -5,8 +5,7 @@ eval_file '../partials/_house_model_tests.rb'
5
5
  invoke 'hobo:model', %w(nest/ed alpha:string -q)
6
6
 
7
7
  desc "Nested files exist"
8
- files_exist? %w[ app/models/nest/ed.rb
9
- app/models/nest.rb ]
8
+ files_exist? %w( app/models/nest/ed.rb app/models/nest.rb )
10
9
  test_value_eql? true
11
10
 
12
11
  desc "Nested injection matches"
@@ -1,7 +1,5 @@
1
1
  desc "Account Model files exist"
2
- files_exist? %w[ app/models/account.rb
3
- app/models/account.rb
4
- ]
2
+ files_exist? %w(app/models/account.rb)
5
3
  test_value_eql? true
6
4
 
7
5
  desc "Account Model injection matches"
@@ -1,7 +1,5 @@
1
1
  desc "All controller files exists"
2
- files_exist? %w[ app/controllers/accounts_controller.rb
3
- app/helpers/accounts_helper.rb
4
- ]
2
+ files_exist? %w( app/controllers/accounts_controller.rb app/helpers/accounts_helper.rb )
5
3
  test_value_eql? true
6
4
 
7
5
 
@@ -1,7 +1,5 @@
1
1
  desc "All files exists"
2
- files_exist? %w[ app/models/user.rb
3
- app/models/user.rb
4
- ]
2
+ files_exist? %w( app/models/user.rb )
5
3
  test_value_eql? true
6
4
 
7
5
  desc "User Model injection matches"