19531
railsでテストや開発用に初期データを用意する方法はありますか?

DBに格納できるテキストデータなどはseedなどを使えば良いと思いますが、  
画像ファイルなどのデータを上手く管理する方法があれば教えて下さい。

よろしくお願いします。
CC BY-SA 3.0
2015-11-30T01:15:42.720
19451
2017-11-21T12:56:30.007
9149
question
ruby-on-rails ruby
railsでテストや開発用の初期データ(バイナリ)を用意する方法
初期データをrailsのプログラムからどのように利用するかで、どこに初期データ用のファイルを置くかなどの条件が変わってくると思いますが、一括してそれらの処理を行うならseedに書くか、rakeファイルを作ってそこに処理を書くのが良いのではないでしょうか。  
データベースに画像データを取り込んでしまう設計なら、seedで処理するのも悪くないんじゃないかと思います。画像ファイルの置き場を決めておき、seed内でバイナリモードでオープンし、そのバイナリデータをそのままテーブルレコードに入れてしまう、という考え方です。
CC BY-SA 3.0
2015-12-01T00:32:10.727
19488
2015-12-01T00:39:53.573
2015-12-01T00:39:53.573
9403
9403
19451
answer
質問がざっくりしすぎていて、どんなユースケースを想定しているのかがちょっとわかりにくいですが、ここではRailsチュートリアルの「マイクロポストの画像投稿」をサンプルとして考えてみます。

<http://railstutorial.jp/chapters/user_microposts?version=4.2#sec-
micropost_images>

まず、`/tests/fixtures/images/`ディレクトリに初期データの画像ファイル"sample.jpg"を配置します。

これを`db/seeds.rb`で投入できるようにします。

```

    # Users
    User.create!(name:  "Example User",
                 email: "example@railstutorial.org",
                 password:              "foobar",
                 password_confirmation: "foobar",
                 admin: true,
                 activated:    true,
                 activated_at: Time.zone.now)
    99.times do |n|
      name  = Faker::Name.name
      email = "example-#{n+1}@railstutorial.org"
      password = "password"
      User.create!(name:  name,
                   email: email,
                   password:              password,
                   password_confirmation: password,
                   activated:    true,
                   activated_at: Time.zone.now)  
    end
    
    # Microposts
    users = User.order(:created_at).take(6)
    image_path = File.join(Rails.root, "test/fixtures/images/sample.jpg")
    50.times do
      content = Faker::Lorem.sentence(5)
      users.each { |user|
        # 画像と一緒にマイクロポストの初期データを作成する
        user.microposts.create!(content: content, picture: File.new(image_path))
      }
    end
    
    # Following relationships
    users = User.all
    user  = users.first
    following = users[2..50]
    followers = users[3..40]
    following.each { |followed| user.follow(followed) }
    followers.each { |follower| follower.follow(user) }
    
```

この状態で`bin/rake db:seed`を実行すると画像データとともにサンプルデータが作成されます。

[![画像の説明をここに入力](https://i.stack.imgur.com/2jEiu.jpg)](https://i.stack.imgur.com/2jEiu.jpg)

「これだと自分が考えているユースケースと異なる」という場合は、ユースケースや実際に使っているコードを追記してください。
CC BY-SA 3.0
2015-12-01T22:22:36.477
19531
2015-12-02T01:33:07.167
2015-12-02T01:33:07.167
85
85
19451
answer
自分も「seedデータとしてbinaryの画像データをDBのbinary列に追加したい」と思い、試行錯誤しましたので、忘備録として記載させていただきます。  
cul8erさんの記載してくださっている内容と重複してしまいますが、サンプルコード込ということでご容赦ください。

```

    schema.rb
    create_table "hoges"
     t.binary   "photo",       limit: 65535
    end
    
```

上記のようなテーブル定義でseedデータ作成する際に

```

    path = Rails.root.join("画像が置いてあるパス")
    photo = File.open(path, "rb").read
    
```

これで、photoをHogesテーブルのphoto列の値としてに設定すれば登録できました。

cul8erさんの

> バイナリモードでオープンし、そのバイナリデータをそのままテーブルレコードに入れてしまう

は、File.openの第二引数に" **rb** "を指定して、それを **read** することで実現可能でした～。
CC BY-SA 3.0
2016-10-08T12:09:50.173
29433
2016-10-08T12:09:50.173
14569
19451
answer
半分自分用のノートです:

環境:  
bundle exec rails --version  
Rails 5.1.4

### Fixture:

Create a file `config/initializer/file_fixtures_extension.rb`

```

      require 'active_record/fixtures'
      module FileFixtureExtension
        def file(file_name)
          File::open(Rails.root.join('test/fixtures/', file_name), 'rb') do |f|
            "!!binary \"#{Base64.strict_encode64(f.read)}\""
          end
        end
      end
    ActiveRecord::Fixture.extend FileFixtureExtension
    
```

module
`ActiveRecord::`の部分は必要なかったり変わったりする。エラーが出たら`active_record/fixtures`を検索しましょう。

Create or edit the file `test/fixtures/YourModelName.yaml`

```

    one:
      user: :one
      file: <%= ActiveRecord::Fixture::file 'files_to_upload/test.png' %>
    
```

当然のことながら:

  * `files_to_upload/test.png`  
`test/fixtures/`に用意するフォルダとファイル名(任意);ここからbinary dataを読み込む。

  * `YourModelName`  
fixtureがseedする対象モデル名。

## Running test

bundle exec rails db:seed  
bundle exec rails test  
と打つとtest databaseがFixtureを読み込みtestが実行されます。

## Handling errors example or what I had to go through

Search tool:

```

    sudo apt search ag|grep "silver"
        silversearcher-ag-el/xenial,xenial 0.46-2 all    
    sudo apt install silversearcher-ag
    
```

Find library location:

```

    bundle exec rails test  
    .../config/initializers/file_fixtures_extension.rb:11:in `<top 
    (required)>': uninitialized constant Fixture (NameError)  
    from /home/d/.rvm/gems/ruby-2.4.0/gems/railties-5.1.4/lib/rails/engine.rb:655:in `block in load_config_initializer'  
    
```

エラーの`/home/d/.rvm/gems/ruby-2.4.0/gems`の部分が使用しているgemの位置を報告しています。

Search gems:

```

    cd /home/d/.rvm/gems/ruby-2.4.0/gems  
    ag 'class Fixture '  
    activerecord-5.1.4/lib/active_record/fixtures.rb
    11:  class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
    412:  class FixtureSet
    804:  class Fixture #:nodoc:
    807:    class FixtureError < StandardError #:nodoc:
    
```

`vi activerecord-5.1.0/lib/active_record/fixtures.rb`で覗くと5.1ではFixtureはmodule
ActiveRecordのメンバーです。

## Current database(e.g. development database)にfixtureを読み込む

bundle exec rails db:fixtures:load  

## Running script to modify database

Fixtureを書くのが面倒なときや、バックアップ作業で使うかも。  
bundle exec rails runner your_script_name.rb

## Uploading a file in controller test

```

      test "should update user" do
        #file = Rack::Test::UploadedFile.new(Rails.root.join("test/fixtures/files_to_upload/test.png"))
        file = fixture_file_upload('/files_to_upload/test.png','image/png')
        patch user_url(@user), 
          params: { 
            user: { 
              name:'new name',
              file: file, 
            } 
        }
        assert_redirected_to user_url(@user)
      end
    
```

上の例ではuserモデルのfileのタイプはbinaryです。  
`file:@user.file`はエラーになる。  
`Rack::Test::UploadedFile.new`も`fixture_file_upload`も両方機能します。
CC BY-SA 3.0
2017-11-21T10:12:55.480
39737
2017-11-21T12:56:30.007
2020-06-17T08:14:45.997
-1
9323
19451
answer