hobo_files/plugin/lib/hobo/model.rb in hobo-0.6.1 vs hobo_files/plugin/lib/hobo/model.rb in hobo-0.6.2
- old
+ new
@@ -26,10 +26,12 @@
end
class << base
alias_method_chain :has_many, :defined_scopes
alias_method_chain :belongs_to, :foreign_key_declaration
end
+ # respond_to? is slow on AR objects, use this instead where possible
+ base.send(:alias_method, :has_hobo_method?, :respond_to_without_attributes?)
end
module ClassMethods
# include methods also shared by CompositeModel
@@ -62,14 +64,17 @@
field(:updated_at, :datetime)
end
def field(name, *args)
type = args.shift
- options = extract_options_from_args!(args)
+ options = args.extract_options!
@model.send(:set_field_type, name => type) unless
type.in?(@model.connection.native_database_types.keys - [:text])
@model.field_specs[name] = FieldSpec.new(@model, name, type, options)
+
+ @model.send(:validates_presence_of, name) if :required.in?(args)
+ @model.send(:validates_uniqueness_of, name) if :unique.in?(args)
end
def method_missing(name, *args)
field(name, *args)
end
@@ -100,10 +105,17 @@
def set_field_type(types)
types.each_pair do |field, type|
type_class = Hobo.field_types[type] || type
field_types[field] = type_class
+
+ if "validate".in?(type_class.instance_methods)
+ self.validate do |record|
+ v = record.send(field).validate
+ record.errors.add(field, v) if v.is_a?(String)
+ end
+ end
end
end
def field_types
@@ -127,19 +139,14 @@
@hobo_never_show and field.to_sym.in?(@hobo_never_show)
end
public :never_show?
def set_creator_attr(attr)
- class_eval %{
- def creator
- #{attr};
- end
- def creator=(x)
- self.#{attr} = x;
- end
- }
+ @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) * ' '}}
@@ -223,31 +230,38 @@
col = columns.find {|c| c.name == name.to_s} rescue nil
col.nil? || col.null
end
- def conditions(&b)
- ModelQueries.new(self).instance_eval(&b).to_sql
+ def conditions(*args, &b)
+ if args.empty?
+ ModelQueries.new(self).instance_eval(&b).to_sql
+ else
+ ModelQueries.new(self).instance_exec(*args, &b).to_sql
+ end
end
+
-
def find(*args, &b)
- if args.first.in?([:all, :first])
- if args.last.is_a? Hash
- options = args.last
- args[-1] = options = options.merge(:order => default_order) if options[:order] == :default
- else
- options = {}
- end
+ options = args.extract_options!
+ if args.first.in?([:all, :first]) && options[:order] == :default
+ options = if default_order.blank?
+ options - [:order]
+ else
+ options.merge(:order => "#{table_name}.#{default_order}")
+ end
+ end
- if b
- super(args.first, options.merge(:conditions => conditions(&b)))
- else
- super(*args)
- end
+ if b && !(block_conditions = conditions(&b)).blank?
+ c = if !options[:conditions].blank?
+ "(#{options[:conditons]}) and (#{block_conditions})"
+ else
+ block_conditions
+ end
+ super(args.first, options.merge(:conditions => c))
else
- super(*args)
+ super(*args + [options])
end
end
def count(*args, &b)
@@ -269,12 +283,12 @@
options[:source] = refl.source_reflection.name if refl.source_reflection
has_many(assoc, refl.options.merge(options))
end
end
- def has_creator?
- instance_methods.include?('creator=') and instance_methods.include?('creator')
+ def creator_type
+ reflections[@creator_attr]._?.klass
end
def search_columns
cols = columns.every(:name)
%w{name title body content}.select{|c| c.in?(cols) }
@@ -364,40 +378,44 @@
end
if find_scope
# Calling instance_variable_get directly causes self to
# get loaded, hence this trick
- assoc = Kernel.instance_method(:instance_variable_get).bind(self).call("@#{name}")
+ assoc = Kernel.instance_method(:instance_variable_get).bind(self).call("@#{name}_scope")
unless assoc
options = proxy_reflection.options
has_many_conditions = options.has_key?(:conditions)
- scope_conditions = find_scope.delete(:conditions)
+ source = proxy_reflection.source_reflection
+ scope_conditions = find_scope[:conditions]
conditions = if has_many_conditions && scope_conditions
"(#{scope_conditions}) AND (#{has_many_conditions})"
else
scope_conditions || has_many_conditions
end
options = options.merge(find_scope).update(:conditions => conditions,
- :class_name => proxy_reflection.klass.name,
- :foreign_key => proxy_reflection.primary_key_name)
+ :class_name => proxy_reflection.klass.name,
+ :foreign_key => proxy_reflection.primary_key_name)
+ options[:source] = source.name if source
+
r = ActiveRecord::Reflection::AssociationReflection.new(:has_many,
name,
options,
- proxy_reflection.klass)
+ proxy_owner.class)
+
@reflections ||= {}
@reflections[name] = r
- assoc = if options.has_key?(:through)
+ assoc = if source
ActiveRecord::Associations::HasManyThroughAssociation
else
ActiveRecord::Associations::HasManyAssociation
end.new(self.proxy_owner, r)
-
+
# Calling directly causes self to get loaded
- Kernel.instance_method(:instance_variable_set).bind(self).call("@#{name}", assoc)
+ Kernel.instance_method(:instance_variable_set).bind(self).call("@#{name}_scope", assoc)
end
assoc
else
super
end
@@ -405,11 +423,11 @@
end
def has_many_with_defined_scopes(name, *args, &block)
- options = extract_options_from_args!(args)
+ options = args.extract_options!
if options.has_key?(:extend) || block
# Normal has_many
has_many_without_defined_scopes(name, *args + [options], &block)
else
options[:extend] = DefinedScopeProxyExtender
@@ -418,10 +436,10 @@
end
end
def set_creator(user)
- self.creator ||= user if self.class.has_creator? and not user.guest?
+ self.send("#{self.class.creator_attr}=", user) if (t = self.class.creator_type) && user.is_a?(t)
end
def duplicate
res = self.class.new