hobo_files/plugin/lib/hobo/model.rb in hobo-0.7.0 vs hobo_files/plugin/lib/hobo/model.rb in hobo-0.7.1
- old
+ new
@@ -1,9 +1,13 @@
module Hobo
module Model
+ NAME_FIELD_GUESS = %w(name title)
+ PRIMARY_CONTENT_GUESS = %w(description body content profile)
+ SEARCH_COLUMNS_GUESS = %w(name title body content profile)
+
PLAIN_TYPES = { :boolean => TrueClass,
:date => Date,
:datetime => Time,
:integer => Fixnum,
:big_integer => BigDecimal,
@@ -16,14 +20,16 @@
def self.included(base)
Hobo.register_model(base)
base.extend(ClassMethods)
base.class_eval do
alias_method_chain :attributes=, :hobo_type_conversion
+ default_scopes
end
class << base
alias_method_chain :has_many, :defined_scopes
alias_method_chain :belongs_to, :foreign_key_declaration
+ alias_method_chain :belongs_to, :hobo_metadata
alias_method_chain :acts_as_list, :fields if defined?(ActiveRecord::Acts::List)
def inherited(klass)
fields do
Hobo.register_model(klass)
field(klass.inheritance_column, :string)
@@ -35,10 +41,48 @@
module ClassMethods
# include methods also shared by CompositeModel
include ModelSupport::ClassMethods
+ attr_accessor :creator_attribute
+ attr_writer :name_attribute, :primary_content_attribute
+
+ def default_scopes
+ def_scope :recent do |*args|
+ count = args.first || 3
+ { :limit => count, :order => "#{table_name}.created_at DESC" }
+ end
+ end
+
+ def name_attribute
+ @name_attribute ||= begin
+ cols = columns.every :name
+ NAME_FIELD_GUESS.detect {|f| f.in? columns.every(:name) }
+ end
+ end
+
+
+ def primary_content_attribute
+ @description_attribute ||= begin
+ cols = columns.every :name
+ PRIMARY_CONTENT_GUESS.detect {|f| f.in? columns.every(:name) }
+ end
+ end
+
+ def dependent_collections
+ reflections.values.select do |refl|
+ refl.macro == :has_many && refl.options[:dependent]
+ end.every(:name)
+ end
+
+
+ def dependent_on
+ reflections.values.select do |refl|
+ refl.macro == :belongs_to && (rev = reverse_reflection(refl.name) and rev.options[:dependent])
+ end.every(:name)
+ end
+
private
def return_type(type)
@next_method_type = type
end
@@ -73,10 +117,17 @@
type_col = "#{name}_type"
field_specs[type_col] ||= FieldSpec.new(self, type_col, :string, column_options)
end
res
end
+
+
+ def belongs_to_with_hobo_metadata(name, *args, &block)
+ options = args.extract_options!
+ self.creator_attribute = name.to_sym if options.delete(:creator)
+ belongs_to_without_hobo_metadata(name, *args + [options], &block)
+ end
def acts_as_list_with_fields(options = {})
fields { |f| f.send(options._?[:column] || "position", :integer) }
acts_as_list_without_fields(options)
@@ -123,16 +174,10 @@
def never_show?(field)
(@hobo_never_show && field.to_sym.in?(@hobo_never_show)) || (superclass < Hobo::Model && superclass.never_show?(field))
end
public :never_show?
- def set_creator_attr(attr)
- @creator_attr = attr.to_sym
- end
- attr_reader :creator_attr
- public :creator_attr
-
def set_search_columns(*columns)
class_eval %{
def self.search_columns
%w{#{columns.every(:to_s) * ' '}}
end
@@ -279,16 +324,16 @@
has_many(assoc, refl.options.merge(options))
end
end
def creator_type
- reflections[@creator_attr]._?.klass
+ reflections[creator_attribute]._?.klass
end
def search_columns
cols = columns.every(:name)
- %w{name title body content}.select{|c| c.in?(cols) }
+ SEARCH_COLUMNS_GUESS.select{|c| c.in?(cols) }
end
# This should really be a method on AssociationReflection
def reverse_reflection(association_name)
refl = reflections[association_name]
@@ -298,13 +343,13 @@
:belongs_to
elsif refl.macro == :belongs_to
:has_many
end
refl.klass.reflections.values.find do |r|
- r.macro == reverse_macro and
- r.klass == self and
- !r.options[:conditions] and
+ r.macro == reverse_macro &&
+ r.klass == self &&
+ !r.options[:conditions] &&
r.primary_key_name == refl.primary_key_name
end
end
@@ -455,19 +500,34 @@
end
end
end
+ def dependent_on
+ self.class.dependent_on.map { |assoc| send(assoc) }
+ end
+
+
def attributes_with_hobo_type_conversion=(attributes, guard_protected_attributes=true)
converted = attributes.map_hash { |k, v| convert_type_for_mass_assignment(self.class.field_type(k), v) }
send(:attributes_without_hobo_type_conversion=, converted, guard_protected_attributes)
end
def set_creator(user)
- self.send("#{self.class.creator_attr}=", user) if (t = self.class.creator_type) && user.is_a?(t)
+ attr = self.class.creator_attribute
+ return unless attr
+
+ # Is creator a string field or an association?
+ if self.class.reflections[attr]
+ # It's an association
+ self.send("#{attr}=", user) if (t = self.class.creator_type) && user.is_a?(t)
+ else
+ # Assume it's a string field -- set it to the name of the current user
+ self.send("#{attr}=", user.to_s) unless user.guest?
+ end
end
def duplicate
res = self.class.new
@@ -485,15 +545,19 @@
res
end
def same_fields?(other, *fields)
+ return true if other.nil?
+
fields = fields.flatten
fields.all?{|f| self.send(f) == other.send(f)}
end
def only_changed_fields?(other, *changed_fields)
+ return true if other.nil?
+
changed_fields = changed_fields.flatten.every(:to_s)
all_cols = self.class.columns.every(:name) - []
all_cols.all?{|c| c.in?(changed_fields) || self.send(c) == other.send(c) }
end
@@ -512,15 +576,13 @@
def typed_id
id ? "#{self.class.name.underscore}_#{self.id}" : nil
end
def to_s
- if respond_to? :title
- title
- elsif respond_to? :name
- name
+ if self.class.name_attribute
+ send self.class.name_attribute
else
- "#{self.class.name.humanize} #{id}"
+ "#{self.class.name.titleize} #{id}"
end
end
private