ハイパーニートプログラマーへの道

頑張ったり頑張らなかったり

【Ruby on Rails】dyld: lazy symbol binding failed: Symbol not found: というエラーが出たので

bin/rake spec を走らせた時に以下のようなエラーが出るようになりました

$ ./bin/rake spec

dyld: lazy symbol binding failed: Symbol not found: __ZN2v82V821AddGCPrologueCallbackEPFvNS_6GCTypeENS_15GCCallbackFlagsEES1_
  Referenced from: /Users/noriyo_tcp/workspace/some-project/vendor/bundle/ruby/2.2.0/extensions/x86_64-darwin-17/2.2.0-static/therubyracer-0.12.1/v8/init.bundle
  Expected in: flat namespace

dyld: Symbol not found: __ZN2v82V821AddGCPrologueCallbackEPFvNS_6GCTypeENS_15GCCallbackFlagsEES1_
  Referenced from: /Users/noriyo_tcp/workspace/some-project/vendor/bundle/ruby/2.2.0/extensions/x86_64-darwin-17/2.2.0-static/therubyracer-0.12.1/v8/init.bundle
  Expected in: flat namespace

therubyracer, libv8, v8 の再インストール

github.com

この記事では therubyracer, libv8, v8 の再インストールを行なっているが、今回の場合

.bundle/config で以下のような設定にしているので、実際にはlibv8 のアンインストールと再インストールはしませんでした

# v8@3.15 をbrew でインストールしてあり、オプションでそちらを見に行くように設定
BUNDLE_BUILD__LIBV8: "--with-system-v8"
BUNDLE_BUILD__THERUBYRACER: "--with-v8-dir=/usr/local/opt/v8@3.15"
$ bundle exec gem uninstall therubyracer
$ brew reinstall v8@3.15
$ bundle

ちなみに therubyracer のアンインストール時に undefined method `delete' for #<Bundler::SpecSet:0x007f8613c354b0>

って出るけど大丈夫っぽい http://smellman.hatenablog.com/entry/20121025/1351162613


しかしこれでもダメだった・・・。その他MacOSrootless を切ってみるなどしたが、うまく行きませんでしたorz

結局therubyracer をアップデート(0.12.1 -> 0.12.3)

$ bundle update therubyracer

【Rails】ファイルアップロードのテスト時のFactoryGirl (FactoryBot) の設定

このようにしていまして

FactoryGirl.define do
  # 中略
  factory :content_figure do
      content do
        ActionDispatch::Http::UploadedFile.new(
          filename: 'figure.png',
          type: 'image/png',
          tempfile: File.open(Rails.root.join('spec', 'files', 'figure.png'))
        )
      end
    end
  end
end

こんな感じで ActionDispatch::Http:UploadedFile.new するのもいいんですが、 fixture_upload_path を使うのもアリかと

include ActionDispatch::TestProcess

FactoryGirl.define do
  factory :content_figure do
      content { fixture_file_upload(Rails.root.join('spec', 'files', 'figure.png'), 'png'), 'image/png' }
  end
end

しかしActionDispatch::TestProcess をインクルードするのを忘れると困ります
この記事のコメントによるとfixture_file_upload はほとんど何もやっていないそうなので、Rack::Test::UploadedFile.newを直接呼んでしまってもいいらしい

content { Rack::Test::UploadedFile.new(Rails.root.join('spec', 'files', 'figure.png'), 'png'), 'image/png' }

fixture_file_upload は呼び出し元のクラスがfixture_path を持っていれば自動的にspec/fixtures までのパスを追加してくれますが、 FactoryGirl からでは参照してくれないので、別途fixture_path の設定が必要になります

今回はspec/files 配下にイメージを置いてしまっていますし、別途fixture_path を設定するのも面倒なので、このように直接パス指定する形でいいかと

tanihiro.hatenablog.com

qiita.com

こちらの記事のコメントでは、FactoryGirl からパスを参照させるためにfixture_path を設定していたり

qiita.com

【Rails】ファイルアップロードのテストにてMiniMagickのValidationがfailedするとき

RSpec + FactoryGirl (FactoryBot) でファイルアップロードが絡むテストを走らせたときに、以下のようなエラーに遭遇

Validation failed: Figures content Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: MiniMagick::Invalid

factory のほうはこんな感じ

FactoryGirl.define do
  factory :figure do
    # 中略
    factory :content_figure do
      content do
        ActionDispatch::Http::UploadedFile.new(
          filename: 'figure.png',
          type: 'image/png',
          tempfile: File.open(Rails.root.join('spec', 'files', 'figure.png'))
        )
      end
    end
  end
end

うーん、CarrierWave::MiniMagick をインクルードしているアップローダでも extension_white_listpng は入ってる

  def extension_white_list
    %w(jpg jpeg gif png)
  end

convert -list configureDELEGATES の部分を見てみる

$ convert -list configure
DELEGATES      bzlib mpeg freetype jng jpeg lzma png tiff xml zlib

んな〜、png は入っているようですぞ?

brew upgrade でimagemagick の更新

$ brew doctor

arning: You have unlinked kegs in your Cellar
Leaving kegs unlinked can lead to build-trouble and cause brews that depend on
those kegs to fail to run properly once built. Run `brew link` on these:
  imagemagick

Warning: Some keg-only formula are linked into the Cellar.
Linking a keg-only formula, such as gettext, into the cellar with
`brew link <formula>` will cause other formulae to detect them during
the `./configure` step. This may cause problems when compiling those
other formulae.

Binaries provided by keg-only formulae may override system binaries
with other strange results.

You may wish to `brew unlink` these brews:
  imagemagick@6

あー、imagemagick@6 系にリンクしてたのが悪いのかなあ

$ brew unlink imagemagick@6
$ brew link imagemagick
$ identify spec/files/figure.png 
identify: unable to load module '/usr/local/Cellar/imagemagick/7.0.5-0/lib/ImageMagick//modules-Q16HDRI/coders/png.la': file not found @ error/module.c/OpenModule/1279.

でもまだidentifyでこけますぞ

$ brew upgrade imagemagick
$ identify spec/files/figure.png 
spec/files/figure.png PNG 64x64 64x64+0+0 8-bit sRGB 155B 0.000u 0:00.000

うむ、良さそう。これでspec が通るようになりました


参考記事:

convert -list configure で確認してたり

ruby on rails 3.2 - Carrierwave Error Msg: Failed to manipulate with MiniMagick, maybe it is not an image? - Stack Overflow

PDF 変換をできるようにする、という記事ですが
identify で確認したり、imagemagick を入れ直したりしてます

ImageMagickでPDFを変換できるようにする。 - Qiita

【Ruby on Rails】content_tagでmultipleなselectタグを生成する

要するにこういう感じです

https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_select_multiple

複数の要素を選択できる select タグを作ろうと

こちらを参考にやってみました

https://rubyplus.com/articles/3411-Tag-View-Helpers-in-Rails-5

  • Rails version 5.1.2
  • Ruby version 2.4.0-p0 (x86_64-darwin16)

Rails console 上で試したので、頭に helper をつけます

array = %w(a b c)

helper.content_tag :select, multiple: true do
  array.collect do |item|  
    helper.content_tag(:option, item)    
  end.join.html_safe  
end  
=> "<select multiple=\"multiple\"><option>a</option><option>b</option><option>c</option></select>"

冒頭のw3schools のコードに合わせてみます。ついでに見やすいように結果を整形しました

array = %w(volvo saab opel audi)

html_output =
helper.content_tag :select, name: 'cars', multiple: true do
  array.collect do |item|  
    helper.content_tag :option, item.capitalize, value: item    
  end.join.html_safe  
end  
=> "<select name=\"cars\" multiple=\"multiple\"><option value=\"volvo\">Volvo</option><option value=\"saab\">Saab</option><option value=\"opel\">Opel</option><option value=\"audi\">Audi</option></select>"

require 'cgi'
puts CGI.pretty(html_output)
<select name="cars" multiple="multiple">
  <option value="volvo">
    Volvo
  </option>
  <option value="saab">
    Saab
  </option>
  <option value="opel">
    Opel
  </option>
  <option value="audi">
    Audi
  </option>
</select>

上記の例だと joinhtml_safe を忘れるのが怖い
collect ではなくeach を使用し、その中で生成されたそれぞれのoption タグをconcat helper で連結します
なおかつ、Rails 5.1 で導入されたtag helper も使ってみます

# Using each with tag helper
helper.tag.select name: 'cars', multiple: true do
  array.each do |item|
    helper.concat(helper.tag.option, item.capitalize, value: item)
  end  
end

参考:

https://rubyplus.com/articles/3411-Tag-View-Helpers-in-Rails-5

New Syntax for HTML Tag helpers in Rails 5.1 | BigBinary Blog

RubyでHTMLを整形する - Ruby Tips!

https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_select_multiple