<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/caring/utilities/url_utils.rb</filename>
    </added>
    <added>
      <filename>test/debug.log</filename>
    </added>
    <added>
      <filename>test/fixtures/from_method_item.rb</filename>
    </added>
    <added>
      <filename>test/fixtures/scoped_item.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -2,5 +2,5 @@
 require &quot;metaid&quot;
 require &quot;acts_as_url_param&quot;
 require &quot;redirect&quot;
-require &quot;url_utils&quot;
+require &quot;caring/utilities/url_utils&quot;
 ActiveRecord::Base.send(:include, ActsAsUrlParam)
\ No newline at end of file</diff>
      <filename>init.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,6 +6,7 @@ module ActsAsUrlParam
   module ActMethods
     
     def acts_as_url_param(*args, &amp;block)
+      return unless table_exists?
       extend ClassMethods
       include InstanceMethods
       include Caring::Utilities::UrlUtils
@@ -45,12 +46,12 @@ module ActsAsUrlParam
     private
     
     def make_redirectable
-      has_many :redirects, :as =&gt; :redirectable
+      has_many :redirects, :as =&gt; :redirectable, :dependent =&gt; :destroy
       before_save :add_redirect
       
       class_def :add_redirect do
-        if !new_record? &amp;&amp; @name_changed &amp;&amp; @old_name
-          redirects.create(:url_name =&gt; @old_name)
+        if !new_record? &amp;&amp; url_to_field_changed?
+          redirects.create(:url_name =&gt; url_to_field_was) unless url_to_field_was.blank?
         end
       end
       
@@ -64,32 +65,43 @@ module ActsAsUrlParam
       meta_def :find_by_url do |*args|
         send(&quot;find_by_#{acts_as_url_options[:column]}&quot;, *args)
       end
+      send(:named_scope, &quot;with_url&quot;, lambda{|url|
+        {:conditions =&gt; [&quot;#{acts_as_url_options[:column]} = ?&quot;, url]}
+      })
     end
     
     def define_url_param_setter
       class_def &quot;#{acts_as_url_options[:column]}=&quot; do |value|
-        @url_name_manually_set = true if value
-        @old_name = read_attribute(acts_as_url_options[:column]) unless @name_changed
-        write_attribute(acts_as_url_options[:column], url_safe(value))
-        @name_changed = true unless read_attribute(acts_as_url_options[:column]) == @old_name || !@old_name
+        super url_safe(value)
+        # @url_name_manually_set = true if value
+        # @old_name = read_attribute(acts_as_url_options[:column]) unless @name_changed
+        # write_attribute(acts_as_url_options[:column], url_safe(value))
+        # @name_changed = true unless read_attribute(acts_as_url_options[:column]) == @old_name || !@old_name
       end
     end
     
     def define_availability_check
       klass = self
       meta_def :url_param_available_for_model? do |*args|
-        candidate, id = *args
-        conditions = acts_as_url_options[:conditions] + ' AND ' if acts_as_url_options[:conditions]
+        candidate, record = *args
+        id = record &amp;&amp; !record.new_record? &amp;&amp; record.id
+        if acts_as_url_options[:scope]
+          base = record || self
+          conditions = base.send(:instance_eval, &quot;\&quot;#{acts_as_url_options[:scope]}\&quot;&quot;) + ' AND '
+        end
         conditions ||= '' 
         conditions += &quot;#{acts_as_url_options[:column]} = ?&quot;
         conditions += &quot; AND id != ?&quot; if id
+        conditions += &quot; AND type = ? &quot; if acts_as_url_options[:scope] == :type
         conditions = [conditions, candidate]
         conditions &lt;&lt; id if id
+        conditions &lt;&lt; self.to_s if acts_as_url_options[:scope] == :type
         available = if descends_from_active_record? or self == klass
           count(:conditions =&gt; conditions) == 0
         else
           base_class.count(:conditions =&gt; conditions) == 0
         end
+        logger.debug(&quot;conditions are #{conditions.inspect}&quot;)
         if acts_as_url_options[:redirectable] &amp;&amp; available
           re_conditions = &quot;url_name = ? AND redirectable_class = ?&quot;
           re_conditions += &quot;AND redirectable_id != ?&quot; if id
@@ -112,18 +124,24 @@ module ActsAsUrlParam
     end
     
     module ClassMethods
-      def url_param_available?(candidate, id=nil)
-        if proc = acts_as_url_options[:block]
-          !(proc.arity == 1 ? proc.call(candidate) : proc.call(candidate, id))
-        else
-          url_param_available_for_model?(candidate, id)
+      def url_param_available?(candidate, record=nil)
+        Caring::Scope::State.instance.with_admin_scope(true) do
+          if proc = acts_as_url_options[:block]
+            if proc.arity == 1
+              proc.call(candidate)
+            else 
+              proc.call(candidate, record)
+            end
+          else
+            url_param_available_for_model?(candidate, record)
+          end
         end
       end
       
-      def compute_url_param(candidate, id=nil)
+      def compute_url_param(candidate, record=nil)
         return if candidate.blank?
         # raise ArgumentError, &quot;The url canidate cannot be empty&quot; if candidate.blank?
-        uniquify_proc = acts_as_url_options[:block] || Proc.new { |candidate| url_param_available? candidate, id }
+        uniquify_proc = acts_as_url_options[:block] || Proc.new { |candidate| url_param_available? candidate, record }
         uniquify(url_safe(candidate), &amp;uniquify_proc)
       end
     end
@@ -131,11 +149,11 @@ module ActsAsUrlParam
     module InstanceMethods
       def compute_url_param
         # raise ArgumentError, &quot;The column used for generating the url_param is empty&quot; unless url_from
-        self.class.compute_url_param(url_from, id)
+        self.class.compute_url_param(url_from, self)
       end
       
       def url_from
-        self.class.method_defined?(acts_as_url_options[:from]) ? send(acts_as_url_options[:from]) : read_attribute(acts_as_url_options[:from])
+        url_from_method? ? send(acts_as_url_options[:from]) : read_attribute(acts_as_url_options[:from])
       end
       
       def to_param
@@ -146,11 +164,34 @@ module ActsAsUrlParam
         read_attribute(acts_as_url_options[:column])
       end
       
+      private
+      
       def empty_param?
         !url_param
       end
       
-      private
+      def update_url?
+        url_to_field_changed? &amp;&amp; !url_from_field_changed?
+      end
+
+      def url_to_field_changed?
+        send(&quot;#{acts_as_url_options[:column]}_changed?&quot;)
+      rescue NoMethodError
+      end
+
+      def url_to_field_was
+        send(&quot;#{acts_as_url_options[:column]}_was&quot;)
+      end
+
+      def url_from_field_changed?
+        send(&quot;#{acts_as_url_options[:from]}_changed?&quot;)
+      rescue NoMethodError
+        true
+      end
+      
+      def url_from_method?
+        self.class.method_defined?(acts_as_url_options[:from])
+      end
       
       def set_url_param_if_non_existant
         unless new_record?
@@ -158,20 +199,27 @@ module ActsAsUrlParam
         end
       end
       
+      def set_url_param?
+        url_param.blank? or
+          (url_from_field_changed? &amp;&amp; 
+          acts_as_url_options[:on] != :create &amp;&amp; 
+          !url_to_field_changed?)
+      end
+      
       def set_url_param
-        if url_param.blank? or (acts_as_url_options[:on] != :create &amp;&amp; !@url_name_manually_set)
+        if set_url_param?
           send(acts_as_url_options[:before]) if acts_as_url_options[:before]
           url = compute_url_param
           send(&quot;#{acts_as_url_options[:column]}=&quot;, url) unless url.blank?
-          @url_name_manually_set = false
           @url_param_validated = true
         end
       end
       
       def validate_with_unique_url
-        return true if @url_param_validated
-        avail_id = new_record? ? nil : id
-        unless self.class.url_param_available? to_param, avail_id
+        if @url_param_validated or (!new_record? &amp;&amp; !url_to_field_changed? &amp;&amp; !url_from_field_changed?)
+          return true 
+        end
+        unless self.class.url_param_available? to_param, self
           errors.add_to_base &quot;The url is not unique&quot;
         end
         validate_without_unique_url</diff>
      <filename>lib/acts_as_url_param.rb</filename>
    </modified>
    <modified>
      <diff>@@ -7,6 +7,8 @@ class Redirect &lt; ActiveRecord::Base
   belongs_to :redirectable, :polymorphic =&gt; true
   before_create :set_real_class
   
+  validates_presence_of :url_name
+  
   def self.find_by_class_and_name(klass,name)
     find(:first, :conditions =&gt; [&quot;redirectable_class = ? AND url_name = ?&quot;, klass.to_s, name], :order =&gt; &quot;created_at desc&quot;)
   end</diff>
      <filename>lib/redirect.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,6 +11,8 @@ require &quot;newspaper&quot;
 require &quot;user&quot;
 require &quot;story&quot;
 require &quot;before_item&quot;
+require &quot;scoped_item&quot;
+require &quot;from_method_item&quot;
 
 class ActsAsUrlParamTest &lt; Test::Unit::TestCase
   
@@ -66,8 +68,8 @@ class ActsAsUrlParamTest &lt; Test::Unit::TestCase
   end
   
   def test_should_use_block_to_check_if_url_param_available
-    ActsAsUrlParam::Story.create(:title =&gt; 'new post')
-    assert !ActsAsUrlParam::BlogPost.url_param_available?('new post')
+    ActsAsUrlParam::Story.create!(:title =&gt; 'new post')
+    assert !ActsAsUrlParam::BlogPost.url_param_available?('new-post')
   end
   
   def test_should_use_block_to_compute_url_name
@@ -186,6 +188,27 @@ class ActsAsUrlParamTest &lt; Test::Unit::TestCase
     assert_match /is-set/, item.to_param
   end
   
+  def test_should_use_scope
+    one = ActsAsUrlParam::ScopedItem.create(:name =&gt; 'scoper', :scope_by_id =&gt; 23)
+    two = ActsAsUrlParam::ScopedItem.create(:name =&gt; 'scoper', :scope_by_id =&gt; 24)
+    three = ActsAsUrlParam::ScopedItem.create(:name =&gt; 'scoper', :scope_by_id =&gt; 24)
+    assert_equal one.url_name, two.url_name
+    assert one.url_name != three.url_name
+  end
+  
+  def test_should_keep_first_url_on_double_save
+    item = ActsAsUrlParam::Item.create(:name =&gt; 'boring', :url_name =&gt; 'exciting')
+    assert_equal item.to_param, 'exciting'
+    item.content = 'drivel'
+    item.save
+    assert_equal item.to_param, 'exciting'
+  end
+  
+  def test_with_url_from_method
+    i = ActsAsUrlParam::FromMethodItem.create
+    assert_equal i.to_param, i.my_method
+  end
+  
   private  
   def acts_as_url_name_model(column = nil, options = {})
     m = Class.new(ActiveRecord::Base)</diff>
      <filename>test/acts_as_url_param_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,3 @@
 class ActsAsUrlParam::Item &lt; ActsAsUrlParamBase
-  acts_as_url_param :conditions =&gt; &quot;items.type != 'Newspaper'&quot;, :redirectable =&gt; true
+  acts_as_url_param :scope =&gt; &quot;items.type != 'Newspaper'&quot;, :redirectable =&gt; true
 end
\ No newline at end of file</diff>
      <filename>test/fixtures/item.rb</filename>
    </modified>
    <modified>
      <diff>@@ -14,6 +14,7 @@ ActiveRecord::Schema.define() do
     t.column :name, :string
     t.column :content, :string
     t.column :type, :string, :default =&gt; 'Item', :null =&gt; false
+    t.column :scope_by_id, :integer
     t.column :url_name, :string
   end
   </diff>
      <filename>test/schema.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,6 +4,7 @@
 require 'test/unit'
 rails_env = File.expand_path(File.join(File.dirname(__FILE__), '../../../../config/environment.rb'))
 if File.exist? rails_env
+  ENV[&quot;RAILS_ENV&quot;] = &quot;test&quot;
   require rails_env
   require 'active_record/fixtures'
 else</diff>
      <filename>test/test_helper.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>f57fc17722bbc9a358a710ebde9fcfa1e69119d8</id>
    </parent>
  </parents>
  <author>
    <name>Chris Eppstein</name>
    <email>chris@eppsteins.net</email>
  </author>
  <url>http://github.com/caring/acts_as_url_param/commit/6713a8d9f0e03014faad79ae82cc1c67bc5d2a52</url>
  <id>6713a8d9f0e03014faad79ae82cc1c67bc5d2a52</id>
  <committed-date>2009-08-03T14:51:22-07:00</committed-date>
  <authored-date>2009-08-03T14:51:22-07:00</authored-date>
  <message>Update to the latest production code.</message>
  <tree>d83dcb23247d1aa40f367a6f90b4f8387e3cb2e9</tree>
  <committer>
    <name>Chris Eppstein</name>
    <email>chris@eppsteins.net</email>
  </committer>
</commit>
