4693


Railsで開発をしているさいに、バリテーションテストであったり、表示テストを行いたいさいに、任意の長さを持つランダムな文字列を作成して、それを使いたいとします。現在、以下のような汚いワンライナーを利用して、それを実現しています:

[code]

      random_string = ->(n){ ->{ (0..n).map{ ->{ ["a", "あ"].sample }.call() }}.call().join }
    
      random_string.call(10)
      # => "aあaaaaあaああa"
    
      random_string.call(20)
      # => "あaaaaaaaaaあaaああaあaaああ"
    
      random_string.call(30)
      # => "ああaあaaaあああああaあaaaああああああaaaあaあaあ"
    
[/code]

当然のことながら、このようなワンライナーは書く分にも読む分にもあまり綺麗ではありませんし、もう少しいい方法があるのではないかと思いました。

ちなみに、意図しているのは以下の通りです:

  * このメソッドは `each`などで利用することを意図しています。例としては `User.all.each { |u| u.name = random_string.call(30) }`という感じで。

  * 生成する文字列に使用する文字列は指定できるほうが望ましい。例えば、上の例なら、サンプルの文字列に`あ`と`a`だけを利用したい

  * 呼び出されるたびに違う文字列を生成したい(何度呼んでも同じ文字列だと困る)

  * 生成する文字列を引数などを使って指定できると嬉しい

以上、いい方法があれば教えて下さい。


CC BY-SA 3.0
2015-01-16T09:57:55.383
4687
2015-01-16T22:56:46.530
939
question
ruby
サンプルデータにセットするための、一定の長さのランダムな文字列を生成するための簡単な方法


綺麗か汚いかは個人の感覚なのですけど、私は、

[code]

    random_string = ->(n){ ->{ (0..n).map{ ->{ ["a", "あ"].sample }.call() }}.call().join }
    
[/code]

よりは

[code]

    random_string = ->(n){ n.times.map{["a", "あ"].sample}.join }
    
[/code]

の方が読みやすいと思います。


CC BY-SA 3.0
2015-01-16T10:46:53.880
4689
2015-01-16T10:46:53.880
3249
4687
answer


これは それなりに汎用的な問題なので、いろいろなアイデアがあるようです。  
参考情報として、"random string ruby" で google 検索した結果からいつくかを抜粋して紹介します。

  * Generate Random String in Ruby <http://yankist.com/blog/2012/11/28/generate-random-string-in-ruby/>
  * シンプルにRubyっぽく、ランダムな文字列生成 <http://qiita.com/diaphragm/items/50b2703c3cd4ba8490a9>
  * How best to generate a random string in Ruby <http://www.acnenomor.com/2105018p1/how-best-to-generate-a-random-string-in-ruby>


CC BY-SA 3.0
2015-01-16T11:33:55.930
4690
2015-01-16T11:33:55.930
2987
4687
answer


[faker](https://rubygems.org/gems/faker)
ライブラリの、[Faker::Base](http://www.rubydoc.info/github/stympy/faker/master/Faker/Base)
と
[Faker::Lorem](http://www.rubydoc.info/github/stympy/faker/master/Faker/Lorem)
が目的にあっていそうです。  
導入は `gem install faker`。`require 'faker'`でインポート。

### ランダム文字列の生成

[code]

    # ランダムな16個の文字
    Faker::Lorem.characters(16)
    => "soqw6mqnla295y72"
    
    # 32文字の`a`と`あ`からなる文字列
    Faker::Base.regexify("[aあ]{32}")
    => "aあaaあaあaあああaaああaああaあああああaあaaあaああ"
    
[/code]

### 名前の生成

[code]

    # それらしい名前を生成
    Faker::Name.name
    => "Robbie Monahan"
    
    # 8人分名前作ってループ
    (0..8).map{ Faker::Name.name }.each{|n| p n}
    "Ewell Miller"
    "Anita Kreiger"
    "Abe Runolfsdottir"
    "Nikita Dietrich"
    "Paige Heathcote"
    "Gracie Keebler"
    "Coleman Kuphal"
    "Ms. Darius Effertz"
    "Misael Lockman"
    
[/code]

### 数値の生成

[code]

    # 下４桁電話サンプリング (dial_telephone というメソッドは自分で作ること)
    (0..100).map{Faker::Base.numerify "0120-3218-####"}.each{|n| dial_telephone n}
    
[/code]

### 段落の生成

自分が Website を作る際は、ランダムの文字の塊ではダメなので、以下のようにすると思います。

[code]

    # 3つの文からなる段落を作成
    Faker::Lorem.paragraph(sentence_count = 3)
    => "Porro vero qui et iste amet. Totam magni quidem nisi necessitatibus voluptatum modi. Accusamus temporibus sed rerum incidunt esse excepturi rerum. Sit adipisci rerum qui corporis. Fuga aliquam dolorem in."
    
[/code]


CC BY-SA 3.0
2015-01-16T11:55:18.940
4693
2015-01-16T11:55:18.940
4978
4687
answer


無理にラムダを使わず、普通にメソッドを定義したほうが柔軟性と可読性が高くなるかなーと思います。  
というわけで、こんなメソッドを考えてみました。

[code]

    LENGTH_MIN_MAX = 5..20
    ALPHABETS = [*'A'..'Z', *'a'..'z']
    def random_string(length: Random.rand(LENGTH_MIN_MAX), chars: ALPHABETS)
      length.times.map { chars.sample }.join
    end
    
    random_string
    => "CjeRHhRUDKbgzlsrDYOE"
    
    random_string
    => "gxbKbtni"
    
    random_string length: 30
    => "fmrvimfqopyiymbdapwmharpkizuft"
    
    random_string chars: %w(A x p)
    => "ApAxxAxxpAAxppxppAxp"
    
    random_string length: 15, chars: %w(Z d f)
    => "ZddZZdZddffffdZ"
    
[/code]

ただ、Hiroshi Yamamotoさんも書いているように、Faker gemを活用するほうが目的に合っている気がしますね。


CC BY-SA 3.0
2015-01-16T12:02:08.073
4694
2015-01-16T22:56:46.530
2015-01-16T22:56:46.530
85
85
4687
answer