hobo 0.5.3
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +22 -0
- data/README.txt +18 -0
- data/bin/hobo +81 -0
- data/hobo_files/plugin/CHANGES.txt +963 -0
- data/hobo_files/plugin/LICENSE.txt +22 -0
- data/hobo_files/plugin/README +4 -0
- data/hobo_files/plugin/Rakefile +11 -0
- data/hobo_files/plugin/generators/hobo/hobo_generator.rb +37 -0
- data/hobo_files/plugin/generators/hobo/templates/application.dryml +2 -0
- data/hobo_files/plugin/generators/hobo/templates/guest.rb +31 -0
- data/hobo_files/plugin/generators/hobo_front_controller/USAGE +11 -0
- data/hobo_files/plugin/generators/hobo_front_controller/hobo_front_controller_generator.rb +90 -0
- data/hobo_files/plugin/generators/hobo_front_controller/templates/controller.rb +51 -0
- data/hobo_files/plugin/generators/hobo_front_controller/templates/functional_test.rb +18 -0
- data/hobo_files/plugin/generators/hobo_front_controller/templates/helper.rb +2 -0
- data/hobo_files/plugin/generators/hobo_front_controller/templates/index.dryml +43 -0
- data/hobo_files/plugin/generators/hobo_front_controller/templates/login.dryml +44 -0
- data/hobo_files/plugin/generators/hobo_front_controller/templates/search.dryml +18 -0
- data/hobo_files/plugin/generators/hobo_front_controller/templates/signup.dryml +45 -0
- data/hobo_files/plugin/generators/hobo_model/USAGE +26 -0
- data/hobo_files/plugin/generators/hobo_model/hobo_model_generator.rb +38 -0
- data/hobo_files/plugin/generators/hobo_model/templates/fixtures.yml +11 -0
- data/hobo_files/plugin/generators/hobo_model/templates/migration.rb +13 -0
- data/hobo_files/plugin/generators/hobo_model/templates/model.rb +24 -0
- data/hobo_files/plugin/generators/hobo_model/templates/unit_test.rb +10 -0
- data/hobo_files/plugin/generators/hobo_model_controller/USAGE +30 -0
- data/hobo_files/plugin/generators/hobo_model_controller/hobo_model_controller_generator.rb +43 -0
- data/hobo_files/plugin/generators/hobo_model_controller/templates/controller.rb +5 -0
- data/hobo_files/plugin/generators/hobo_model_controller/templates/functional_test.rb +18 -0
- data/hobo_files/plugin/generators/hobo_model_controller/templates/helper.rb +2 -0
- data/hobo_files/plugin/generators/hobo_model_controller/templates/view.rhtml +2 -0
- data/hobo_files/plugin/generators/hobo_rapid/hobo_rapid_generator.rb +51 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/hobo_rapid.js +436 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/default_mapping.rb +11 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/banner.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_bodytop.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_01.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_02.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_03.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_04.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_bottom.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_left.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_right.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_top.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_blue.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_dblue.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_green.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_purple.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_red.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/logo.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/spinner.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_dblue.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_green.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_purple.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_red.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_01.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_02.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_03.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_04.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_bottom.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_left.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_right.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_top.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/stylesheets/application.css +390 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/views/application.dryml +104 -0
- data/hobo_files/plugin/generators/hobo_user_model/USAGE +26 -0
- data/hobo_files/plugin/generators/hobo_user_model/hobo_user_model_generator.rb +38 -0
- data/hobo_files/plugin/generators/hobo_user_model/templates/fixtures.yml +11 -0
- data/hobo_files/plugin/generators/hobo_user_model/templates/migration.rb +15 -0
- data/hobo_files/plugin/generators/hobo_user_model/templates/model.rb +58 -0
- data/hobo_files/plugin/generators/hobo_user_model/templates/unit_test.rb +10 -0
- data/hobo_files/plugin/init.rb +44 -0
- data/hobo_files/plugin/lib/action_view_extensions/base.rb +14 -0
- data/hobo_files/plugin/lib/active_record/has_many_association.rb +54 -0
- data/hobo_files/plugin/lib/active_record/has_many_through_association.rb +22 -0
- data/hobo_files/plugin/lib/active_record/table_definition.rb +34 -0
- data/hobo_files/plugin/lib/extensions.rb +245 -0
- data/hobo_files/plugin/lib/extensions/test_case.rb +130 -0
- data/hobo_files/plugin/lib/hobo.rb +353 -0
- data/hobo_files/plugin/lib/hobo/HtmlString +3 -0
- data/hobo_files/plugin/lib/hobo/authenticated_user.rb +106 -0
- data/hobo_files/plugin/lib/hobo/authentication_support.rb +108 -0
- data/hobo_files/plugin/lib/hobo/composite_model.rb +66 -0
- data/hobo_files/plugin/lib/hobo/controller.rb +134 -0
- data/hobo_files/plugin/lib/hobo/controller_helpers.rb +135 -0
- data/hobo_files/plugin/lib/hobo/core.rb +475 -0
- data/hobo_files/plugin/lib/hobo/define_tags.rb +56 -0
- data/hobo_files/plugin/lib/hobo/dryml.rb +161 -0
- data/hobo_files/plugin/lib/hobo/dryml/dryml_builder.rb +126 -0
- data/hobo_files/plugin/lib/hobo/dryml/tag_module.rb +9 -0
- data/hobo_files/plugin/lib/hobo/dryml/taglib.rb +57 -0
- data/hobo_files/plugin/lib/hobo/dryml/template.rb +586 -0
- data/hobo_files/plugin/lib/hobo/dryml/template_environment.rb +302 -0
- data/hobo_files/plugin/lib/hobo/dryml/template_handler.rb +19 -0
- data/hobo_files/plugin/lib/hobo/generator.rb +25 -0
- data/hobo_files/plugin/lib/hobo/html_string.rb +3 -0
- data/hobo_files/plugin/lib/hobo/lazy_hash.rb +28 -0
- data/hobo_files/plugin/lib/hobo/mapping_tags.rb +262 -0
- data/hobo_files/plugin/lib/hobo/markdown_string.rb +7 -0
- data/hobo_files/plugin/lib/hobo/model.rb +391 -0
- data/hobo_files/plugin/lib/hobo/model_controller.rb +676 -0
- data/hobo_files/plugin/lib/hobo/model_queries.rb +92 -0
- data/hobo_files/plugin/lib/hobo/model_support.rb +44 -0
- data/hobo_files/plugin/lib/hobo/password_string.rb +3 -0
- data/hobo_files/plugin/lib/hobo/predicate_dispatch.rb +78 -0
- data/hobo_files/plugin/lib/hobo/proc_binding.rb +32 -0
- data/hobo_files/plugin/lib/hobo/rapid.rb +447 -0
- data/hobo_files/plugin/lib/hobo/static_tags +92 -0
- data/hobo_files/plugin/lib/hobo/text.rb +3 -0
- data/hobo_files/plugin/lib/hobo/textile_string.rb +13 -0
- data/hobo_files/plugin/lib/hobo/undefined.rb +41 -0
- data/hobo_files/plugin/lib/hobo/undefined_access_error.rb +5 -0
- data/hobo_files/plugin/lib/hobo/where_fragment.rb +23 -0
- data/hobo_files/plugin/lib/rexml.rb +345 -0
- data/hobo_files/plugin/tags/core.dryml +6 -0
- data/hobo_files/plugin/tags/rapid.dryml +177 -0
- data/hobo_files/plugin/tags/rapid_editing.dryml +168 -0
- data/hobo_files/plugin/tags/rapid_navigation.dryml +95 -0
- data/hobo_files/plugin/tags/rapid_pages.dryml +175 -0
- data/hobo_files/plugin/tasks/environments.rake +19 -0
- data/hobo_files/plugin/tasks/hobo_tasks.rake +4 -0
- data/hobo_files/plugin/test/hobo_dryml_template_test.rb +7 -0
- data/hobo_files/plugin/test/hobo_test.rb +7 -0
- data/hobo_files/plugin/uninstall.rb +1 -0
- metadata +206 -0
@@ -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
|