<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="initial-scale=1.0,user-scalable=yes">
    <meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="E7HNBjbjZNK-LsWbKXcGctN2tW7df3okXxl0iddI2-yQSSZdo2JvOjcN_2OhByoQiuSOG8hyXFc64HGNCXVROA" />
    <title>Sooey</title>
    <link rel="shortcut icon" href="/favicon.ico">
    <link rel="alternate" type="application/rss+xml" href="http://feeds.feedburner.com/Sooey">

    <link rel="stylesheet" href="/assets/application-e59afb733507d4a4489edaa918d7f367b57c495cf62e452d0ae2549f12336fcc.css" />
    
  </head>
  <body>
    <div id="main">
      


      <header>
        <h1 id="logo" class="tk-daniel">
          <a href="/">Sooey</a>
        </h1>
      </header>
      <nav class="primary">
        <ul class="social tk-museo">
    <li>
      <a href="https://junya.bio.link/">links</a>
    </li>
    <li>
      <a href="https://qnyp.com/junya">qnyp</a>
    </li>
</ul>

      </nav>
      <div id="content">
        <div class="autopagerize_page_element">
  <article class="post">
  <header>
    <h1 class="tk-museo">
      <a href="/274">2018-06-05 21:29:40 +0900</a>
    </h1>
  </header>
  <div class="content">
    <p>Capybara 3.0.0にてCapybara::Element::Node#textなどの戻り値が変化する仕様変更があった</p>

<p>Capybara 3.0.0(厳密には<a href="https://github.com/teamcapybara/capybara/blob/master/History.md#version-300rc2">3.0.0.rc2</a>)にて、</p>

<ul>
<li>Visibile text whitespace is no longer fully normalized in favor of being more in line with the WebDriver spec for visible text</li>
</ul>

<p>という仕様変更が行われた結果、</p>

<pre><code>element = page.first(&#39;.some-element&#39;)
expect(element).to have_content(&quot;Foo\nBar&quot;)
</code></pre>

<p>のように <code>Capybara::Element::Node</code> のコンテンツに対して「改行」や「連続する空白文字」を期待値としているテストが失敗するようになりました(実際の値として返される文字列が <code>Foo Bar</code> のようになるため)。</p>

<p>これはどうやら、「ブラウザ上での表示に近い文字列を返す」ようにする意図の変更のようです。</p>

<ul>
<li><a href="https://github.com/teamcapybara/capybara/pull/1982">Change #text to be closer to what a browser displays by twalpole · Pull Request #1982 · teamcapybara/capybara</a></li>
</ul>

<p>従来どおりにテストを成功させるための対応としては、</p>

<pre><code>element = page.first(&#39;.some-element&#39;)
expect(element.native.text).to have_content(&quot;Foo\nBar&quot;)
</code></pre>

<p>のようにネイティブなオブジェクト経由で文字列を取得するようにすればよさそうです。</p>

  </div>
</article>
<article class="post">
  <header>
    <h1 class="tk-museo">
      <a href="/273">2017-11-19 01:46:20 +0900</a>
    </h1>
  </header>
  <div class="content">
    <p>rspec 3.7でOmniAuthのテストモードが失敗するようになった場合の対策。</p>

<p>rspec (rspec-rails) を3.7.xにアップデートしてから、<a href="https://github.com/omniauth/omniauth/wiki/Integration-Testing">Integration Testing · omniauth/omniauth Wiki</a>にあるような <code>OmniAuth.config.test_mode</code> を使ったFeature specが失敗するようになってしまった場合は、Pumaがclusters modeで動作するように設定されていないか見直すこと。</p>

<p>具体的には、<code>config/puma.rb</code> が<a href="https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#workers">Herokuの推奨する</a>以下のような設定になっていると、</p>

<pre><code>workers Integer(ENV[&#39;WEB_CONCURRENCY&#39;] || 2)
</code></pre>

<p>テスト時にOmniAuthのモックがうまく設定されない状態でテストが実行されてしまうようになる。</p>

<p>これを、</p>

<pre><code>if  ENV.fetch(&#39;RAILS_ENV&#39;) { &#39;development&#39; } == &#39;test&#39;
  workers 0
else
  workers Integer(ENV[&#39;WEB_CONCURRENCY&#39;] || 2)
end
</code></pre>

<p>のようにしてclusters modeでは動作しないようにした状態でテストを実行すると、おそらく従来通りの結果が得られる。</p>

<p>他にも <code>VCR.use_cassette &#39;...&#39; { ... }</code> のようにVCRで囲んだ部分でもリクエストをフックしてモックデータを返すような動作をしなくなるなど、clusters modeにしていることによってハマることがある。</p>

<ul>
<li><a href="https://github.com/omniauth/omniauth/issues/918">mock_auth doesn&#39;t redirect to success url with rspec 3.7.0 · Issue #918 · omniauth/omniauth</a></li>
<li><a href="https://stackoverflow.com/questions/44124072/how-can-i-use-vcr-with-rails-5-1-system-tests">capybara - How can I use VCR with Rails 5.1 system tests? - Stack Overflow</a></li>
<li><a href="https://github.com/rails/rails/pull/30638">Use the default Capybara registered puma server configuration by twalpole · Pull Request #30638 · rails/rails</a></li>
</ul>

  </div>
</article>
<article class="post">
  <header>
    <h1 class="tk-museo">
      <a href="/272">2017-08-29 22:13:38 +0900</a>
    </h1>
  </header>
  <div class="content">
    <p>PhantomJSからChromeDriverに移行した場合にテストでダイアログのボタンをどのように押すか</p>

<p>Poltergeist + PhantomJSという組み合わせでRailsアプリのFeature specを書いている場合、JavaScriptのalertやconfirmでダイアログが開かれた時には常にOKボタンが押されるようになるため、クリックすると確認のダイアログが開くようなボタンを押すテストは以下のようなコードで実行することができる。</p>

<pre><code>find(&quot;#button-with-confirm&quot;).click
</code></pre>

<p>これを、ChromeDriveとselenium-driverを使ったFeature specに移行した場合、以下のようにCapybaraのaccept_alertを利用して明示的にダイアログのボタンを押すようなコードにする必要がある。</p>

<pre><code>accept_alert do
  find(&quot;#button-with-confirm&quot;).click
end
</code></pre>

  </div>
</article>
<article class="post">
  <header>
    <h1 class="tk-museo">
      <a href="/271">2017-07-20 00:23:28 +0900</a>
    </h1>
  </header>
  <div class="content">
    <p>Rails 5.1の新しいform_withヘルパーはINPUT要素にid属性を設定しない</p>

<p>Rails 5.1で新たに導入された <code>form_with</code> ヘルパーは、これまでの <code>form_for</code> ヘルパーと違って、そのフォームオブジェクトを利用して生成されるDOM要素にid属性やclass属性をできるだけ付けないように設計されているようだ。</p>

<ul>
<li><a href="https://github.com/rails/rails/issues/29450">form_with is not assigning id&#39;s to inputs · Issue #29450 · rails/rails</a></li>
<li><a href="https://github.com/rails/rails/issues/25197">Provide form_with as a new alternative to form_for/form_tag · Issue #25197 · rails/rails</a></li>
</ul>

<p>したがって、従来の <code>form_for</code> ヘルパーによって以下のようなHTMLが生成されていた場合に、</p>

<pre><code>&lt;label for=&quot;title_genre&quot;&gt;作品ジャンル&lt;/label&gt;
&lt;input type=&quot;text&quot; id=&quot;title_genre&quot; value=&quot;...&quot;&gt;
</code></pre>

<p>Capybara を使った feature spec 内で、以下のようにLABEL要素とINPUT要素のfor/id属性値による紐付けを利用して、</p>

<pre><code>fill_in &#39;作品ジャンル&#39;, with: &#39;ホラー&#39;
</code></pre>

<p>のように指定していた箇所の実行が <code>Capybara::ElementNotFound: Unable to find field &quot;作品ジャンル&quot;</code> で失敗するようになる。</p>

<p>これを回避するためには、新しい <code>form_with</code> ヘルパーのフォームオブジェクトを利用してDOM要素を生成する際に、以下のように明示的にid属性値を指定する必要がある。</p>

<pre><code>&lt;%= form_with(...) do |form| %&gt;
  &lt;%= form.label(:genre) %&gt;
  &lt;%= form.text_field(:genre, id: :title_genre) %&gt;
&lt;% end %&gt;
</code></pre>

<p>このあたりの挙動についてはAPIリファレンスの<a href="http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_with">form_with</a>の項目で詳しく解説されている。</p>

<p>また、以下のように <code>label</code> ヘルパーをブロックを渡す形で利用している場合には、生成されるLABEL要素に<code>for</code>属性が設定される一方でブロック内のINPUT要素などには<code>id</code>属性値が自動設定されないため、意図した動作（「確認しました」の部分をクリックするとチェックボックスが切り替わる）にならない場合がある。</p>

<pre><code>&lt;%= form.label(:confirmation) do %&gt;
  &lt;%= form.check_box(:confirmation) %&gt; 確認しました
&lt;%= end %&gt;
</code></pre>

<p>これを解消するには、今のところ <code>for</code> 属性値を設定しないことを <code>label</code> ヘルパーで明示する必要があるようだ。</p>

<pre><code>&lt;%= form.label(:confirmation, for: nil) do %&gt;
  &lt;%= form.check_box(:confirmation) %&gt; 確認しました
&lt;%= end %&gt;
</code></pre>

  </div>
</article>
<article class="post">
  <header>
    <h1 class="tk-museo">
      <a href="/270">2016-05-21 23:31:51 +0900</a>
    </h1>
  </header>
  <div class="content">
    <p>CircleCI上でのRails 5.0.0.rc1 + factory_girl_railsのビルドがPG::UndefinedTableで失敗する件</p>

<p>以下のような構成のRailsアプリをCircleCIでビルドする際、</p>

<ul>
<li>Rails 5.0.0.rc1</li>
<li>factory_girl_rails 4.7.0</li>
</ul>

<p><code>rake db:create db:schema:load</code>や<code>rake db:create db:structure:load</code>のフェーズで以下のような例外が発生してビルドが失敗するようになった。</p>

<pre><code>ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  relation &quot;posts&quot; does not exist
LINE 8:                WHERE a.attrelid = &#39;&quot;posts&quot;&#39;::regclass
                                          ^
:               SELECT a.attname, format_type(a.atttypid, a.atttypmod),
                     pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
             (SELECT c.collname FROM pg_collation c, pg_type t
               WHERE c.oid = a.attcollation AND t.oid = a.atttypid AND a.attcollation &lt;&gt; t.typcollation),
                     col_description(a.attrelid, a.attnum) AS comment
                FROM pg_attribute a LEFT JOIN pg_attrdef d
                  ON a.attrelid = d.adrelid AND a.attnum = d.adnum
               WHERE a.attrelid = &#39;&quot;posts&quot;&#39;::regclass
                 AND a.attnum &gt; 0 AND NOT a.attisdropped
               ORDER BY a.attnum    
</code></pre>

<p>スタックトレースや<a href="https://circleci.com/docs/ruby-exception-during-schema-load/">rake db:schema:load fails - CircleCI</a>を見た結果、以下のような流れになっていることがわかった。</p>

<ul>
<li>Railsのロード過程で<code>factory_girl_rails/railtie.rb</code>が読み込まれる</li>
<li><code>FactoryGirl.find_definitions</code>が呼び出される</li>
<li><code>spec/factories/*.rb</code>が読み込まれる</li>
<li>モデルクラスがロードされる</li>
<li>モデルクラスに対応するテーブルがまだ存在しないため例外が発生</li>
</ul>

<p>Rails 5.0がリリースされるまでの過程で解消するのかもしれないが、ひとまず<code>Gemfile</code>では<code>factory_girl_rails</code>を<code>require</code>しないようにして、</p>

<pre><code>group :test do
  ...
  gem &#39;factory_girl_rails&#39;, &#39;4.7.0&#39;, require: false
  ...
end
</code></pre>

<p>そのかわりに<code>spec/spec_helper.rb</code>で明示的に<code>require</code>する形にして問題を回避することにした。</p>

<pre><code>#
# factory_girl_rails
#
# To prevent PG::UndefinedTable excetion during `rake db:structure:load` on
# CircleCI build, we don&#39;t require the gem in Gemfile.
# Because of this, we need to require it explicitly here.
#
# See: https://circleci.com/docs/ruby-exception-during-schema-load/
#
require &quot;factory_girl_rails&quot;
</code></pre>

  </div>
</article>

</div>
  <nav class="pagination" role="navigation" aria-label="pager">
    
    
        <span class="page current">
  1
</span>

        <span class="page">
  <a rel="next" href="/?page=2">2</a>
</span>

        <span class="page">
  <a href="/?page=3">3</a>
</span>

        <span class="page">
  <a href="/?page=4">4</a>
</span>

        <span class="page">
  <a href="/?page=5">5</a>
</span>

        <span class="page gap">&hellip;</span>

      <span class="next">
  <a rel="next" href="/?page=2">Next &rsaquo;</a>
</span>

      <span class="last">
  <a href="/?page=55">Last &raquo;</a>
</span>

  </nav>


      </div>
      <footer>
        <address>
          written by Junya Ogura <juno at sooey.com>
        </address>
        <p class="copyright">
          <a rel="license" href="https://creativecommons.org/licenses/by-nd/4.0/deed.ja">
            <img alt="Creative Commons License" style="border-width:0" src="//mirrors.creativecommons.org/presskit/buttons/80x15/svg/by-nd.svg">
          </a>
        </p>
      </footer>
      <div class="autopagerize_insert_before"></div>
      <!-- This page rendered at 2025-11-20 21:03:07 +0900 -->
    </div>
    <script src="/assets/application-5472823e7cddc2710f959523cca4fe5d986df21ac3ccb6ea8e06f6e2329e1534.js"></script>
      <script type="text/javascript">
    var _gaq = _gaq || [];
    _gaq.push(['_setAccount', 'UA-17293111-1']);
    _gaq.push(['_setDomainName', 'sooey.com']);
    _gaq.push(['_trackPageview']);
    (function() {
      var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
      ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
      var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
    })();
  </script>

  </body>
</html>
