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