Module: Hobo::Model

Includes:
Scopes
Defined in:
lib/hobo/model.rb,
lib/hobo/model/guest.rb,
lib/hobo/model/scopes.rb,
lib/hobo/model/find_for.rb,
lib/hobo/model/user_base.rb,
lib/hobo/model/lifecycles.rb,
lib/hobo/model/view_hints.rb,
lib/hobo/model/permissions.rb,
lib/hobo/model/include_in_save.rb,
lib/hobo/model/lifecycles/state.rb,
lib/hobo/model/lifecycles/actions.rb,
lib/hobo/model/lifecycles/creator.rb,
lib/hobo/model/scopes/apply_scopes.rb,
lib/hobo/model/lifecycles/lifecycle.rb,
lib/hobo/model/lifecycles/transition.rb,
lib/hobo/model/accessible_associations.rb,
lib/hobo/model/scopes/automatic_scopes.rb

Defined Under Namespace

Modules: AccessibleAssociations, ClassMethods, FindFor, Lifecycles, Permissions, Scopes, UserBase Classes: Guest, NoNameError, ViewHints

Constant Summary collapse

NAME_FIELD_GUESS =
%w(name title)
PRIMARY_CONTENT_GUESS =
%w(description body content profile)
SEARCH_COLUMNS_GUESS =
%w(name title body description content profile)
IncludeInSave =
classy_module do

  attr_accessor :included_in_save

  validate         :validate_included_in_save
  before_save      :save_included
  after_save       :clear_included_in_save

  def include_in_save(association, *records)
    self.included_in_save ||= Hash.new {|h, k| h[k] = []}
    included_in_save[association.to_sym].concat records
  end

  def validate_included_in_save
    if included_in_save
      included_in_save._?.each_pair do |association, records|
        next if self.class.reflections[association.to_s].options[:validate]==false
        added = false
        records.each do |record|
          # we want to call valid? on each one, but only add the error to self once

          record.with_acting_user(acting_user) do
            unless record.valid?
              unless added
                errors.add association, "..."
                added = true
              end
            end
          end
        end
      end
    end
  end


  def save_included
    if included_in_save
      included_in_save.each_pair do |association, records|
        records.each do |record|
          # save(:validate => false) means without transactions too
          record.with_acting_user(acting_user) { record.save(:validate => false) }
        end
      end
    end
  end

  def clear_included_in_save
    included_in_save._?.clear
  end

end

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Scopes

included_in_class

Class Method Details

.all_modelsObject



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/hobo/model.rb', line 50

def self.all_models
  # Load every model in app/models...
  unless @models_loaded
    Dir.entries("#{Rails.root}/app/models/").each do |f|
      f =~ /^[a-zA-Z_][a-zA-Z0-9_]*\.rb$/ and f.sub(/.rb$/, '').camelize.constantize
    end
    @models_loaded = true
  end

  @model_names ||= Set.new
  # ...but only return the ones that registered themselves
  @model_names.map do |name|
    name.safe_constantize || (@model_names.delete name; nil)
  end.compact
end

.find_by_typed_id(typed_id) ⇒ Object

Raises:

  • (ArgumentError)


67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/hobo/model.rb', line 67

def self.find_by_typed_id(typed_id)
  return nil if typed_id == 'nil'

  _, name, id, attr = *typed_id.match(/^([^:]+)(?::([^:]+)(?::([^:]+))?)?$/)
  raise ArgumentError.new("invalid typed-id: #{typed_id}") unless name

  model_class = name.camelize.safe_constantize or raise ArgumentError.new("no such class in typed-id: #{typed_id}")
  return nil unless model_class

  if id
    obj = model_class.find(id)
      # Optimise: can we use eager loading in the situation where the attr is a belongs_to?
      # We used to, but hit a bug in AR
    attr ? obj.send(attr) : obj
  else
    model_class
  end
end

.included(base) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/hobo/model.rb', line 13

def self.included(base)
  base.extend(ClassMethods)

  register_model(base)

  base.class_eval do
    inheriting_cattr_reader :default_order

    cattr_accessor :hobo_controller
    self.hobo_controller = {}

    include Permissions
    include Lifecycles::ModelExtensions
    include FindFor
    include AccessibleAssociations
    include IncludeInSave
  end

  class << base
    alias_method_chain :belongs_to,    :creator_metadata
    alias_method_chain :belongs_to,    :test_methods
    alias_method_chain :attr_accessor, :creator_metadata

    alias_method_chain :has_one, :new_method
  end

  base.fields(false) # force hobo_fields to load

  included_in_class_callbacks(base)
end

.register_model(model) ⇒ Object



44
45
46
47
# File 'lib/hobo/model.rb', line 44

def self.register_model(model)
  @model_names ||= Set.new
  @model_names << model.name
end

Instance Method Details

#get_creatorObject



401
402
403
# File 'lib/hobo/model.rb', line 401

def get_creator
  self.class.creator_attribute && send(self.class.creator_attribute)
end

#set_creator(user) ⇒ Object

We deliberately give these three methods unconventional (java-esque) names to avoid polluting the application namespace



376
377
378
# File 'lib/hobo/model.rb', line 376

def set_creator(user)
  set_creator!(user) unless get_creator
end

#set_creator!(user) ⇒ Object



381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
# File 'lib/hobo/model.rb', line 381

def set_creator!(user)
  attr = self.class.creator_attribute
  return unless attr

  attr_type = self.class.creator_type

  # Is creator an instance, a string field or an association?
  if !attr_type.is_a?(Class)
    # attr_type is an instance - typically AssociationReflection for a polymorphic association
    self.send("#{attr}=", user)
  elsif self.class.attr_type(attr)._? <= String
    # Set it to the name of the current user
    self.send("#{attr}=", user.to_s) unless user.guest?
  else
    # Assume user is a user object, but don't set if we've got a type mismatch
    self.send("#{attr}=", user) if attr_type.nil? || user.is_a?(attr_type)
  end
end

#to_paramObject



362
363
364
365
366
367
368
369
370
# File 'lib/hobo/model.rb', line 362

def to_param
  name_attr = self.class.name_attribute and name = send(name_attr)
  if name_attr && !name.blank? && id.is_a?(Fixnum)
    readable = name.to_s.downcase.gsub(/[^a-z0-9]+/, '-').remove(/-+$/).remove(/^-+/).split('-')[0..5].join('-')
    @to_param ||= "#{id}-#{readable}"
  else
    id.to_s
  end
end

#to_sObject



411
412
413
414
415
416
417
# File 'lib/hobo/model.rb', line 411

def to_s
  if self.class.name_attribute
    send self.class.name_attribute
  else
    "#{self.class.model_name.human} #{id}"
  end
end

#to_url_pathObject



357
358
359
# File 'lib/hobo/model.rb', line 357

def to_url_path
  "#{self.class.to_url_path}/#{to_param}"
end

#typed_idObject



406
407
408
# File 'lib/hobo/model.rb', line 406

def typed_id
  "#{self.class.name.underscore}:#{self.id}" if id
end