diff --git a/lib/rbs_rails/cli.rb b/lib/rbs_rails/cli.rb index 952ae72..b0d2bbd 100644 --- a/lib/rbs_rails/cli.rb +++ b/lib/rbs_rails/cli.rb @@ -126,7 +126,7 @@ def generate_single_model(klass, dep_builder) #: bool path.dirname.mkpath sig = RbsRails::ActiveRecord.class_to_rbs(klass, dependencies: dep_builder.deps) - path.write sig + Util::FileWriter.new(path).write sig dep_builder.done << klass.name true @@ -137,7 +137,7 @@ def generate_path_helpers #: void path.dirname.mkpath sig = RbsRails::PathHelpers.generate - path.write sig + Util::FileWriter.new(path).write sig end def create_option_parser #: OptionParser diff --git a/lib/rbs_rails/util.rb b/lib/rbs_rails/util.rb index b6b6509..24979c7 100644 --- a/lib/rbs_rails/util.rb +++ b/lib/rbs_rails/util.rb @@ -1,3 +1,5 @@ +require_relative 'util/file_writer' + module RbsRails module Util MODULE_NAME = Module.instance_method(:name) #: UnboundMethod diff --git a/lib/rbs_rails/util/file_writer.rb b/lib/rbs_rails/util/file_writer.rb new file mode 100644 index 0000000..e6e3c4a --- /dev/null +++ b/lib/rbs_rails/util/file_writer.rb @@ -0,0 +1,22 @@ +module RbsRails + module Util + # To avoid unnecessary type reloading by type checkers and other utilities, + # FileWriter modifies the target file only if its content has been changed. + class FileWriter + attr_reader :path #: Pathname + + # @rbs path: Pathname + def initialize(path) #: void + @path = path + end + + def write(content) #: void + original_content = path.read rescue nil + + if original_content != content + path.write(content) + end + end + end + end +end diff --git a/sig/rbs_rails/util/file_writer.rbs b/sig/rbs_rails/util/file_writer.rbs new file mode 100644 index 0000000..89bf12a --- /dev/null +++ b/sig/rbs_rails/util/file_writer.rbs @@ -0,0 +1,16 @@ +# Generated from lib/rbs_rails/util/file_writer.rb with RBS::Inline + +module RbsRails + module Util + # To avoid unnecessary type reloading by type checkers and other utilities, + # FileWriter modifies the target file only if its content has been changed. + class FileWriter + attr_reader path: Pathname + + # @rbs path: Pathname + def initialize: (Pathname path) -> void + + def write: (untyped content) -> void + end + end +end diff --git a/sig/rbs_rails/utils/file_writer.rbs b/sig/rbs_rails/utils/file_writer.rbs new file mode 100644 index 0000000..0a3ce7d --- /dev/null +++ b/sig/rbs_rails/utils/file_writer.rbs @@ -0,0 +1,4 @@ +# Generated from lib/rbs_rails/utils/file_writer.rb with RBS::Inline + +module RbsRails +end diff --git a/test/rbs_rails/util/file_writer_test.rb b/test/rbs_rails/util/file_writer_test.rb new file mode 100644 index 0000000..4c52363 --- /dev/null +++ b/test/rbs_rails/util/file_writer_test.rb @@ -0,0 +1,49 @@ +require 'test_helper' +require 'tmpdir' +require_relative '../../../lib/rbs_rails/util/file_writer' + +class FileWriterTest < Minitest::Test + def setup + @temp_dir = Pathname.new(Dir.mktmpdir('file_writer_test')) + end + + def teardown + FileUtils.rm_rf(@temp_dir) if @temp_dir + end + + def test_write_on_file_not_found + file_path = @temp_dir / 'non_existent_file.rbs' + file_writer = RbsRails::Util::FileWriter.new(file_path) + + file_writer.write("content") + + assert file_path.exist? + assert_equal "content", file_path.read + end + + def test_write_on_changed + file_path = @temp_dir / 'test_file.rbs' + file_path.write("old content") + + file_writer = RbsRails::Util::FileWriter.new(file_path) + + file_writer.write("new content") + + assert_equal "new content", file_path.read + end + + def test_write_on_not_changed + content = "unchanged content" + mtime = Time.now - 10 + + file_path = @temp_dir / 'test_file.rbs' + file_path.write(content) + file_path.utime(mtime, mtime) + + file_writer = RbsRails::Util::FileWriter.new(file_path) + file_writer.write(content) + + assert_equal content, file_path.read + assert_equal mtime, file_path.mtime + end +end