Issue #1760 has been updated by Yusuke Endoh.


Hi,

> Methods that expect paths usually call #to_path on their argument. They may also try #to_str. When an argument responds to both of these methods, I suggest that #to_path is preferred as it is the more specific, thus more likely to be correct.


Seems reasonable.

I'll apply the patch unless anyone expresses opposition.


diff --git a/file.c b/file.c
index 36b0b06..9b5d380 100644
--- a/file.c
+++ b/file.c
@@ -140,16 +140,16 @@ rb_get_path_check(VALUE obj, int level)
     if (insecure_obj_p(obj, level)) {
        rb_insecure_operation();
     }
-    tmp = rb_check_string_type(obj);
-    if (!NIL_P(tmp)) goto exit;

     CONST_ID(to_path, "to_path");
-    if (rb_respond_to(obj, to_path)) {
+    if (!rb_special_const_p(obj) && RBASIC(obj)->klass != 0 && rb_respond_to(obj, to_path)) {
        tmp = rb_funcall(obj, to_path, 0, 0);
     }
     else {
        tmp = obj;
     }
+    tmp = rb_check_string_type(tmp);
+    if (!NIL_P(tmp)) goto exit;
     StringValue(tmp);
   exit:
     tmp = file_path_convert(tmp);


A patch for rubyspec:

diff --git a/core/dir/chdir_spec.rb b/core/dir/chdir_spec.rb
index ec82759..068833d 100644
--- a/core/dir/chdir_spec.rb
+++ b/core/dir/chdir_spec.rb
@@ -56,10 +56,10 @@ describe "Dir.chdir" do
       Dir.chdir(obj)
     end

-    it "prefers #to_str over #to_path" do
+    it "prefers #to_path over #to_str" do
       obj = Class.new do
-        def to_path; DirSpecs.mock_dir; end
-        def to_str;  Dir.pwd; end
+        def to_path; Dir.pwd; end
+        def to_str;  DirSpecs.mock_dir; end
       end
       Dir.chdir(obj.new)
       Dir.pwd.should == @original
diff --git a/core/kernel/shared/require.rb b/core/kernel/shared/require.rb
index 1b35fd4..956fa72 100644
--- a/core/kernel/shared/require.rb
+++ b/core/kernel/shared/require.rb
@@ -108,10 +108,11 @@ describe :kernel_require_basic, :shared => true do
         ScratchPad.recorded.should == [:loaded]
       end

-      it "does not call #to_path on a String" do
+      it "calls #to_path on a String" do
         path = File.expand_path "load_fixture.rb", CODE_LOADING_DIR
-        path.should_not_receive(:to_path)
-        @object.send(@method, path).should be_true
+        str = mock("load_fixture.rb mock")
+        str.should_receive(:to_path).and_return(path)
+        @object.send(@method, str).should be_true
         ScratchPad.recorded.should == [:loaded]
       end

-- 
Yusuke ENDOH <mame / tsg.ne.jp>
----------------------------------------
http://redmine.ruby-lang.org/issues/show/1760

----------------------------------------
http://redmine.ruby-lang.org