hobo 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- data/hobo_files/plugin/CHANGES.txt +220 -23
- data/hobo_files/plugin/generators/hobo_front_controller/templates/index.dryml +18 -25
- data/hobo_files/plugin/generators/hobo_migration/hobo_migration_generator.rb +20 -15
- data/hobo_files/plugin/generators/hobo_model/templates/model.rb +3 -3
- data/hobo_files/plugin/generators/hobo_rapid/hobo_rapid_generator.rb +3 -3
- data/hobo_files/plugin/generators/hobo_rapid/templates/hobo-rapid.css +1 -2
- data/hobo_files/plugin/generators/hobo_rapid/templates/hobo-rapid.js +21 -4
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/images/fieldbg.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/images/spinner.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/stylesheets/application.css +154 -26
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/stylesheets/rapid-ui.css +144 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/views/application.dryml +1 -1
- data/hobo_files/plugin/generators/hobo_user_controller/templates/controller.rb +1 -1
- data/hobo_files/plugin/generators/hobo_user_model/templates/model.rb +8 -11
- data/hobo_files/plugin/init.rb +0 -2
- data/hobo_files/plugin/lib/active_record/has_many_association.rb +0 -9
- data/hobo_files/plugin/lib/active_record/has_many_through_association.rb +0 -10
- data/hobo_files/plugin/lib/hobo.rb +57 -44
- data/hobo_files/plugin/lib/hobo/bundle.rb +222 -0
- data/hobo_files/plugin/lib/hobo/controller.rb +2 -5
- data/hobo_files/plugin/lib/hobo/dryml.rb +8 -7
- data/hobo_files/plugin/lib/hobo/dryml/dryml_builder.rb +10 -21
- data/hobo_files/plugin/lib/hobo/dryml/taglib.rb +107 -80
- data/hobo_files/plugin/lib/hobo/dryml/template.rb +27 -20
- data/hobo_files/plugin/lib/hobo/enum_string.rb +1 -1
- data/hobo_files/plugin/lib/hobo/field_declaration_dsl.rb +7 -0
- data/hobo_files/plugin/lib/hobo/guest.rb +4 -0
- data/hobo_files/plugin/lib/hobo/hobo_helper.rb +37 -9
- data/hobo_files/plugin/lib/hobo/model.rb +79 -17
- data/hobo_files/plugin/lib/hobo/model_controller.rb +59 -60
- data/hobo_files/plugin/lib/hobo/model_router.rb +16 -4
- data/hobo_files/plugin/lib/hobo/rapid_helper.rb +2 -1
- data/hobo_files/plugin/lib/hobo/user.rb +10 -7
- data/hobo_files/plugin/lib/hobo/user_controller.rb +6 -6
- data/hobo_files/plugin/{tags → taglibs}/core.dryml +5 -4
- data/hobo_files/plugin/{tags → taglibs}/rapid.dryml +54 -7
- data/hobo_files/plugin/{tags → taglibs}/rapid_document_tags.dryml +0 -0
- data/hobo_files/plugin/{tags → taglibs}/rapid_editing.dryml +4 -2
- data/hobo_files/plugin/{tags → taglibs}/rapid_forms.dryml +1 -4
- data/hobo_files/plugin/{tags → taglibs}/rapid_navigation.dryml +1 -2
- data/hobo_files/plugin/taglibs/rapid_pages.dryml +411 -0
- data/hobo_files/plugin/{tags → taglibs}/rapid_plus.dryml +0 -0
- data/hobo_files/plugin/{tags → taglibs}/rapid_support.dryml +9 -6
- data/hobo_files/plugin/tasks/fix_dryml.rake +0 -1
- metadata +16 -14
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/stylesheets/rapid_ui.css +0 -167
- data/hobo_files/plugin/lib/hobo/plugins.rb +0 -75
- data/hobo_files/plugin/tags/rapid_pages.dryml +0 -341
@@ -2,6 +2,10 @@ module Hobo
|
|
2
2
|
|
3
3
|
module Model
|
4
4
|
|
5
|
+
NAME_FIELD_GUESS = %w(name title)
|
6
|
+
PRIMARY_CONTENT_GUESS = %w(description body content profile)
|
7
|
+
SEARCH_COLUMNS_GUESS = %w(name title body content profile)
|
8
|
+
|
5
9
|
PLAIN_TYPES = { :boolean => TrueClass,
|
6
10
|
:date => Date,
|
7
11
|
:datetime => Time,
|
@@ -18,10 +22,12 @@ module Hobo
|
|
18
22
|
base.extend(ClassMethods)
|
19
23
|
base.class_eval do
|
20
24
|
alias_method_chain :attributes=, :hobo_type_conversion
|
25
|
+
default_scopes
|
21
26
|
end
|
22
27
|
class << base
|
23
28
|
alias_method_chain :has_many, :defined_scopes
|
24
29
|
alias_method_chain :belongs_to, :foreign_key_declaration
|
30
|
+
alias_method_chain :belongs_to, :hobo_metadata
|
25
31
|
alias_method_chain :acts_as_list, :fields if defined?(ActiveRecord::Acts::List)
|
26
32
|
def inherited(klass)
|
27
33
|
fields do
|
@@ -37,6 +43,44 @@ module Hobo
|
|
37
43
|
# include methods also shared by CompositeModel
|
38
44
|
include ModelSupport::ClassMethods
|
39
45
|
|
46
|
+
attr_accessor :creator_attribute
|
47
|
+
attr_writer :name_attribute, :primary_content_attribute
|
48
|
+
|
49
|
+
def default_scopes
|
50
|
+
def_scope :recent do |*args|
|
51
|
+
count = args.first || 3
|
52
|
+
{ :limit => count, :order => "#{table_name}.created_at DESC" }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def name_attribute
|
57
|
+
@name_attribute ||= begin
|
58
|
+
cols = columns.every :name
|
59
|
+
NAME_FIELD_GUESS.detect {|f| f.in? columns.every(:name) }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
def primary_content_attribute
|
65
|
+
@description_attribute ||= begin
|
66
|
+
cols = columns.every :name
|
67
|
+
PRIMARY_CONTENT_GUESS.detect {|f| f.in? columns.every(:name) }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def dependent_collections
|
72
|
+
reflections.values.select do |refl|
|
73
|
+
refl.macro == :has_many && refl.options[:dependent]
|
74
|
+
end.every(:name)
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
def dependent_on
|
79
|
+
reflections.values.select do |refl|
|
80
|
+
refl.macro == :belongs_to && (rev = reverse_reflection(refl.name) and rev.options[:dependent])
|
81
|
+
end.every(:name)
|
82
|
+
end
|
83
|
+
|
40
84
|
private
|
41
85
|
|
42
86
|
def return_type(type)
|
@@ -75,6 +119,13 @@ module Hobo
|
|
75
119
|
end
|
76
120
|
res
|
77
121
|
end
|
122
|
+
|
123
|
+
|
124
|
+
def belongs_to_with_hobo_metadata(name, *args, &block)
|
125
|
+
options = args.extract_options!
|
126
|
+
self.creator_attribute = name.to_sym if options.delete(:creator)
|
127
|
+
belongs_to_without_hobo_metadata(name, *args + [options], &block)
|
128
|
+
end
|
78
129
|
|
79
130
|
|
80
131
|
def acts_as_list_with_fields(options = {})
|
@@ -125,12 +176,6 @@ module Hobo
|
|
125
176
|
end
|
126
177
|
public :never_show?
|
127
178
|
|
128
|
-
def set_creator_attr(attr)
|
129
|
-
@creator_attr = attr.to_sym
|
130
|
-
end
|
131
|
-
attr_reader :creator_attr
|
132
|
-
public :creator_attr
|
133
|
-
|
134
179
|
def set_search_columns(*columns)
|
135
180
|
class_eval %{
|
136
181
|
def self.search_columns
|
@@ -281,12 +326,12 @@ module Hobo
|
|
281
326
|
end
|
282
327
|
|
283
328
|
def creator_type
|
284
|
-
reflections[
|
329
|
+
reflections[creator_attribute]._?.klass
|
285
330
|
end
|
286
331
|
|
287
332
|
def search_columns
|
288
333
|
cols = columns.every(:name)
|
289
|
-
|
334
|
+
SEARCH_COLUMNS_GUESS.select{|c| c.in?(cols) }
|
290
335
|
end
|
291
336
|
|
292
337
|
# This should really be a method on AssociationReflection
|
@@ -300,9 +345,9 @@ module Hobo
|
|
300
345
|
:has_many
|
301
346
|
end
|
302
347
|
refl.klass.reflections.values.find do |r|
|
303
|
-
r.macro == reverse_macro
|
304
|
-
r.klass == self
|
305
|
-
!r.options[:conditions]
|
348
|
+
r.macro == reverse_macro &&
|
349
|
+
r.klass == self &&
|
350
|
+
!r.options[:conditions] &&
|
306
351
|
r.primary_key_name == refl.primary_key_name
|
307
352
|
end
|
308
353
|
end
|
@@ -457,6 +502,11 @@ module Hobo
|
|
457
502
|
end
|
458
503
|
|
459
504
|
|
505
|
+
def dependent_on
|
506
|
+
self.class.dependent_on.map { |assoc| send(assoc) }
|
507
|
+
end
|
508
|
+
|
509
|
+
|
460
510
|
def attributes_with_hobo_type_conversion=(attributes, guard_protected_attributes=true)
|
461
511
|
converted = attributes.map_hash { |k, v| convert_type_for_mass_assignment(self.class.field_type(k), v) }
|
462
512
|
send(:attributes_without_hobo_type_conversion=, converted, guard_protected_attributes)
|
@@ -465,7 +515,17 @@ module Hobo
|
|
465
515
|
|
466
516
|
|
467
517
|
def set_creator(user)
|
468
|
-
|
518
|
+
attr = self.class.creator_attribute
|
519
|
+
return unless attr
|
520
|
+
|
521
|
+
# Is creator a string field or an association?
|
522
|
+
if self.class.reflections[attr]
|
523
|
+
# It's an association
|
524
|
+
self.send("#{attr}=", user) if (t = self.class.creator_type) && user.is_a?(t)
|
525
|
+
else
|
526
|
+
# Assume it's a string field -- set it to the name of the current user
|
527
|
+
self.send("#{attr}=", user.to_s) unless user.guest?
|
528
|
+
end
|
469
529
|
end
|
470
530
|
|
471
531
|
|
@@ -487,11 +547,15 @@ module Hobo
|
|
487
547
|
|
488
548
|
|
489
549
|
def same_fields?(other, *fields)
|
550
|
+
return true if other.nil?
|
551
|
+
|
490
552
|
fields = fields.flatten
|
491
553
|
fields.all?{|f| self.send(f) == other.send(f)}
|
492
554
|
end
|
493
555
|
|
494
556
|
def only_changed_fields?(other, *changed_fields)
|
557
|
+
return true if other.nil?
|
558
|
+
|
495
559
|
changed_fields = changed_fields.flatten.every(:to_s)
|
496
560
|
all_cols = self.class.columns.every(:name) - []
|
497
561
|
all_cols.all?{|c| c.in?(changed_fields) || self.send(c) == other.send(c) }
|
@@ -514,12 +578,10 @@ module Hobo
|
|
514
578
|
end
|
515
579
|
|
516
580
|
def to_s
|
517
|
-
if
|
518
|
-
|
519
|
-
elsif respond_to? :name
|
520
|
-
name
|
581
|
+
if self.class.name_attribute
|
582
|
+
send self.class.name_attribute
|
521
583
|
else
|
522
|
-
"#{self.class.name.
|
584
|
+
"#{self.class.name.titleize} #{id}"
|
523
585
|
end
|
524
586
|
end
|
525
587
|
|
@@ -4,18 +4,10 @@ module Hobo
|
|
4
4
|
|
5
5
|
include Hobo::Controller
|
6
6
|
|
7
|
-
class PermissionDeniedError < RuntimeError; end
|
8
|
-
class UserPermissionError < StandardError
|
9
|
-
attr :models
|
10
|
-
def initialize(models)
|
11
|
-
@models = models || []
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
7
|
VIEWLIB_DIR = "taglibs"
|
16
8
|
|
17
9
|
PAGINATE_FORMATS = [ Mime::HTML, Mime::ALL ]
|
18
|
-
|
10
|
+
|
19
11
|
class << self
|
20
12
|
|
21
13
|
def included(base)
|
@@ -23,38 +15,14 @@ module Hobo
|
|
23
15
|
@auto_actions ||= {}
|
24
16
|
|
25
17
|
extend ClassMethods
|
26
|
-
|
18
|
+
|
19
|
+
helper_method :model, :current_user
|
27
20
|
before_filter :set_no_cache_headers
|
28
21
|
end
|
22
|
+
base.template_path_cache = {}
|
29
23
|
|
30
24
|
Hobo::Controller.included_in_class(base)
|
31
25
|
end
|
32
|
-
|
33
|
-
def find_partial(klass, as)
|
34
|
-
find_model_template(klass, as, :is_parital => true)
|
35
|
-
end
|
36
|
-
|
37
|
-
|
38
|
-
def template_path(dir, name, is_partial)
|
39
|
-
fileRx = is_partial ? /^_#{name}\.[^.]+/ : /^#{name}\.[^.]+/
|
40
|
-
full_dir = "#{RAILS_ROOT}/app/views/#{dir}"
|
41
|
-
if File.exists?(full_dir) && Dir.entries(full_dir).grep(fileRx).any?
|
42
|
-
return "#{dir}/#{name}"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
|
47
|
-
def find_model_template(klass, name, options={})
|
48
|
-
while klass and klass != ActiveRecord::Base
|
49
|
-
dir = klass.name.underscore.pluralize
|
50
|
-
dir = File.join(options[:subsite], dir) if options[:subsite]
|
51
|
-
path = template_path(dir, name, options[:is_partial])
|
52
|
-
return path if path
|
53
|
-
|
54
|
-
klass = klass.superclass
|
55
|
-
end
|
56
|
-
nil
|
57
|
-
end
|
58
26
|
|
59
27
|
end
|
60
28
|
|
@@ -62,6 +30,8 @@ module Hobo
|
|
62
30
|
|
63
31
|
attr_writer :model
|
64
32
|
|
33
|
+
attr_accessor :template_path_cache
|
34
|
+
|
65
35
|
def add_collection_actions(name)
|
66
36
|
defined_methods = instance_methods
|
67
37
|
|
@@ -400,6 +370,24 @@ module Hobo
|
|
400
370
|
end
|
401
371
|
|
402
372
|
|
373
|
+
def destination_after_create(record)
|
374
|
+
# The after_submit post parameter takes priority
|
375
|
+
params[:after_submit] ||
|
376
|
+
|
377
|
+
# Then try the records show page
|
378
|
+
object_url(@this, :if_available => true) ||
|
379
|
+
|
380
|
+
# Then the show page of the 'owning' object if there is one
|
381
|
+
(@this.dependent_on.first && object_url(@this.dependent_on.first, :if_available => true)) ||
|
382
|
+
|
383
|
+
# Last try - the index page for this model
|
384
|
+
object_url(@this.class, :if_available => true) ||
|
385
|
+
|
386
|
+
# Give up
|
387
|
+
home_page
|
388
|
+
end
|
389
|
+
|
390
|
+
|
403
391
|
# --- Action implementations --- #
|
404
392
|
|
405
393
|
def hobo_index(*args, &b)
|
@@ -478,7 +466,7 @@ module Hobo
|
|
478
466
|
response_block(&b) or
|
479
467
|
if valid?
|
480
468
|
respond_to do |wants|
|
481
|
-
wants.html { redirect_to(
|
469
|
+
wants.html { redirect_to(destination_after_create(@this)) }
|
482
470
|
wants.js { hobo_ajax_response || render(:text => "") }
|
483
471
|
end
|
484
472
|
elsif invalid?
|
@@ -510,14 +498,14 @@ module Hobo
|
|
510
498
|
@this.send(:clear_aggregation_cache)
|
511
499
|
@this.send(:clear_association_cache)
|
512
500
|
|
513
|
-
changes = params[
|
501
|
+
changes = params[@this.class.name.underscore]
|
514
502
|
@this.attributes = changes
|
515
503
|
save_and_set_status!(@this, original)
|
516
504
|
|
517
505
|
# Ensure current_user isn't out of date
|
518
506
|
@current_user = @this if @this == current_user
|
519
507
|
|
520
|
-
flash[:notice] = "Changes to the #{
|
508
|
+
flash[:notice] = "Changes to the #{@this.class.name.titleize.downcase} were saved" if !request.xhr? && valid?
|
521
509
|
|
522
510
|
set_named_this!
|
523
511
|
response_block(&b) or
|
@@ -671,32 +659,43 @@ module Hobo
|
|
671
659
|
end
|
672
660
|
end
|
673
661
|
|
662
|
+
|
663
|
+
def hobo_template_exists?(dir, name)
|
664
|
+
self.class.template_path_cache.clear if RAILS_ENV == "development"
|
665
|
+
self.class.template_path_cache.fetch([dir, name],
|
666
|
+
begin
|
667
|
+
full_dir = "#{RAILS_ROOT}/app/views/#{dir}"
|
668
|
+
!Dir["#{full_dir}/#{name}.*"].empty?
|
669
|
+
end)
|
670
|
+
end
|
671
|
+
|
672
|
+
|
673
|
+
def find_model_template(klass, name)
|
674
|
+
while klass and klass != ActiveRecord::Base
|
675
|
+
dir = klass.name.underscore.pluralize
|
676
|
+
dir = File.join(subsite, dir) if subsite
|
677
|
+
if hobo_template_exists?(dir, name)
|
678
|
+
return "#{dir}/#{name}"
|
679
|
+
end
|
680
|
+
klass = klass.superclass
|
681
|
+
end
|
682
|
+
nil
|
683
|
+
end
|
674
684
|
|
685
|
+
|
675
686
|
def hobo_render(page_kind = nil, page_model=nil)
|
676
687
|
page_kind ||= params[:action].to_sym
|
677
688
|
page_model ||= model
|
678
|
-
|
679
|
-
template = ModelController.find_model_template(page_model, page_kind, :subsite => subsite)
|
680
689
|
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
e = wrapper.original_exception if wrapper.respond_to? :original_exception
|
691
|
-
if e.is_a? Hobo::ModelController::UserPermissionError
|
692
|
-
if current_user.guest?
|
693
|
-
redirect_to login_url(e.models.first || UserController.user_models.first)
|
694
|
-
else
|
695
|
-
permission_denied(:message => e.message)
|
696
|
-
end
|
697
|
-
else
|
698
|
-
raise
|
699
|
-
end
|
690
|
+
if hobo_template_exists?(controller_path, page_kind)
|
691
|
+
render :action => page_kind
|
692
|
+
true
|
693
|
+
elsif (template = find_model_template(page_model, page_kind))
|
694
|
+
render :template => template
|
695
|
+
true
|
696
|
+
else
|
697
|
+
# This returns false if no such tag exists
|
698
|
+
render_tag("#{page_kind.to_s.dasherize}-page", :with => @this)
|
700
699
|
end
|
701
700
|
end
|
702
701
|
|
@@ -1,13 +1,24 @@
|
|
1
|
+
class ActionController::Routing::RouteSet
|
2
|
+
# Monkey patch this method so routes are reloaded on *every*
|
3
|
+
# request. Without this Rails checks the mtime of config/routes.rb
|
4
|
+
# which doesn't take into account Hobo's auto routing
|
5
|
+
def reload
|
6
|
+
load!
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
1
10
|
module Hobo
|
2
11
|
|
3
12
|
class ModelRouter
|
4
13
|
|
5
|
-
@linkable = Hash.new {|h, k| h[k] = Hash.new {|h, k| h[k] = {} } }
|
6
|
-
|
7
14
|
APP_ROOT = "#{RAILS_ROOT}/app"
|
8
15
|
|
9
16
|
class << self
|
10
17
|
|
18
|
+
def reset_linkables
|
19
|
+
@linkable = Hash.new {|h, k| h[k] = Hash.new {|h, k| h[k] = {} } }
|
20
|
+
end
|
21
|
+
|
11
22
|
def linkable(subsite, klass, action)
|
12
23
|
@linkable[subsite][klass.name][action] = true
|
13
24
|
end
|
@@ -17,6 +28,7 @@ module Hobo
|
|
17
28
|
end
|
18
29
|
|
19
30
|
def add_routes(map)
|
31
|
+
reset_linkables
|
20
32
|
begin
|
21
33
|
ActiveRecord::Base.connection.reconnect! unless ActiveRecord::Base.connection.active?
|
22
34
|
rescue
|
@@ -25,8 +37,8 @@ module Hobo
|
|
25
37
|
end
|
26
38
|
|
27
39
|
require "#{APP_ROOT}/controllers/application" unless Object.const_defined? :ApplicationController
|
28
|
-
|
29
|
-
|
40
|
+
load "#{APP_ROOT}/assemble.rb" if File.exists? "#{APP_ROOT}/assemble.rb"
|
41
|
+
|
30
42
|
# Add non-subsite routes
|
31
43
|
add_routes_for(map, nil)
|
32
44
|
|
@@ -11,6 +11,7 @@ module Hobo::RapidHelper
|
|
11
11
|
js_options['resultUpdate'] = js_result_updates(options[:result_update]) if options[:result_update]
|
12
12
|
js_options['resetForm'] = options[:reset_form] if options.has_key?(:reset_form)
|
13
13
|
js_options['refocusForm'] = options[:refocus_form] if options.has_key?(:refocus_form)
|
14
|
+
js_options['spinnerNextTo'] = options[:spinner_next_to] if options.has_key?(:spinner_next_to)
|
14
15
|
|
15
16
|
js_options.empty? ? nil : options_for_javascript(js_options)
|
16
17
|
end
|
@@ -97,7 +98,7 @@ module Hobo::RapidHelper
|
|
97
98
|
|
98
99
|
AJAX_ATTRS = [:before, :success, :failure, :complete, :type, :method,
|
99
100
|
:script, :form, :params, :confirm,
|
100
|
-
:reset_form, :refocus_form, :result_update]
|
101
|
+
:reset_form, :refocus_form, :result_update, :spinner_next_to]
|
101
102
|
|
102
103
|
|
103
104
|
def editor_class
|
@@ -41,7 +41,7 @@ module Hobo
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
# Additional classmethods for
|
44
|
+
# Additional classmethods for authentication
|
45
45
|
module ClassMethods
|
46
46
|
|
47
47
|
# Validation of the plaintext password
|
@@ -49,22 +49,20 @@ module Hobo
|
|
49
49
|
validates_length_of :password, :within => 4..40, :if => :password_required?
|
50
50
|
end
|
51
51
|
|
52
|
-
def
|
52
|
+
def login_attribute=(attr, validate=true)
|
53
53
|
@login_attr = attr = attr.to_sym
|
54
54
|
unless attr == :login
|
55
55
|
alias_attribute(:login, attr)
|
56
56
|
set_field_type :login => field_type(attr)
|
57
57
|
end
|
58
58
|
|
59
|
-
if
|
60
|
-
yield
|
61
|
-
else
|
59
|
+
if validate
|
62
60
|
validates_presence_of attr
|
63
61
|
validates_length_of attr, :within => 3..100
|
64
62
|
validates_uniqueness_of attr, :case_sensitive => false
|
65
63
|
end
|
66
64
|
end
|
67
|
-
|
65
|
+
attr_reader :login_attr
|
68
66
|
|
69
67
|
# Authenticates a user by their login name and unencrypted password. Returns the user or nil.
|
70
68
|
def authenticate(login, password)
|
@@ -86,6 +84,11 @@ module Hobo
|
|
86
84
|
def encrypt(password, salt)
|
87
85
|
Digest::SHA1.hexdigest("--#{salt}--#{password}--")
|
88
86
|
end
|
87
|
+
|
88
|
+
|
89
|
+
def set_admin_on_first_user
|
90
|
+
before_create { |user| user.administrator = true if count == 0 }
|
91
|
+
end
|
89
92
|
|
90
93
|
end
|
91
94
|
|
@@ -121,7 +124,7 @@ module Hobo
|
|
121
124
|
def guest?
|
122
125
|
false
|
123
126
|
end
|
124
|
-
|
127
|
+
|
125
128
|
protected
|
126
129
|
# Before filter that encrypts the password before having it stored in the database.
|
127
130
|
def encrypt_password
|