Module: ReactOnRails::Utils

Defined in:
lib/react_on_rails/utils.rb

Defined Under Namespace

Modules: Required

Constant Summary collapse

TRUNCATION_FILLER =
"\n... TRUNCATED ...\n"

Class Method Summary collapse

Class Method Details

.bundle_js_file_path(bundle_name) ⇒ Object



96
97
98
99
100
101
102
103
104
105
# File 'lib/react_on_rails/utils.rb', line 96

def self.bundle_js_file_path(bundle_name)
  if ReactOnRails::WebpackerUtils.using_webpacker? && bundle_name != "manifest.json"
    ReactOnRails::WebpackerUtils.bundle_js_uri_from_webpacker(bundle_name)
  else
    # Default to the non-hashed name in the specified output directory, which, for legacy
    # React on Rails, this is the output directory picked up by the asset pipeline.
    # For Webpacker, this is the public output path defined in the webpacker.yml file.
    File.join(generated_assets_full_path, bundle_name)
  end
end

.find_most_recent_mtime(files) ⇒ Object



195
196
197
198
199
200
# File 'lib/react_on_rails/utils.rb', line 195

def self.find_most_recent_mtime(files)
  files.reduce(1.year.ago) do |newest_time, file|
    mt = File.mtime(file)
    [mt, newest_time].max
  end
end

.gem_available?(name) ⇒ Boolean

Returns:

  • (Boolean)


154
155
156
157
158
159
160
# File 'lib/react_on_rails/utils.rb', line 154

def self.gem_available?(name)
  Gem.loaded_specs[name].present?
rescue Gem::LoadError
  false
rescue StandardError
  Gem.available?(name).present?
end

.generated_assets_full_pathObject



146
147
148
149
150
151
152
# File 'lib/react_on_rails/utils.rb', line 146

def self.generated_assets_full_path
  if ReactOnRails::WebpackerUtils.using_webpacker?
    ReactOnRails::WebpackerUtils.webpacker_public_output_path
  else
    File.expand_path(ReactOnRails.configuration.generated_assets_dir)
  end
end

.invoke_and_exit_if_failed(cmd, failure_message) ⇒ Object

Invokes command, exiting with a detailed message if there’s a failure.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/react_on_rails/utils.rb', line 45

def self.invoke_and_exit_if_failed(cmd, failure_message)
  stdout, stderr, status = Open3.capture3(cmd)
  unless status.success?
    stdout_msg = stdout.present? ? "\nstdout:\n#{stdout.strip}\n" : ""
    stderr_msg = stderr.present? ? "\nstderr:\n#{stderr.strip}\n" : ""
    msg = <<~MSG
      React on Rails FATAL ERROR!
      #{failure_message}
      cmd: #{cmd}
      exitstatus: #{status.exitstatus}#{stdout_msg}#{stderr_msg}
    MSG

    puts wrap_message(msg)

    # Rspec catches exit without! in the exit callbacks
    exit!(1)
  end
  [stdout, stderr, status]
end

.object_to_boolean(value) ⇒ Object



36
37
38
# File 'lib/react_on_rails/utils.rb', line 36

def self.object_to_boolean(value)
  [true, "true", "yes", 1, "1", "t"].include?(value.instance_of?(String) ? value.downcase : value)
end

.prepend_cd_node_modules_directory(cmd) ⇒ Object



127
128
129
# File 'lib/react_on_rails/utils.rb', line 127

def self.prepend_cd_node_modules_directory(cmd)
  "cd \"#{ReactOnRails.configuration.node_modules_location}\" && #{cmd}"
end

.prepend_to_file_if_text_not_present(file:, text_to_prepend:, regex:) ⇒ Object



202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/react_on_rails/utils.rb', line 202

def self.prepend_to_file_if_text_not_present(file:, text_to_prepend:, regex:)
  if File.exist?(file)
    file_content = File.read(file)

    return if file_content.match(regex)

    content_with_prepended_text = text_to_prepend + file_content
    File.write(file, content_with_prepended_text, mode: "w")
  else
    File.write(file, text_to_prepend, mode: "w+")
  end

  puts "Prepended\n#{text_to_prepend}to #{file}."
end

.rails_version_less_than(version) ⇒ Object



111
112
113
114
115
116
117
118
119
# File 'lib/react_on_rails/utils.rb', line 111

def self.rails_version_less_than(version)
  @rails_version_less_than ||= {}

  return @rails_version_less_than[version] if @rails_version_less_than.key?(version)

  @rails_version_less_than[version] = begin
    Gem::Version.new(Rails.version) < Gem::Version.new(version)
  end
end

.react_on_rails_pro?Boolean

Todo – remove this for v13, as we don’t need both boolean and number

Returns:

  • (Boolean)


163
164
165
166
167
# File 'lib/react_on_rails/utils.rb', line 163

def self.react_on_rails_pro?
  return @react_on_rails_pro if defined?(@react_on_rails_pro)

  @react_on_rails_pro = gem_available?("react_on_rails_pro")
end

.react_on_rails_pro_versionObject

Return an empty string if React on Rails Pro is not installed



170
171
172
173
174
175
176
177
178
# File 'lib/react_on_rails/utils.rb', line 170

def self.react_on_rails_pro_version
  return @react_on_rails_pro_version if defined?(@react_on_rails_pro_version)

  @react_on_rails_pro_version = if react_on_rails_pro?
                                  Gem.loaded_specs["react_on_rails_pro"].version.to_s
                                else
                                  ""
                                end
end

.running_on_windows?Boolean

Returns:

  • (Boolean)


107
108
109
# File 'lib/react_on_rails/utils.rb', line 107

def self.running_on_windows?
  (/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
end

.server_bundle_js_file_pathObject



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/react_on_rails/utils.rb', line 69

def self.server_bundle_js_file_path
  # Either:
  # 1. Using same bundle for both server and client, so server bundle will be hashed in manifest
  # 2. Using a different bundle (different Webpack config), so file is not hashed, and
  #    bundle_js_path will throw so the default path is used without a hash.
  # 3. The third option of having the server bundle hashed and a different configuration than
  #    the client bundle is not supported for 2 reasons:
  #    a. The webpack manifest plugin would have a race condition where the same manifest.json
  #       is edited by both the webpack-dev-server
  #    b. There is no good reason to hash the server bundle name.
  return @server_bundle_path if @server_bundle_path && !Rails.env.development?

  bundle_name = ReactOnRails.configuration.server_bundle_js_file
  @server_bundle_path = if ReactOnRails::WebpackerUtils.using_webpacker?
                          begin
                            bundle_js_file_path(bundle_name)
                          rescue Webpacker::Manifest::MissingEntryError
                            File.expand_path(
                              File.join(ReactOnRails::WebpackerUtils.webpacker_public_output_path,
                                        bundle_name)
                            )
                          end
                        else
                          bundle_js_file_path(bundle_name)
                        end
end

.server_bundle_path_is_http?Boolean

Returns:

  • (Boolean)


65
66
67
# File 'lib/react_on_rails/utils.rb', line 65

def self.server_bundle_path_is_http?
  server_bundle_js_file_path =~ %r{https?://}
end

.server_rendering_is_enabled?Boolean

Returns:

  • (Boolean)


40
41
42
# File 'lib/react_on_rails/utils.rb', line 40

def self.server_rendering_is_enabled?
  ReactOnRails.configuration.server_bundle_js_file.present?
end

.smart_trim(str, max_length = 1000) ⇒ Object



180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/react_on_rails/utils.rb', line 180

def self.smart_trim(str, max_length = 1000)
  # From https://stackoverflow.com/a/831583/1009332
  str = str.to_s
  return str unless str.present? && max_length >= 1
  return str if str.length <= max_length

  return str[0, 1] + TRUNCATION_FILLER if max_length == 1

  midpoint = (str.length / 2.0).ceil
  to_remove = str.length - max_length
  lstrip = (to_remove / 2.0).ceil
  rstrip = to_remove - lstrip
  str[0..(midpoint - lstrip - 1)] + TRUNCATION_FILLER + str[(midpoint + rstrip)..]
end

.source_pathObject



131
132
133
134
135
136
137
# File 'lib/react_on_rails/utils.rb', line 131

def self.source_path
  if ReactOnRails::WebpackerUtils.using_webpacker?
    ReactOnRails::WebpackerUtils.webpacker_source_path
  else
    ReactOnRails.configuration.node_modules_location
  end
end

.truthy_presence(obj) ⇒ Object



15
16
17
18
19
20
21
# File 'lib/react_on_rails/utils.rb', line 15

def self.truthy_presence(obj)
  if obj.nil? || obj == false
    nil
  else
    obj
  end
end

.using_webpacker_source_path_is_not_defined_and_custom_node_modules?Boolean

Returns:

  • (Boolean)


139
140
141
142
143
144
# File 'lib/react_on_rails/utils.rb', line 139

def self.using_webpacker_source_path_is_not_defined_and_custom_node_modules?
  return false unless ReactOnRails::WebpackerUtils.using_webpacker?

  !ReactOnRails::WebpackerUtils.webpacker_source_path_explicit? &&
    ReactOnRails.configuration.node_modules_location.present?
end

.wrap_message(msg, color = :red) ⇒ Object

Wraps message and makes it colored. Pass in the msg and color as a symbol.



25
26
27
28
29
30
31
32
33
34
# File 'lib/react_on_rails/utils.rb', line 25

def self.wrap_message(msg, color = :red)
  wrapper_line = ("=" * 80).to_s
  fenced_msg = <<~MSG
    #{wrapper_line}
    #{msg.strip}
    #{wrapper_line}
  MSG

  Rainbow(fenced_msg).color(color)
end