hobo 0.7.2 → 0.7.3
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.
- data/bin/hobo +24 -7
- data/hobo_files/plugin/CHANGES.txt +501 -0
- data/hobo_files/plugin/generators/hobo/hobo_generator.rb +8 -6
- data/hobo_files/plugin/generators/hobo/templates/application.dryml +3 -0
- data/hobo_files/plugin/generators/hobo/templates/dryml-support.js +132 -0
- data/hobo_files/plugin/generators/hobo_front_controller/hobo_front_controller_generator.rb +4 -5
- data/hobo_files/plugin/generators/hobo_model_resource/hobo_model_resource_generator.rb +75 -0
- data/hobo_files/plugin/generators/hobo_model_resource/templates/controller.rb +7 -0
- data/hobo_files/plugin/generators/hobo_model_resource/templates/functional_test.rb +8 -0
- data/hobo_files/plugin/generators/hobo_model_resource/templates/helper.rb +2 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/hobo-rapid.js +30 -11
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/stylesheets/application.css +149 -92
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/stylesheets/rapid-ui.css +0 -48
- data/hobo_files/plugin/init.rb +45 -13
- data/hobo_files/plugin/lib/action_view_extensions/base.rb +4 -3
- data/hobo_files/plugin/lib/active_record/association_proxy.rb +18 -0
- data/hobo_files/plugin/lib/active_record/association_reflection.rb +5 -0
- data/hobo_files/plugin/lib/active_record/has_many_association.rb +7 -11
- data/hobo_files/plugin/lib/active_record/has_many_through_association.rb +8 -0
- data/hobo_files/plugin/lib/extensions/test_case.rb +1 -1
- data/hobo_files/plugin/lib/hobo.rb +38 -60
- data/hobo_files/plugin/lib/hobo/authentication_support.rb +1 -1
- data/hobo_files/plugin/lib/hobo/bundle.rb +131 -34
- data/hobo_files/plugin/lib/hobo/composite_model.rb +1 -1
- data/hobo_files/plugin/lib/hobo/controller.rb +7 -8
- data/hobo_files/plugin/lib/hobo/dev_controller.rb +21 -0
- data/hobo_files/plugin/lib/hobo/dryml/dryml_builder.rb +14 -8
- data/hobo_files/plugin/lib/hobo/dryml/dryml_support_controller.rb +13 -0
- data/hobo_files/plugin/lib/hobo/dryml/taglib.rb +6 -7
- data/hobo_files/plugin/lib/hobo/dryml/template.rb +207 -73
- data/hobo_files/plugin/lib/hobo/dryml/template_environment.rb +67 -55
- data/hobo_files/plugin/lib/hobo/dryml/template_handler.rb +53 -3
- data/hobo_files/plugin/lib/hobo/hobo_helper.rb +75 -107
- data/hobo_files/plugin/lib/hobo/model.rb +236 -429
- data/hobo_files/plugin/lib/hobo/model_controller.rb +277 -437
- data/hobo_files/plugin/lib/hobo/model_router.rb +62 -29
- data/hobo_files/plugin/lib/hobo/rapid_helper.rb +48 -9
- data/hobo_files/plugin/lib/hobo/scopes.rb +98 -0
- data/hobo_files/plugin/lib/hobo/scopes/association_proxy_extensions.rb +31 -0
- data/hobo_files/plugin/lib/hobo/scopes/automatic_scopes.rb +282 -0
- data/hobo_files/plugin/lib/hobo/scopes/defined_scope_proxy_extender.rb +88 -0
- data/hobo_files/plugin/lib/hobo/scopes/scope_reflection.rb +18 -0
- data/hobo_files/plugin/lib/hobo/scopes/scoped_proxy.rb +59 -0
- data/hobo_files/plugin/lib/hobo/undefined.rb +2 -0
- data/hobo_files/plugin/lib/hobo/user.rb +31 -14
- data/hobo_files/plugin/lib/hobo/user_controller.rb +41 -27
- data/hobo_files/plugin/taglibs/core.dryml +9 -11
- data/hobo_files/plugin/taglibs/rapid.dryml +51 -108
- data/hobo_files/plugin/taglibs/rapid_editing.dryml +25 -25
- data/hobo_files/plugin/taglibs/rapid_forms.dryml +111 -79
- data/hobo_files/plugin/taglibs/rapid_generics.dryml +74 -0
- data/hobo_files/plugin/taglibs/rapid_navigation.dryml +23 -21
- data/hobo_files/plugin/taglibs/rapid_pages.dryml +83 -169
- data/hobo_files/plugin/taglibs/rapid_plus.dryml +16 -2
- data/hobo_files/plugin/taglibs/rapid_support.dryml +3 -3
- data/hobo_files/plugin/taglibs/rapid_user_pages.dryml +104 -0
- metadata +60 -55
- data/hobo_files/plugin/generators/hobo_migration/hobo_migration_generator.rb +0 -276
- data/hobo_files/plugin/generators/hobo_migration/templates/migration.rb +0 -9
- data/hobo_files/plugin/lib/active_record/table_definition.rb +0 -34
- data/hobo_files/plugin/lib/extensions.rb +0 -375
- data/hobo_files/plugin/lib/hobo/email_address.rb +0 -12
- data/hobo_files/plugin/lib/hobo/enum_string.rb +0 -50
- data/hobo_files/plugin/lib/hobo/field_declaration_dsl.rb +0 -43
- data/hobo_files/plugin/lib/hobo/field_spec.rb +0 -68
- data/hobo_files/plugin/lib/hobo/html_string.rb +0 -7
- data/hobo_files/plugin/lib/hobo/lazy_hash.rb +0 -40
- data/hobo_files/plugin/lib/hobo/markdown_string.rb +0 -11
- data/hobo_files/plugin/lib/hobo/migrations.rb +0 -12
- data/hobo_files/plugin/lib/hobo/model_queries.rb +0 -117
- data/hobo_files/plugin/lib/hobo/password_string.rb +0 -7
- data/hobo_files/plugin/lib/hobo/percentage.rb +0 -14
- data/hobo_files/plugin/lib/hobo/predicate_dispatch.rb +0 -78
- data/hobo_files/plugin/lib/hobo/proc_binding.rb +0 -32
- data/hobo_files/plugin/lib/hobo/text.rb +0 -3
- data/hobo_files/plugin/lib/hobo/textile_string.rb +0 -25
- data/hobo_files/plugin/lib/hobo/where_fragment.rb +0 -28
data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/stylesheets/rapid-ui.css
CHANGED
|
@@ -17,11 +17,6 @@ table.new-record textarea, table.new-record input {
|
|
|
17
17
|
display: inline;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
.edit-page .content-header {overflow: hidden; height: 100%;}
|
|
21
|
-
.edit-page .content-header h1 {float: left;}
|
|
22
|
-
.edit-page .content-header .delete-button {float: right;}
|
|
23
|
-
form .actions {margin: 30px 0;width: 100%; text-align: center;}
|
|
24
|
-
|
|
25
20
|
/**** Admin ****/
|
|
26
21
|
|
|
27
22
|
.admin-banner {
|
|
@@ -39,25 +34,6 @@ form .actions {margin: 30px 0;width: 100%; text-align: center;}
|
|
|
39
34
|
float: right;
|
|
40
35
|
}
|
|
41
36
|
|
|
42
|
-
/* rails error message */
|
|
43
|
-
.error-messages {
|
|
44
|
-
font-family: "Lucida Grande", arial, sans-serif;
|
|
45
|
-
background: #9d0018;
|
|
46
|
-
border: 1px solid #7a0013;
|
|
47
|
-
padding: 15px 30px;
|
|
48
|
-
color: white;
|
|
49
|
-
margin-bottom: 20px;
|
|
50
|
-
}
|
|
51
|
-
.error-messages h2 {
|
|
52
|
-
text-transform: none;
|
|
53
|
-
letter-spacing: normal;
|
|
54
|
-
color: white;
|
|
55
|
-
margin-bottom: 10px;
|
|
56
|
-
}
|
|
57
|
-
.error-messages li {
|
|
58
|
-
margin-left: 20px;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
37
|
/********* everything below here came from hobo_rapid.css, needs looking at ********/
|
|
62
38
|
|
|
63
39
|
/**** Default styling for Rapid ***/
|
|
@@ -66,30 +42,6 @@ form .actions {margin: 30px 0;width: 100%; text-align: center;}
|
|
|
66
42
|
float: right; margin: 20px;
|
|
67
43
|
position: fixed; display: none; z-index: 10;
|
|
68
44
|
}
|
|
69
|
-
/*
|
|
70
|
-
#ajax-progress {
|
|
71
|
-
color: grey;
|
|
72
|
-
float: right;
|
|
73
|
-
margin: 20px;
|
|
74
|
-
position: fixed;
|
|
75
|
-
background: white;
|
|
76
|
-
font-family: Tahoma "sans serif";
|
|
77
|
-
display: none;
|
|
78
|
-
z-index: 10;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
#ajax-progress div {
|
|
82
|
-
border: 1px dashed grey;
|
|
83
|
-
margin: 10px;
|
|
84
|
-
padding: 3px;
|
|
85
|
-
padding-top: -15px;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
#ajax-progress img {
|
|
89
|
-
padding-left: 6px;
|
|
90
|
-
vertical-align: middle;
|
|
91
|
-
}
|
|
92
|
-
*/
|
|
93
45
|
|
|
94
46
|
/* Scriptaculous Autocompleter ---*/
|
|
95
47
|
|
data/hobo_files/plugin/init.rb
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
|
+
# gem dependencies
|
|
2
|
+
require 'hobosupport'
|
|
3
|
+
|
|
4
|
+
# Force load:
|
|
5
|
+
HoboFields
|
|
6
|
+
|
|
1
7
|
# Monkey patches, ooh ooh
|
|
2
|
-
require 'extensions'
|
|
3
8
|
require 'rexml'
|
|
4
9
|
require 'active_record/has_many_association'
|
|
5
10
|
require 'active_record/has_many_through_association'
|
|
6
|
-
require 'active_record/
|
|
11
|
+
require 'active_record/association_proxy'
|
|
12
|
+
require 'active_record/association_reflection'
|
|
7
13
|
require 'action_view_extensions/base'
|
|
8
14
|
|
|
9
15
|
require 'hobo'
|
|
10
16
|
require 'hobo/dryml'
|
|
11
17
|
|
|
12
18
|
require 'hobo/model'
|
|
13
|
-
require 'hobo/field_declaration_dsl'
|
|
14
19
|
|
|
15
20
|
require 'hobo/dryml/template'
|
|
16
21
|
require 'hobo/dryml/taglib'
|
|
@@ -19,16 +24,6 @@ require 'hobo/dryml/template_handler'
|
|
|
19
24
|
|
|
20
25
|
require 'extensions/test_case' if RAILS_ENV == "test"
|
|
21
26
|
|
|
22
|
-
# Rich data types
|
|
23
|
-
require "hobo/html_string"
|
|
24
|
-
require "hobo/markdown_string"
|
|
25
|
-
require "hobo/textile_string"
|
|
26
|
-
require "hobo/password_string"
|
|
27
|
-
require "hobo/text"
|
|
28
|
-
require "hobo/email_address"
|
|
29
|
-
require "hobo/enum_string"
|
|
30
|
-
require "hobo/percentage"
|
|
31
|
-
|
|
32
27
|
|
|
33
28
|
ActionView::Base.register_template_handler("dryml", Hobo::Dryml::TemplateHandler)
|
|
34
29
|
|
|
@@ -54,6 +49,7 @@ end
|
|
|
54
49
|
class ActiveRecord::Base
|
|
55
50
|
def self.hobo_model
|
|
56
51
|
include Hobo::Model
|
|
52
|
+
fields # force hobofields to load
|
|
57
53
|
end
|
|
58
54
|
def self.hobo_user_model
|
|
59
55
|
include Hobo::Model
|
|
@@ -64,3 +60,39 @@ end
|
|
|
64
60
|
# Default settings
|
|
65
61
|
|
|
66
62
|
Hobo.developer_features = RAILS_ENV.in?(["development", "test"]) if Hobo.developer_features?.nil?
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
module ::Hobo
|
|
66
|
+
# Empty class to represent the boolean type.
|
|
67
|
+
class Boolean; end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
if defined? HoboFields
|
|
72
|
+
HoboFields.never_wrap(Hobo::Undefined)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# Add support for type metadata to arrays
|
|
77
|
+
class ::Array
|
|
78
|
+
|
|
79
|
+
attr_accessor :member_class, :origin, :origin_attribute
|
|
80
|
+
|
|
81
|
+
def to_url_path
|
|
82
|
+
base_path = origin_object.try.to_url_path
|
|
83
|
+
"#{base_path}/#{origin_attribute}" unless base_path.blank?
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def typed_id
|
|
87
|
+
origin_id = origin.try.typed_id
|
|
88
|
+
"#{origin_id}_#{origin_attribute}" if origin_id
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class NilClass
|
|
95
|
+
def typed_id
|
|
96
|
+
"nil"
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -2,12 +2,13 @@ module ActionView
|
|
|
2
2
|
|
|
3
3
|
class Base
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
def render_file(template_path, *args)
|
|
5
|
+
def render_file_with_dryml(template_path, *args)
|
|
7
6
|
@hobo_template_path = template_path
|
|
8
|
-
|
|
7
|
+
render_file_without_dryml(template_path, *args)
|
|
9
8
|
end
|
|
10
9
|
|
|
10
|
+
alias_method_chain :render_file, :dryml
|
|
11
|
+
|
|
11
12
|
end
|
|
12
13
|
|
|
13
14
|
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module ActiveRecord
|
|
2
|
+
module Associations
|
|
3
|
+
class AssociationProxy #:nodoc:
|
|
4
|
+
|
|
5
|
+
private
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def raise_on_type_mismatch(record)
|
|
9
|
+
# Don't complain if the interface type of a polymorphic association doesn't exist
|
|
10
|
+
klass = @reflection.klass rescue nil
|
|
11
|
+
unless klass.nil? || record.is_a?(klass)
|
|
12
|
+
raise ActiveRecord::AssociationTypeMismatch, "#{@reflection.klass} expected, got #{record.class}"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -18,7 +18,7 @@ module ActiveRecord::Associations
|
|
|
18
18
|
record = @reflection.klass.new(attributes)
|
|
19
19
|
if hobo_has_many?
|
|
20
20
|
set_belongs_to_association_for(record)
|
|
21
|
-
set_reverse_association(record)
|
|
21
|
+
set_reverse_association(record) unless proxy_reflection.options[:as]
|
|
22
22
|
end
|
|
23
23
|
record
|
|
24
24
|
end
|
|
@@ -28,17 +28,13 @@ module ActiveRecord::Associations
|
|
|
28
28
|
proxy_reflection.klass
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
else
|
|
38
|
-
find_without_block(*args)
|
|
39
|
-
end
|
|
31
|
+
def origin
|
|
32
|
+
proxy_owner
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def origin_attribute
|
|
36
|
+
proxy_reflection.association_name
|
|
40
37
|
end
|
|
41
|
-
alias_method_chain :find, :block
|
|
42
38
|
|
|
43
39
|
private
|
|
44
40
|
|
|
@@ -102,7 +102,7 @@ class Test::Unit::TestCase
|
|
|
102
102
|
def replace_objects_in_params!(hash)
|
|
103
103
|
hash.each do |k,v|
|
|
104
104
|
if v.is_a? ActiveRecord::Base
|
|
105
|
-
hash[k] = "@" +
|
|
105
|
+
hash[k] = "@" + v.typed_id
|
|
106
106
|
elsif v.is_a? Hash
|
|
107
107
|
replace_objects_in_params!(v)
|
|
108
108
|
end
|
|
@@ -5,20 +5,12 @@ module Hobo
|
|
|
5
5
|
class RawJs < String; end
|
|
6
6
|
|
|
7
7
|
@models = []
|
|
8
|
-
@field_types = HashWithIndifferentAccess.new
|
|
9
8
|
|
|
10
9
|
class << self
|
|
11
10
|
|
|
12
|
-
attr_accessor :current_theme
|
|
11
|
+
attr_accessor :current_theme
|
|
13
12
|
attr_writer :developer_features
|
|
14
13
|
|
|
15
|
-
def symbolic_type_name(type)
|
|
16
|
-
field_types.index(type)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def type_id(type)
|
|
20
|
-
symbolic_type_name(type) || type.name.underscore.gsub("/", "__")
|
|
21
|
-
end
|
|
22
14
|
|
|
23
15
|
def developer_features?
|
|
24
16
|
@developer_features
|
|
@@ -41,7 +33,7 @@ module Hobo
|
|
|
41
33
|
|
|
42
34
|
|
|
43
35
|
def models=(models)
|
|
44
|
-
@models = models
|
|
36
|
+
@models = models.*.name
|
|
45
37
|
end
|
|
46
38
|
|
|
47
39
|
|
|
@@ -52,7 +44,7 @@ module Hobo
|
|
|
52
44
|
end
|
|
53
45
|
@models_loaded = true
|
|
54
46
|
end
|
|
55
|
-
@models
|
|
47
|
+
@models.*.constantize
|
|
56
48
|
end
|
|
57
49
|
|
|
58
50
|
|
|
@@ -87,64 +79,38 @@ module Hobo
|
|
|
87
79
|
end
|
|
88
80
|
|
|
89
81
|
def dom_id(obj, attr=nil)
|
|
90
|
-
if obj.nil?
|
|
91
|
-
raise ArgumentError, "Tried to get dom id of nil.#{attr}" if attr
|
|
92
|
-
return 'nil'
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
if obj.is_a?(Array) and obj.respond_to?(:proxy_owner)
|
|
96
|
-
attr = obj.proxy_reflection.name
|
|
97
|
-
obj = obj.proxy_owner
|
|
98
|
-
elsif obj.is_a?(Class)
|
|
99
|
-
return type_id(obj)
|
|
100
|
-
elsif !obj.respond_to?(:typed_id)
|
|
101
|
-
return (if attr
|
|
102
|
-
dom_id(get_field(obj, attr))
|
|
103
|
-
elsif obj.respond_to?(:id)
|
|
104
|
-
"#{obj.class.name.underscore}_#{obj.id}"
|
|
105
|
-
else
|
|
106
|
-
raise ArgumentError, "Can't create dom id for #{obj.inspect}"
|
|
107
|
-
end)
|
|
108
|
-
end
|
|
109
82
|
attr ? "#{obj.typed_id}_#{attr}" : obj.typed_id
|
|
110
83
|
end
|
|
111
84
|
|
|
112
|
-
def find_by_search(query)
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
where = cols.map {|c| "(#{c} like ?)"}.join(' or ')
|
|
121
|
-
type = model.column_names.include?("type") ? "type" : "'#{model.name}'"
|
|
122
|
-
ActiveRecord::Base.send(:sanitize_sql,
|
|
123
|
-
["select #{type} as type, id " +
|
|
124
|
-
"from #{model.table_name} " +
|
|
125
|
-
"where #{where}"] +
|
|
126
|
-
["%#{query}%"] * cols.length)
|
|
85
|
+
def find_by_search(query, search_targets=nil)
|
|
86
|
+
search_targets ||=
|
|
87
|
+
begin
|
|
88
|
+
# FIXME: This should interrogate the model-router directly, there's no need to enumerate models
|
|
89
|
+
# By default, search all models, but filter out...
|
|
90
|
+
Hobo.models.select do |m|
|
|
91
|
+
ModelRouter.linkable?(m, :show) && # ...non-linkables
|
|
92
|
+
m.search_columns.any? # and models with no search-columns
|
|
127
93
|
end
|
|
128
94
|
end
|
|
129
|
-
end.compact.join(" union ")
|
|
130
|
-
|
|
131
|
-
rows = ActiveRecord::Base.connection.select_all(sql)
|
|
132
|
-
records = Hash.new {|h,k| h[k] = []}
|
|
133
|
-
for row in rows
|
|
134
|
-
records[row['type']] << row['id']
|
|
135
|
-
end
|
|
136
|
-
results = []
|
|
137
|
-
for type, ids in records
|
|
138
|
-
results.concat(type.constantize.find(:all, :conditions => "id in (#{ids * ','})"))
|
|
139
|
-
end
|
|
140
95
|
|
|
141
|
-
|
|
96
|
+
query_words = ActiveRecord::Base.connection.quote_string(query).split
|
|
97
|
+
|
|
98
|
+
search_targets.build_hash do |search_target|
|
|
99
|
+
conditions = query_words.map do |word|
|
|
100
|
+
"(" + search_target.search_columns.map { |column| %(#{column} like "%#{word}%") }.join(" or ") + ")"
|
|
101
|
+
end.join(" and ")
|
|
102
|
+
|
|
103
|
+
results = search_target.find(:all, :conditions => conditions)
|
|
104
|
+
[search_target.name, results] unless results.empty?
|
|
105
|
+
end
|
|
142
106
|
end
|
|
143
107
|
|
|
144
108
|
def add_routes(m)
|
|
145
109
|
Hobo::ModelRouter.add_routes(m)
|
|
146
110
|
end
|
|
147
111
|
|
|
112
|
+
|
|
113
|
+
# FIXME: This method won't be needed
|
|
148
114
|
def all_models
|
|
149
115
|
Hobo.models.map { |m| m.name.underscore }
|
|
150
116
|
end
|
|
@@ -159,6 +125,16 @@ module Hobo
|
|
|
159
125
|
end
|
|
160
126
|
|
|
161
127
|
|
|
128
|
+
def can_create_in_association?(array_or_reflection)
|
|
129
|
+
refl =
|
|
130
|
+
(array_or_reflection.is_a?(ActiveRecord::Reflection::AssociationReflection) and array_or_reflection) or
|
|
131
|
+
array_or_reflection.try.proxy_reflection or
|
|
132
|
+
(origin = array_or_reflection.try.origin and origin.send(array_or_reflection.origin_attribute).try.proxy_reflection)
|
|
133
|
+
|
|
134
|
+
refl && refl.macro == :has_many && (!refl.through_reflection) && (!refl.options[:conditions])
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
|
|
162
138
|
def get_field(object, field)
|
|
163
139
|
return nil if object.nil?
|
|
164
140
|
if field.to_s =~ /^\d+$/
|
|
@@ -213,10 +189,12 @@ module Hobo
|
|
|
213
189
|
return false if !can_view?(person, object, field)
|
|
214
190
|
|
|
215
191
|
if field.nil?
|
|
216
|
-
if
|
|
192
|
+
if object.has_hobo_method?(:editable_by?)
|
|
217
193
|
object.editable_by?(person)
|
|
218
|
-
|
|
194
|
+
elsif object.has_hobo_method?(:updatable_by?)
|
|
219
195
|
object.updatable_by?(person, nil)
|
|
196
|
+
else
|
|
197
|
+
false
|
|
220
198
|
end
|
|
221
199
|
|
|
222
200
|
else
|
|
@@ -333,7 +311,7 @@ module Hobo
|
|
|
333
311
|
else
|
|
334
312
|
File.join(File.dirname(__FILE__), "hobo/static_tags")
|
|
335
313
|
end
|
|
336
|
-
File.readlines(path)
|
|
314
|
+
File.readlines(path).*.chop
|
|
337
315
|
end
|
|
338
316
|
end
|
|
339
317
|
|
|
@@ -38,7 +38,7 @@ module Hobo
|
|
|
38
38
|
# skip_before_filter :login_required
|
|
39
39
|
#
|
|
40
40
|
def login_required(user_model=nil)
|
|
41
|
-
auth_model = user_model ||
|
|
41
|
+
auth_model = user_model || User.default_user_model
|
|
42
42
|
if current_user.guest?
|
|
43
43
|
username, passwd = get_auth_data
|
|
44
44
|
self.current_user = auth_model.authenticate(username, passwd) || nil if username && passwd && auth_model
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
require 'extensions'
|
|
2
|
-
|
|
3
1
|
module ::Hobo
|
|
4
2
|
|
|
5
3
|
class Bundle
|
|
@@ -8,48 +6,93 @@ module ::Hobo
|
|
|
8
6
|
|
|
9
7
|
class << self
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
# Hobo::Bundle.bundles is a hash of all instantiated bundles by name
|
|
10
|
+
attr_accessor :bundles
|
|
11
|
+
|
|
12
|
+
# Used by subclasses, e.g MyBundle.plugin is the name of the
|
|
13
|
+
# plugin the bundle came from
|
|
14
|
+
attr_reader :plugin
|
|
15
|
+
|
|
16
|
+
attr_reader :model_declarations, :controller_declarations
|
|
17
|
+
|
|
18
|
+
attr_accessor :dirname
|
|
12
19
|
|
|
13
20
|
def inherited(base)
|
|
14
21
|
filename = caller[0].match(/^(.*):\d+/)[1]
|
|
15
|
-
dirname = filename.match(%r(^.*/plugins/[^/]+))[0]
|
|
16
|
-
|
|
22
|
+
base.dirname = filename.match(%r(^.*/plugins/[^/]+))[0]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def load_models_and_controllers
|
|
27
|
+
return if models_and_controllers_loaded?
|
|
17
28
|
|
|
18
|
-
|
|
19
|
-
attr_accessor :models, :controllers
|
|
20
|
-
end
|
|
29
|
+
@plugin = File.basename(dirname)
|
|
21
30
|
|
|
22
|
-
|
|
23
|
-
|
|
31
|
+
@model_declarations = []
|
|
32
|
+
@controller_declarations = []
|
|
24
33
|
|
|
25
|
-
|
|
26
|
-
|
|
34
|
+
class_eval do
|
|
35
|
+
eval_ruby_files("#{dirname}/models", @models)
|
|
36
|
+
eval_ruby_files("#{dirname}/controllers", @controllers)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def [](bundle_name)
|
|
41
|
+
bundles[bundle_name]
|
|
27
42
|
end
|
|
28
43
|
|
|
44
|
+
|
|
45
|
+
private
|
|
29
46
|
|
|
30
47
|
def bundle_model(name, &block)
|
|
31
|
-
|
|
48
|
+
@model_declarations << [name, block]
|
|
32
49
|
end
|
|
33
50
|
|
|
34
51
|
|
|
35
52
|
def bundle_model_controller(model_name, &block)
|
|
36
|
-
|
|
53
|
+
@controller_declarations << [model_name, block]
|
|
37
54
|
end
|
|
55
|
+
|
|
38
56
|
|
|
57
|
+
def models_and_controllers_loaded?
|
|
58
|
+
@model_declarations
|
|
59
|
+
end
|
|
39
60
|
|
|
40
|
-
private
|
|
41
61
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
62
|
+
|
|
63
|
+
def eval_ruby_files(dir, filenames)
|
|
64
|
+
files = if filenames == [:none]
|
|
65
|
+
[]
|
|
66
|
+
elsif filenames.blank? || filenames == [:all]
|
|
67
|
+
Dir["#{dir}/*.rb"]
|
|
68
|
+
else
|
|
69
|
+
filenames.map { |f| "#{dir}/#{f}.rb" }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
files.each { |f| instance_eval(File.read(f), f, 1) }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# Declatations
|
|
77
|
+
|
|
78
|
+
def models(*models)
|
|
79
|
+
@models = models
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def controllers(*controllers)
|
|
83
|
+
@controllers = controllers.map {|c| case c.to_s
|
|
84
|
+
when /controller$/, "all", "none" then c
|
|
85
|
+
else "#{c.to_s.pluralize}_controller"
|
|
86
|
+
end }
|
|
46
87
|
end
|
|
47
88
|
|
|
48
89
|
end
|
|
49
90
|
|
|
50
91
|
def initialize(*args)
|
|
92
|
+
self.class.load_models_and_controllers
|
|
93
|
+
|
|
51
94
|
options = defaults.with_indifferent_access
|
|
52
|
-
options.
|
|
95
|
+
options.recursive_update(args.extract_options!)
|
|
53
96
|
|
|
54
97
|
self.name = args.first || self.class.name.match(/[^:]+$/)[0].underscore
|
|
55
98
|
Bundle.bundles[name] = self
|
|
@@ -78,18 +121,52 @@ module ::Hobo
|
|
|
78
121
|
|
|
79
122
|
|
|
80
123
|
def create_models
|
|
81
|
-
self.class.
|
|
82
|
-
klass = make_class(new_name_for(name), ActiveRecord::Base)
|
|
83
|
-
|
|
124
|
+
self.class.model_declarations.each do |name, block|
|
|
125
|
+
klass = make_class(new_name_for(name), ActiveRecord::Base)
|
|
126
|
+
|
|
127
|
+
klass.meta_def :belongs_to_with_optional_polymorphism do |*args|
|
|
128
|
+
opts = args.extract_options!
|
|
129
|
+
|
|
130
|
+
if opts[:polymorphic] == :optional
|
|
131
|
+
if bundle.options["polymorphic_#{name}"]
|
|
132
|
+
opts[:polymorphic] = true
|
|
133
|
+
opts.delete(:class_name)
|
|
134
|
+
else
|
|
135
|
+
opts.delete(:polymorphic)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
belongs_to_without_optional_polymorphism(name, opts)
|
|
84
139
|
end
|
|
85
|
-
klass.
|
|
140
|
+
klass.meta_eval { alias_method_chain :belongs_to, :optional_polymorphism }
|
|
141
|
+
|
|
142
|
+
klass.class_eval { hobo_model }
|
|
143
|
+
|
|
144
|
+
# FIXME this extension breaks passing a block to belongs_to
|
|
145
|
+
klass.meta_def :belongs_to_with_alias do |*args|
|
|
146
|
+
opts = args.extract_options!
|
|
147
|
+
name = args.first.to_sym
|
|
148
|
+
|
|
149
|
+
alias_name = opts.delete(:alias)
|
|
150
|
+
|
|
151
|
+
belongs_to_without_alias(name, opts)
|
|
152
|
+
|
|
153
|
+
if alias_name && name != alias_name
|
|
154
|
+
klass.send(:alias_method, alias_name, name)
|
|
155
|
+
# make the aliased name available in the classes metadata
|
|
156
|
+
klass.reflections[alias_name] = klass.reflections[name]
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
end
|
|
160
|
+
klass.meta_eval { alias_method_chain :belongs_to, :alias }
|
|
161
|
+
|
|
162
|
+
klass.class_eval(&block)
|
|
86
163
|
end
|
|
87
164
|
end
|
|
88
165
|
|
|
89
166
|
|
|
90
167
|
def create_controllers
|
|
91
168
|
bundle = self
|
|
92
|
-
self.class.
|
|
169
|
+
self.class.controller_declarations.each do |model_name, block|
|
|
93
170
|
klass = make_class("#{new_name_for(model_name).to_s.pluralize}Controller", ApplicationController) do
|
|
94
171
|
hobo_model_controller
|
|
95
172
|
end
|
|
@@ -106,6 +183,14 @@ module ::Hobo
|
|
|
106
183
|
def self.feature(name, &block)
|
|
107
184
|
_feature(name, block)
|
|
108
185
|
end
|
|
186
|
+
|
|
187
|
+
def method_missing(name, *args)
|
|
188
|
+
if name.to_s =~ /^_.*_$/
|
|
189
|
+
self.class.bundle.magic_option(name)
|
|
190
|
+
else
|
|
191
|
+
super
|
|
192
|
+
end
|
|
193
|
+
end
|
|
109
194
|
end
|
|
110
195
|
|
|
111
196
|
klass.meta_def(:bundle) do
|
|
@@ -134,19 +219,23 @@ module ::Hobo
|
|
|
134
219
|
end
|
|
135
220
|
|
|
136
221
|
klass.class_eval(&b) if b
|
|
222
|
+
|
|
137
223
|
klass
|
|
138
224
|
end
|
|
139
225
|
|
|
140
226
|
|
|
141
227
|
def new_name_for(name)
|
|
142
|
-
while
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
228
|
+
while true
|
|
229
|
+
if renames.has_key?(name)
|
|
230
|
+
name = renames[name]
|
|
231
|
+
elsif name.to_s =~ /_.*?_/
|
|
232
|
+
name2 = name.to_s.gsub(/_.*?_/) { |s| new_name_for(s[1..-2]) }
|
|
233
|
+
# Make sure symbols stay symbols
|
|
234
|
+
name = name.is_a?(Symbol) ? name2.to_sym : name2
|
|
235
|
+
else
|
|
236
|
+
return name
|
|
237
|
+
end
|
|
148
238
|
end
|
|
149
|
-
name
|
|
150
239
|
end
|
|
151
240
|
|
|
152
241
|
|
|
@@ -169,7 +258,7 @@ module ::Hobo
|
|
|
169
258
|
new_name_for(name).to_s.constantize.class_eval(&block)
|
|
170
259
|
end
|
|
171
260
|
|
|
172
|
-
|
|
261
|
+
|
|
173
262
|
def method_missing(name, *args)
|
|
174
263
|
if name.to_s =~ /^_.*_$/
|
|
175
264
|
magic_option(name)
|
|
@@ -213,7 +302,15 @@ module ::Hobo
|
|
|
213
302
|
external_options = self.options[option_name]
|
|
214
303
|
external_options = {} if external_options.nil? || external_options == true
|
|
215
304
|
name = "#{self.name}_#{option_name}"
|
|
216
|
-
|
|
305
|
+
|
|
306
|
+
sub_bundle_options = external_options.merge(local_options).merge(renames)
|
|
307
|
+
sub_bundle = class_name.to_s.constantize.new(name, sub_bundle_options)
|
|
308
|
+
|
|
309
|
+
conflicting_renames = (renames.keys & sub_bundle.renames.keys).select { |k| renames[k] != sub_bundle.renames[k] }
|
|
310
|
+
unless conflicting_renames.empty?
|
|
311
|
+
raise ArgumentError, "Conflicting renames in included bundle '#{name}' of '#{self.name}': #{conflicting_renames * ', '}"
|
|
312
|
+
end
|
|
313
|
+
renames.update(sub_bundle.renames)
|
|
217
314
|
self.options["#{option_name}_bundle"] = name
|
|
218
315
|
end
|
|
219
316
|
|