hobo 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data/LICENSE.txt +22 -0
  2. data/README.txt +18 -0
  3. data/bin/hobo +81 -0
  4. data/hobo_files/plugin/CHANGES.txt +963 -0
  5. data/hobo_files/plugin/LICENSE.txt +22 -0
  6. data/hobo_files/plugin/README +4 -0
  7. data/hobo_files/plugin/Rakefile +11 -0
  8. data/hobo_files/plugin/generators/hobo/hobo_generator.rb +37 -0
  9. data/hobo_files/plugin/generators/hobo/templates/application.dryml +2 -0
  10. data/hobo_files/plugin/generators/hobo/templates/guest.rb +31 -0
  11. data/hobo_files/plugin/generators/hobo_front_controller/USAGE +11 -0
  12. data/hobo_files/plugin/generators/hobo_front_controller/hobo_front_controller_generator.rb +90 -0
  13. data/hobo_files/plugin/generators/hobo_front_controller/templates/controller.rb +51 -0
  14. data/hobo_files/plugin/generators/hobo_front_controller/templates/functional_test.rb +18 -0
  15. data/hobo_files/plugin/generators/hobo_front_controller/templates/helper.rb +2 -0
  16. data/hobo_files/plugin/generators/hobo_front_controller/templates/index.dryml +43 -0
  17. data/hobo_files/plugin/generators/hobo_front_controller/templates/login.dryml +44 -0
  18. data/hobo_files/plugin/generators/hobo_front_controller/templates/search.dryml +18 -0
  19. data/hobo_files/plugin/generators/hobo_front_controller/templates/signup.dryml +45 -0
  20. data/hobo_files/plugin/generators/hobo_model/USAGE +26 -0
  21. data/hobo_files/plugin/generators/hobo_model/hobo_model_generator.rb +38 -0
  22. data/hobo_files/plugin/generators/hobo_model/templates/fixtures.yml +11 -0
  23. data/hobo_files/plugin/generators/hobo_model/templates/migration.rb +13 -0
  24. data/hobo_files/plugin/generators/hobo_model/templates/model.rb +24 -0
  25. data/hobo_files/plugin/generators/hobo_model/templates/unit_test.rb +10 -0
  26. data/hobo_files/plugin/generators/hobo_model_controller/USAGE +30 -0
  27. data/hobo_files/plugin/generators/hobo_model_controller/hobo_model_controller_generator.rb +43 -0
  28. data/hobo_files/plugin/generators/hobo_model_controller/templates/controller.rb +5 -0
  29. data/hobo_files/plugin/generators/hobo_model_controller/templates/functional_test.rb +18 -0
  30. data/hobo_files/plugin/generators/hobo_model_controller/templates/helper.rb +2 -0
  31. data/hobo_files/plugin/generators/hobo_model_controller/templates/view.rhtml +2 -0
  32. data/hobo_files/plugin/generators/hobo_rapid/hobo_rapid_generator.rb +51 -0
  33. data/hobo_files/plugin/generators/hobo_rapid/templates/hobo_rapid.js +436 -0
  34. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/default_mapping.rb +11 -0
  35. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/banner.gif +0 -0
  36. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_bodytop.gif +0 -0
  37. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_01.gif +0 -0
  38. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_02.gif +0 -0
  39. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_03.gif +0 -0
  40. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_04.gif +0 -0
  41. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_bottom.gif +0 -0
  42. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_left.gif +0 -0
  43. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_right.gif +0 -0
  44. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_top.gif +0 -0
  45. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_blue.gif +0 -0
  46. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_dblue.gif +0 -0
  47. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_green.gif +0 -0
  48. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_purple.gif +0 -0
  49. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_red.gif +0 -0
  50. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/logo.gif +0 -0
  51. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/spinner.gif +0 -0
  52. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_dblue.gif +0 -0
  53. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_green.gif +0 -0
  54. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_purple.gif +0 -0
  55. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_red.gif +0 -0
  56. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_01.gif +0 -0
  57. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_02.gif +0 -0
  58. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_03.gif +0 -0
  59. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_04.gif +0 -0
  60. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_bottom.gif +0 -0
  61. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_left.gif +0 -0
  62. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_right.gif +0 -0
  63. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_top.gif +0 -0
  64. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/stylesheets/application.css +390 -0
  65. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/views/application.dryml +104 -0
  66. data/hobo_files/plugin/generators/hobo_user_model/USAGE +26 -0
  67. data/hobo_files/plugin/generators/hobo_user_model/hobo_user_model_generator.rb +38 -0
  68. data/hobo_files/plugin/generators/hobo_user_model/templates/fixtures.yml +11 -0
  69. data/hobo_files/plugin/generators/hobo_user_model/templates/migration.rb +15 -0
  70. data/hobo_files/plugin/generators/hobo_user_model/templates/model.rb +58 -0
  71. data/hobo_files/plugin/generators/hobo_user_model/templates/unit_test.rb +10 -0
  72. data/hobo_files/plugin/init.rb +44 -0
  73. data/hobo_files/plugin/lib/action_view_extensions/base.rb +14 -0
  74. data/hobo_files/plugin/lib/active_record/has_many_association.rb +54 -0
  75. data/hobo_files/plugin/lib/active_record/has_many_through_association.rb +22 -0
  76. data/hobo_files/plugin/lib/active_record/table_definition.rb +34 -0
  77. data/hobo_files/plugin/lib/extensions.rb +245 -0
  78. data/hobo_files/plugin/lib/extensions/test_case.rb +130 -0
  79. data/hobo_files/plugin/lib/hobo.rb +353 -0
  80. data/hobo_files/plugin/lib/hobo/HtmlString +3 -0
  81. data/hobo_files/plugin/lib/hobo/authenticated_user.rb +106 -0
  82. data/hobo_files/plugin/lib/hobo/authentication_support.rb +108 -0
  83. data/hobo_files/plugin/lib/hobo/composite_model.rb +66 -0
  84. data/hobo_files/plugin/lib/hobo/controller.rb +134 -0
  85. data/hobo_files/plugin/lib/hobo/controller_helpers.rb +135 -0
  86. data/hobo_files/plugin/lib/hobo/core.rb +475 -0
  87. data/hobo_files/plugin/lib/hobo/define_tags.rb +56 -0
  88. data/hobo_files/plugin/lib/hobo/dryml.rb +161 -0
  89. data/hobo_files/plugin/lib/hobo/dryml/dryml_builder.rb +126 -0
  90. data/hobo_files/plugin/lib/hobo/dryml/tag_module.rb +9 -0
  91. data/hobo_files/plugin/lib/hobo/dryml/taglib.rb +57 -0
  92. data/hobo_files/plugin/lib/hobo/dryml/template.rb +586 -0
  93. data/hobo_files/plugin/lib/hobo/dryml/template_environment.rb +302 -0
  94. data/hobo_files/plugin/lib/hobo/dryml/template_handler.rb +19 -0
  95. data/hobo_files/plugin/lib/hobo/generator.rb +25 -0
  96. data/hobo_files/plugin/lib/hobo/html_string.rb +3 -0
  97. data/hobo_files/plugin/lib/hobo/lazy_hash.rb +28 -0
  98. data/hobo_files/plugin/lib/hobo/mapping_tags.rb +262 -0
  99. data/hobo_files/plugin/lib/hobo/markdown_string.rb +7 -0
  100. data/hobo_files/plugin/lib/hobo/model.rb +391 -0
  101. data/hobo_files/plugin/lib/hobo/model_controller.rb +676 -0
  102. data/hobo_files/plugin/lib/hobo/model_queries.rb +92 -0
  103. data/hobo_files/plugin/lib/hobo/model_support.rb +44 -0
  104. data/hobo_files/plugin/lib/hobo/password_string.rb +3 -0
  105. data/hobo_files/plugin/lib/hobo/predicate_dispatch.rb +78 -0
  106. data/hobo_files/plugin/lib/hobo/proc_binding.rb +32 -0
  107. data/hobo_files/plugin/lib/hobo/rapid.rb +447 -0
  108. data/hobo_files/plugin/lib/hobo/static_tags +92 -0
  109. data/hobo_files/plugin/lib/hobo/text.rb +3 -0
  110. data/hobo_files/plugin/lib/hobo/textile_string.rb +13 -0
  111. data/hobo_files/plugin/lib/hobo/undefined.rb +41 -0
  112. data/hobo_files/plugin/lib/hobo/undefined_access_error.rb +5 -0
  113. data/hobo_files/plugin/lib/hobo/where_fragment.rb +23 -0
  114. data/hobo_files/plugin/lib/rexml.rb +345 -0
  115. data/hobo_files/plugin/tags/core.dryml +6 -0
  116. data/hobo_files/plugin/tags/rapid.dryml +177 -0
  117. data/hobo_files/plugin/tags/rapid_editing.dryml +168 -0
  118. data/hobo_files/plugin/tags/rapid_navigation.dryml +95 -0
  119. data/hobo_files/plugin/tags/rapid_pages.dryml +175 -0
  120. data/hobo_files/plugin/tasks/environments.rake +19 -0
  121. data/hobo_files/plugin/tasks/hobo_tasks.rake +4 -0
  122. data/hobo_files/plugin/test/hobo_dryml_template_test.rb +7 -0
  123. data/hobo_files/plugin/test/hobo_test.rb +7 -0
  124. data/hobo_files/plugin/uninstall.rb +1 -0
  125. metadata +206 -0
@@ -0,0 +1,3 @@
1
+ class Hobo::HtmlString
2
+
3
+ end
@@ -0,0 +1,106 @@
1
+ require 'digest/sha1'
2
+
3
+ module Hobo
4
+
5
+ module AuthenticatedUser
6
+
7
+ def self.included(base)
8
+ base.extend(ClassMethods)
9
+
10
+ base.class_eval do
11
+ # Virtual attribute for the unencrypted password
12
+ attr_accessor :password
13
+
14
+ validates_presence_of :password, :if => :password_required?
15
+ validates_presence_of :password_confirmation, :if => :password_required?
16
+ validates_confirmation_of :password, :if => :password_required?
17
+
18
+ before_save :encrypt_password
19
+
20
+ never_show :salt, :crypted_password, :remember_token, :remember_token_expires_at
21
+
22
+ set_field_type :password => :password, :password_confirmation => :password
23
+
24
+ password_validations
25
+ end
26
+ end
27
+
28
+ module ClassMethods
29
+
30
+ def password_validations
31
+ validates_length_of :password, :within => 4..40, :if => :password_required?
32
+ end
33
+
34
+ def set_login_attr(attr)
35
+ @login_attr = attr = attr.to_sym
36
+ alias_attribute(:login, attr) unless attr == :login
37
+
38
+ if block_given?
39
+ yield
40
+ else
41
+ validates_presence_of attr
42
+ validates_length_of attr, :within => 3..100
43
+ validates_uniqueness_of attr, :case_sensitive => false
44
+ end
45
+ end
46
+
47
+ # Authenticates a user by their login name and unencrypted password. Returns the user or nil.
48
+ def authenticate(login, password)
49
+ u = find(:first, :conditions => ["#{@login_attr} = ?", login]) # need to get the salt
50
+
51
+ if u && u.authenticated?(password)
52
+ u.last_login_at = Time.now and u.save if u.respond_to?(:last_login_at)
53
+ u
54
+ else
55
+ nil
56
+ end
57
+ end
58
+
59
+ # Encrypts some data with the salt.
60
+ def encrypt(password, salt)
61
+ Digest::SHA1.hexdigest("--#{salt}--#{password}--")
62
+ end
63
+
64
+ end
65
+
66
+ # Encrypts the password with the user salt
67
+ def encrypt(password)
68
+ self.class.encrypt(password, salt)
69
+ end
70
+
71
+ def authenticated?(password)
72
+ crypted_password == encrypt(password)
73
+ end
74
+
75
+ def remember_token?
76
+ remember_token_expires_at && Time.now.utc < remember_token_expires_at
77
+ end
78
+
79
+ # These create and unset the fields required for remembering users between browser closes
80
+ def remember_me
81
+ self.remember_token_expires_at = 2.weeks.from_now.utc
82
+ self.remember_token = encrypt("#{login}--#{remember_token_expires_at}")
83
+ save(false)
84
+ end
85
+
86
+ def forget_me
87
+ self.remember_token_expires_at = nil
88
+ self.remember_token = nil
89
+ save(false)
90
+ end
91
+
92
+ protected
93
+ # before filter
94
+ def encrypt_password
95
+ return if password.blank?
96
+ self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record?
97
+ self.crypted_password = encrypt(password)
98
+ end
99
+
100
+ def password_required?
101
+ (crypted_password.blank? && password != nil) || !password.blank?
102
+ end
103
+
104
+ end
105
+
106
+ end
@@ -0,0 +1,108 @@
1
+ module Hobo
2
+
3
+ module AuthenticationSupport
4
+
5
+ # Filter method to enforce a login requirement.
6
+ def logged_in?
7
+ not current_user.guest?
8
+ end
9
+
10
+ # Check if the user is authorized.
11
+ #
12
+ # Override this method in your controllers if you want to restrict access
13
+ # to only a few actions or if you want to check if the user
14
+ # has the correct rights.
15
+ #
16
+ # Example:
17
+ #
18
+ # # only allow nonbobs
19
+ # def authorize?
20
+ # current_user.login != "bob"
21
+ # end
22
+ def authorized?
23
+ true
24
+ end
25
+
26
+ #
27
+ # To require logins for all actions, use this in your controllers:
28
+ #
29
+ # before_filter :login_required
30
+ #
31
+ # To require logins for specific actions, use this in your controllers:
32
+ #
33
+ # before_filter :login_required, :only => [ :edit, :update ]
34
+ #
35
+ # To skip this in a subclassed controller:
36
+ #
37
+ # skip_before_filter :login_required
38
+ #
39
+ def login_required
40
+ if current_user.guest?
41
+ username, passwd = get_auth_data
42
+ self.current_user = Hobo.user_model.authenticate(username, passwd) || :false if username && passwd
43
+ end
44
+ logged_in? && authorized? ? true : access_denied
45
+ end
46
+
47
+ # Redirect as appropriate when an access request fails.
48
+ #
49
+ # The default action is to redirect to the login screen.
50
+ #
51
+ # Override this method in your controllers if you want to have special
52
+ # behavior in case the user is not authorized
53
+ # to access the requested action. For example, a popup window might
54
+ # simply close itself.
55
+ def access_denied
56
+ respond_to do |accepts|
57
+ accepts.html do
58
+ store_location
59
+ redirect_to login_url
60
+ end
61
+ accepts.xml do
62
+ headers["Status"] = "Unauthorized"
63
+ headers["WWW-Authenticate"] = %(Basic realm="Web Password")
64
+ render :text => "Could't authenticate you", :status => '401 Unauthorized'
65
+ end
66
+ end
67
+ false
68
+ end
69
+
70
+ # Store the URI of the current request in the session.
71
+ #
72
+ # We can return to this location by calling #redirect_back_or_default.
73
+ def store_location
74
+ session[:return_to] = request.request_uri
75
+ end
76
+
77
+ # Redirect to the URI stored by the most recent store_location call or
78
+ # to the passed default.
79
+ def redirect_back_or_default(default)
80
+ session[:return_to] ? redirect_to_url(session[:return_to]) : redirect_to(default)
81
+ session[:return_to] = nil
82
+ end
83
+
84
+ # When called with before_filter :login_from_cookie will check for an :auth_token
85
+ # cookie and log the user back in if apropriate
86
+ def login_from_cookie
87
+ return unless cookies[:auth_token] && !logged_in?
88
+ user = Hobo.user_model.find_by_remember_token(cookies[:auth_token])
89
+ if user && user.remember_token?
90
+ user.remember_me
91
+ self.current_user = user
92
+ cookies[:auth_token] = { :value => self.current_user.remember_token ,
93
+ :expires => self.current_user.remember_token_expires_at }
94
+ end
95
+ end
96
+
97
+ private
98
+ @@http_auth_headers = %w(X-HTTP_AUTHORIZATION HTTP_AUTHORIZATION Authorization)
99
+ # gets BASIC auth info
100
+ def get_auth_data
101
+ auth_key = @@http_auth_headers.detect { |h| request.env.has_key?(h) }
102
+ auth_data = request.env[auth_key].to_s.split unless auth_key.blank?
103
+ return auth_data && auth_data[0] == 'Basic' ? Base64.decode64(auth_data[1]).split(':')[0..1] : [nil, nil]
104
+ end
105
+
106
+ end
107
+
108
+ end
@@ -0,0 +1,66 @@
1
+ module Hobo
2
+
3
+ class CompositeModel
4
+
5
+ include ModelSupport
6
+
7
+ class << self
8
+
9
+ def find(id)
10
+ ids = id.split('_')
11
+ new(*ids.map_with_index{|id, i| @models[i].constantize.find(id)})
12
+ end
13
+
14
+ def compose(*models)
15
+ @models = models.omap{to_s.camelize}
16
+ attr_reader *models
17
+ CompositeModel.composites ||= {}
18
+ CompositeModel.composites[@models.sort] = self.name
19
+
20
+ Hobo.register_model(self)
21
+ end
22
+
23
+ attr_accessor :composites
24
+
25
+ attr_reader :models
26
+
27
+ def new_for(objects)
28
+ classes = objects.map{|o| o.class.name}.sort
29
+ composite_class = CompositeModel.composites[classes].constantize rescue
30
+ (raise ArgumentError, "No composite model for #{classes.inspect}")
31
+ composite_class.new(*objects)
32
+ end
33
+
34
+ end
35
+
36
+
37
+ def initialize(*objects)
38
+ objects.each do |obj|
39
+ raise ArgumentError, "invalid objects for composition: #{objects.inspect}" unless
40
+ obj.class.name.in? self.class.models
41
+ instance_variable_set("@#{obj.class.name.underscore}", obj)
42
+ end
43
+ end
44
+
45
+
46
+ def compose_with(object, use=nil)
47
+ self_classes = use ? use.models : self.class.models
48
+ from_self = (self_classes - [object.class.name]).map {|classname| send(classname.underscore)}
49
+ CompositeModel.new_for(from_self + [object])
50
+ end
51
+
52
+
53
+ def typed_id
54
+ "#{self.class.name.underscore}_#{id}"
55
+ end
56
+
57
+
58
+ def id
59
+ objects = self.class.models.map {|m| instance_variable_get("@#{m.underscore}")}
60
+ objects.omap{id}.join("_")
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+
@@ -0,0 +1,134 @@
1
+ module Hobo
2
+
3
+ module Controller
4
+
5
+ include ControllerHelpers
6
+
7
+ include AuthenticationSupport
8
+
9
+ def self.included(base)
10
+ if base.is_a?(Class)
11
+ Hobo::ControllerHelpers.public_instance_methods.each {|m| base.hide_action(m)}
12
+ base.class_eval do
13
+ alias_method_chain :redirect_to, :object_url
14
+ end
15
+ end
16
+ end
17
+
18
+
19
+ protected
20
+
21
+ def redirect_to_with_object_url(destination, view=nil)
22
+ if destination.is_a?(String, Hash, Symbol)
23
+ redirect_to_without_object_url(destination)
24
+ else
25
+ redirect_to_without_object_url(object_url(destination, view))
26
+ end
27
+ end
28
+
29
+ def hobo_ajax_response(this=nil, results={})
30
+ this ||= @this
31
+ part_page = params[:part_page]
32
+ r = params[:render]
33
+ if r
34
+ ajax_update_response(this, part_page, r.values, results)
35
+ true
36
+ else
37
+ false
38
+ end
39
+ end
40
+
41
+
42
+ def ajax_update_response(this, part_page, render_specs, results={})
43
+ before_ajax if respond_to? :before_ajax
44
+ add_variables_to_assigns
45
+ renderer = Hobo::Dryml.page_renderer(@template, [], part_page) if part_page
46
+
47
+ render :update do |page|
48
+ page << "var _update = typeof Hobo == 'undefined' ? Element.update : Hobo.updateElement;"
49
+ for spec in render_specs
50
+ function = spec[:function] || "_update"
51
+
52
+ if spec[:as] or spec[:part]
53
+ obj = if spec[:object] == "this" or spec[:object].blank?
54
+ this
55
+ elsif spec[:object] == "nil"
56
+ nil
57
+ else
58
+ Hobo.object_from_dom_id(spec[:object])
59
+ end
60
+
61
+ if spec[:as]
62
+ part_content = render(:partial => (Hobo::ModelController.find_partial(obj.class, spec[:as])),
63
+ :locals => { :this => obj })
64
+ page.call(function, spec[:id], part_content)
65
+
66
+ elsif spec[:part]
67
+ dom_id = spec[:id] || spec[:part]
68
+ part_content = renderer.call_part(dom_id, spec[:part], obj)
69
+ page.call(function, dom_id, part_content)
70
+ end
71
+
72
+ elsif spec[:result]
73
+ result = results[spec[:result].to_sym]
74
+ page.call(function, spec[:id], result)
75
+
76
+ else
77
+ # spec didn't specify any action :-/
78
+ end
79
+ end
80
+ if renderer
81
+ renderer.part_contexts.each_pair do |dom_id, p|
82
+ part_id, model_id = p
83
+ page.assign "hoboParts.#{dom_id}", [part_id, model_id]
84
+
85
+ # not sure why this isn't happending automatically
86
+ # but it's messing up ARTS, so chuck a newline in
87
+ page << "\n"
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+
94
+ def render_tag(tag, options={})
95
+ add_variables_to_assigns
96
+ render :text => Hobo::Dryml.render_tag(@template, tag, options), :layout => false
97
+ end
98
+
99
+
100
+ def render_tags(objects, tag, options={})
101
+ add_variables_to_assigns
102
+ dryml_renderer = Hobo::Dryml.empty_page_renderer(@template)
103
+ render :text => objects.map {|o| dryml_renderer.send(tag, options.merge(:obj => o))}.join +
104
+ dryml_renderer.part_contexts_js
105
+ end
106
+
107
+
108
+ def site_search(query)
109
+ results = Hobo.find_by_search(query).select {|r| Hobo.can_view?(current_user, r, nil)}
110
+ if results.empty?
111
+ render :text => "<p>Your search returned no matches.</p>"
112
+ else
113
+ render_tags(results, "tag_for_object", :name => "search_result")
114
+ end
115
+ end
116
+
117
+
118
+ # Store the given user in the session.
119
+ def current_user=(new_user)
120
+ session[:user] = (new_user.nil? || new_user.is_a?(Symbol)) ? nil : new_user.id
121
+ @current_user = new_user
122
+ end
123
+
124
+
125
+ def request_no_cache?
126
+ request.env['HTTP_CACHE_CONTROL'] =~ /max-age=\s*0/
127
+ end
128
+
129
+ def not_found
130
+
131
+ end
132
+
133
+ end
134
+ end
@@ -0,0 +1,135 @@
1
+ module Hobo::ControllerHelpers
2
+
3
+ protected
4
+
5
+ def current_user
6
+ # simple one-hit-per-request cache
7
+ @current_user or
8
+ @current_user = if Hobo.user_model and session and id = session[:user]
9
+ Hobo.user_model.find(id)
10
+ else
11
+ Guest.new
12
+ end
13
+ end
14
+
15
+
16
+ def logged_in?
17
+ not current_user.guest?
18
+ end
19
+
20
+
21
+ def urlb
22
+ request.relative_url_root
23
+ end
24
+
25
+
26
+ def controller_for(obj)
27
+ if obj.is_a? Class
28
+ obj.name.underscore.pluralize
29
+ else
30
+ obj.class.name.underscore.pluralize
31
+ end
32
+ end
33
+
34
+
35
+ def object_url(obj, action=nil, *param_hashes)
36
+ action &&= action.to_s
37
+
38
+ controller_name = controller_for(obj)
39
+
40
+ parts = if obj.is_a? Class
41
+ [urlb, controller_name]
42
+
43
+ elsif obj.is_a? Hobo::CompositeModel
44
+ [urlb, controller_name, obj.id]
45
+
46
+ elsif obj.is_a? ActiveRecord::Base
47
+ if obj.new_record?
48
+ [urlb, controller_name]
49
+ else
50
+ raise HoboError.new("invalid object url: new for existing object") if action == "new"
51
+
52
+ klass = obj.class
53
+ id = if klass.id_name?
54
+ obj.id_name(true)
55
+ else
56
+ obj.id
57
+ end
58
+
59
+ [urlb, controller_name, id]
60
+ end
61
+
62
+ elsif obj.is_a? Array # warning - this breaks if we use `case/when Array`
63
+ owner = obj.proxy_owner
64
+ new_model = obj.proxy_reflection.klass
65
+ [object_url(owner), obj.proxy_reflection.name]
66
+
67
+ else
68
+ raise HoboError.new("cannot create url for #{obj.inspect} (#{obj.class})")
69
+ end
70
+ basic = parts.join("/")
71
+
72
+ controller = (controller_name.camelize + "Controller").constantize rescue nil
73
+ url = if action && controller && action.to_sym.in?(controller.web_methods)
74
+ basic + "/#{action}"
75
+ else
76
+ case action
77
+ when "new"
78
+ basic + "/new"
79
+ when "destroy"
80
+ basic + "?_method=DELETE"
81
+ when "update"
82
+ basic + "?_method=PUT"
83
+ when nil
84
+ basic
85
+ else
86
+ basic + ";" + action
87
+ end
88
+ end
89
+ params = make_params(*param_hashes)
90
+ params.blank? ? url : url + "?" + params
91
+ end
92
+
93
+
94
+ def _as_params(name, obj)
95
+ if obj.is_a? Array
96
+ obj.map {|x| _as_params("#{name}[]", x)}.join("&")
97
+ elsif obj.is_a? Hash
98
+ obj.map {|k,v| _as_params("#{name}[#{k}]", v)}.join("&")
99
+ elsif obj.is_a? Hobo::RawJs
100
+ "#{name}=' + #{obj} + '"
101
+ else
102
+ v = if obj.is_a?(ActiveRecord::Base) or obj.is_a?(Array)
103
+ "@" + dom_id(obj)
104
+ else
105
+ obj.to_s.gsub("'"){"\\'"}
106
+ end
107
+ "#{name}=#{v}"
108
+ end
109
+ end
110
+
111
+
112
+ def make_params(*hashes)
113
+ hash = {}
114
+ hashes.each {|h| hash.update(h) if h}
115
+ hash.map {|k,v| _as_params(k, v)}.join("&")
116
+ end
117
+
118
+
119
+ def dom_id(x, attr=nil)
120
+ Hobo.dom_id(x, attr)
121
+ end
122
+
123
+
124
+ # debugging support
125
+
126
+ def debug(*args)
127
+ logger.debug(args.map{|arg| PP.pp(arg, "")}.join("\n"))
128
+ return args.first
129
+ end
130
+
131
+ def abort_with(*args)
132
+ raise args.map{|arg| PP.pp(arg, "")}.join("\n")
133
+ end
134
+
135
+ end