20200830のRubyに関する記事は17件です。

thorでオプションを定義する6つの方法

Rubyでcliを作るときに定番のgem thorではコマンドのオプション(--key value みたいなやつ)を定義するときにmethod_optionを利用する.
しかし,いくつかのブログやドキュメント等を参照すると他にもいくつかの方法がある.
この違いがよくわからなかったのでいろいろ確認した.

オプション定義方法を解説する2種類のドキュメント

thorのドキュメントとしては,GitHub wiki公式webサイトの2種類存在する.

GitHub wikiでは method_optionmethod_options で定義する方法が紹介されている.
こちらのwikiには option / options を用いて定義する方法については触れられていない.

Thor allows you to specify options for its tasks, using method_options to supply a hash of options, or method_option to provide more detail about an individual option.

GitHub/wiki記載のサンプル
method_option :value, :default => "some value"
#=> Creates a string option with a default value of "some value"

一方で,公式webサイトでは Options and Flags の章にて optionoptions を用いて定義する方法が紹介されている.
こちらのドキュメントには method_option / method_options を用いて定義する方法については触れられていない.

Thor makes it easy to specify options and flags as metadata about a Thor command:

公式webサイト記載のサンプル
class MyCLI < Thor
  desc "hello NAME", "say hello to NAME"
  option :from
  def hello(name)
    puts "from: #{options[:from]}" if options[:from]
    puts "Hello #{name}"
  end
end

なお method_optionsmethod_option の違いについて GitHub wiki には,
method_option は個別のオプションに対してより詳細な項目を定義するために利用すると説明がある.
optionsoption の違いについて公式webサイトには,
options は複数の option を一度に定義できると説明がある.
上記の説明では, method_optionmethod_options の関係は optionsoption の関係とは異なるように読める.

You can use a shorthand to specify a number of options at once if you just want to specify the type of the options.

また,公式webサイトには上記に加えて Class Options の章で class_option という別の方法が記載されている.
class_option はGitHub wikiでは説明はなく,GeneratorsGroupsで参照されているだけだった.
ただし,公式webサイトでは触れられていない class_options も参照されている.

You can specify an option that should exist for the entire class by using class_option. Class options take exactly the same parameters as options for individual commands, but apply across all commands for a class.

公式webサイト記載のclass_optionサンプル
class MyCLI < Thor
  class_option :verbose, :type => :boolean

  desc "hello NAME", "say hello to NAME"
  options :from => :required, :yell => :boolean
  def hello(name)
    puts "> saying hello" if options[:verbose]
    output = []
    output << "from: #{options[:from]}" if options[:from]
    output << "Hello #{name}"
    output = output.join("\n")
    puts options[:yell] ? output.upcase : output
    puts "> done saying hello" if options[:verbose]
  end

  desc "goodbye", "say goodbye to the world"
  def goodbye
    puts "> saying goodbye" if options[:verbose]
    puts "Goodbye World"
    puts "> done saying goodbye" if options[:verbose]
  end
end

使い分け

method_options と options

この疑問についてはまさに同じ内容のissueが報告されている.
参考: Difference between method_options and options #596

結論としてはどちらも同じ.GitHub wikiは内容が古くなっているということ.
実際,GitHub wikiには内容が古くなっているので公式wbサイトを参照してくれと注意書きがある

NOTE: a good part of the documentation here is outdated, see the website instead: http://whatisthor.com

実装を見ても, method_optionsで実装されて options でエイリアスが張られている
同様に, method_option で実装されて optionでエイリアスが張られてもいる

lib/thor.rb#128
alias_method :options, :method_options
lib/thor.rb#165
alias_method :option, :method_option

method_options と method_option

一方で, method_optionsmethod_option (および optionsoption)の違いについて,
単に method_options は複数の method_option を同時に指定できるというだけでなく,
method_option でしか定義できない詳細オプションがある様子.
すなわち GitHub wikiが正しい (公式webサイトの記載を自分が読み違えている?).

具体的には,method_options では :required, :type, :default, :aliases の4つしか指定できない.
これはmethod_optionsを指定したときの処理の実装上,この4つしか対応していないように読める.
その他の指定可能な項目として,公式webサイトでは :desc, :banner を,
GitHub wikiでは上記に加えて :lazy_default, :enum を,
オプション項目の生成処理の実装を見ると上記に加えて :hide
それぞれ指定可能のように見える.

method_options と class_options

class_options および class_option は説明の通り,指定したクラスに定義されたコマンドすべてに適用される.
利用可能な項目は method_options および method_option と等しい.

なお,class_option実装のコメントを見ると lazy_default の記載がない.
しかし実際には class_optionmethod_option も共通の build_optionで生成しているので
おそらく laze_defaultも含めて共通化されている.

結論

  • method_optionsoptions, method_optionoption の機能はそれぞれ同じ.どちらを利用してもよい.
  • method_optionsmethod_option は役割が異なる.
    • method_options は異なる複数のオプションに対して, method_option は単一のオプションに対して項目を指定する.
    • method_optionsrequired, type, default, aliases の計4項目を指定できる.
    • method_option では上記に加えて desc, banner, lazy_default, enum, hide の計9項目を指定できる.
  • method_optionsclass_options は対象となるコマンドが違うだけで同じ項目を指定できる. class_option も同様.
  • ドキュメントは GitHub wikiと公式webサイトがあるが,どちらも古いので両方とも鵜呑みにできない.
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ヒトゲノムの配列の特定されてないところを見てみたりする夏休みの絵日記的なやつだよ

はじめに

この記事はすごいテキトーな記事なので真に受けるなよろし。

目的

ヒトゲノム計画では、人のDNAの配列が全部明らかにされたと言われていますが、実際にはわかっていない部分もかなりあるはずです。
どこの部分がわかっていないのか、グラフを描きます。

ヒトゲノムのfastaのダウンロード

Gencodeからヒトゲノムの配列がダウンロードできます。
https://www.gencodegenes.org/human/

ここでは、贅沢にALLをダウンロードします。

wget ftp://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_35/GRCh38.p13.genome.fa.gz

解凍してもいいのですが、zcat コマンドを使えばある程度見ることができますね。

まずは head を表示してみます。

zcat GRCh38.p13.genome.fa.gz | head
>chr1 1
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN

はい、早速出てきました。Nの山です。つまり、配列が特定できていない部分がのっけの頭から来ているわけですね。
次に、一応染色体を確認しておきましょう。

zcat GRCh38.p13.genome.fa.gz | grep "^>"

hoge.png

まあ、こんな感じで大量に出てきます。

次に、本当に配列がTCGANだけの5種類の文字列から構成されているのか確認してみることにします。
きっとコマンドラインツールを使う方法もあると思うのですが、ここはCrystal言語を使って小さなプログラムを書いてしまうことにします。なぜCrystal言語かというと爆速だからですね。

count.cr
counter = Hash(Char, Int32).new(0)

while l = gets
    l.chomp.each_char do |c|
        counter[c] += 1
    end
end

p counter

はい、Rubyわかる人には何の変哲もないコードですね。ポイントは、Hashの生成時に型を指定しているところだけです。ほかは全部Rubyと同じです。これがCrystalです。ビルドします。

crystal build counter.cr --release

このビルド時間を含めると実行速度でJulia等とあまり変わらないかも知れませんが気にしないことにします。
では、TCGANの数を数えてみましょう

zcat GRCh38.p13.genome.fa.gz | grep -v "^>" | ./count

grep -v "^>" で行頭の染色体などを定義している行を省いています。結果は

{'N' => 161331703, 'T' => 916993511, 'A' => 914265135, 'C' => 635937481, 'G' => 638590158}

となりました。確かに,TCGAおよびN以外の文字列が存在しないことが確認できました。次はNの連続の分布を数えてみましょう。つまりNが何文字連続するか、を調べてみてみることにします。

nseq.cr
temp = 0 

while l = gets
    l.chomp.each_char do |c|
        if c == 'N'
             temp += 1
        elsif temp != 0
            puts temp
            temp = 0
        end
    end
end
puts temp if temp != 0

ビルドします。

crystal build nseq.cr --release

まずはNの連続する箇所がいくつあるか調べてみましょう。

zcat GRCh38.p13.genome.fa.gz | grep -v "^>" | ./nseq | wc -l

1234

そんなに多くないことがわかります。これを長い順に並べて表示するとこんな感じになります。

fuga.png

1っていうのが不思議な気がするのと、100とか50000とかが多いなあといった印象ですかね。

本題

さて、適当に10000文字ごとに、N, AT, CGの割合を計算してくれるようなプログラムを書きます。

n2
tcgan = Hash(Char, Int32).new(0)

target = ARGV[0]
chr = ""
loc = 1
flag = false

while l = gets
  if l.starts_with?(">")
    exit if flag
    if l == target
      puts "loc\tN\tAT\tCG"
      flag = true
    end
    next
  end
  if flag
    l.chomp.each_char do |c|
      tcgan[c] += 1
      loc += 1
      if loc % 10000 == 0
        total = tcgan.values.sum.to_f
        ta = (tcgan['A'] + tcgan['T']) / total
        cg = (tcgan['G'] + tcgan['C']) / total
        n  = tcgan['N'] / total
        puts "#{loc}\t#{n}\t#{ta}\t#{cg}"
        tcgan = Hash(Char, Int32).new(0)
      end
    end
  end
end

ためしに実行します。

zcat GRCh38.p13.genome.fa.gz | ./n2 ">chr1 1" | head
loc N   AT  CG
10000   1.0 0.0 0.0
20000   0.0001  0.4076  0.5923
30000   0.0 0.4826  0.5174
40000   0.0 0.5288  0.4712
50000   0.0 0.6439  0.3561
60000   0.0 0.6346  0.3654
70000   0.0 0.6669  0.3331
80000   0.0 0.6199  0.3801
90000   0.0 0.6294  0.3706

だいたいうまくいってるようですね。Rubyで同じ動作のプログラムを作成すると、実行時間がすごくがかかってしまいますがCrystalは超高速です。これをコマンドラインでuplotに投げていきます。

uplotというのは、UnicodePlots.rbを使ってターミナル上にグラフを表示できる私が個人的に作っているRuby製のツールです。

ここからターミナルにグラフを描いて、それをスクリーンショットを取ってQiitaに貼り付けるというかなり意味のわからないことをしています。

chr1

image.png

chr2

image.png

chr3

image.png

chr4

image.png

chr5

image.png

chr6

image.png

chr7

image.png

chr8

image.png

chr9

image.png

chr10

image.png

chr11

image.png

chr12

image.png

chr13

image.png

chr14

image.png

chr 15

image.png

chr 16

image.png

chr 17

image.png

chr 18

image.png

chr 19

image.png

chr 20

image.png

chr 21

image.png

scatterも追加
image.png

chr 22

image.png

scatterも追加
image.png

chr X

image.png

chr Y

image.png

Wikipediaによると、
主にヘテロクロマチン領域が未解読であり、その領域は活性がないそうです。転写とかほとんどされないという意味だと思います。
つまり生物学的にはあまり意味がないということなのかも知れません。

しかしこうやってみると、配列のわかっていない部分はずいぶんあるんだな〜という感じですね。

詳しい方とかいらっしゃいましたらご自由に突っ込んでください。

この記事は以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails AWSのデプロイが反映されない場合

AWS デプロイが反映されない場合に行うこと

環境
rails 5.2.4
unicorn
nginx
capistranoで自動デプロイした場合にすぐにAWSに反映されないことがある方向け

解決法

デプロイする前にローカルで
cap production unicorn:stop
この後に、
bundle exec cap production deploy
をターミナルでうちましょう。unicornがストップします。自動デプロイでも同じようにunicornはストップ
させているはずですが、すぐに反映されないことも多いです。私の環境ではこれですぐにデプロイが反映されています

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[過去POST]TECH::CAMPのメンターをしていた時の回答メモを一部公開します

過去POST

過去自分がTECH::CAMPのメンターをしていた時期にメモしていた内容を公開します。
小分けにしようとしましたが小粒なものはまとめておきます。
記憶が曖昧なので間違っている箇所もあるかもしれないです…

Q.ハッシュの中身が取り出せない

movie = {"title" => "ハリーポッター", "genre" => "ファンタジー", "year" => "2001年"}
から取りたい文字列を取るコードを書きましょう。
のような問題だったと思います。

該当コード

def movie_info(movie, data)
  puts movie[data]
end

movie = {"title" => "ハリーポッター", "genre" => "ファンタジー", "year" => "2001年"}

puts "以下から一つを選んで入力してください。
  ・title
  ・genre
  ・year"

info = gets.chomp

movie_info(movie, info)

解説

ここで
puts movie[:data]
としてしまうとうまくいかないです。
その原因は型が違うからです。

info = gets.chomp
ここでキーを「文字列」として受け取っているので
ハッシュの定義も文字列"title"を使っているのでここでは問題はおこりません。

puts movie[:data]
一方で、こう記述すると、シンボル型で出力してしまい、
型が違うためなにも出力されません。

ちなみに型を調べるのは.classを使うと調べられます。
ex) info.class

もしシンボル型を使いたいなら
movie = {title: => "ハリーポッター”}
のようにハッシュの定義を変えて
info = gets.chomp.to_sym
のように書き換えるとうまくいきます。

puts movie[data.to_sym]
でも大丈夫です。(シンボル型に変換)

Q.devise, no method error

devise関連でno method errorが出た時。current_sign_in_atがないなど。

対処方法

deviseによって作成した、該当のマイグレーションファイルを確認
該当箇所周辺のコメントアウト外して
データベースを作成し直す
$ rake db:migrate:reset
このコマンドで一気にできます。

このコマンドは、データベースを一度ドロップして、
今あるマイグレートファイルを元にデータベースを作り直すというコマンドです。
もちろんデータベースに入っていたデータは消えます。
色々データが入っていて残しておきたい場合、CSVでデータを出力してどっかに保存してからやるべきかと思います。

直前にマイグレートしたものならrollbackで戻っても良いかもしれません。

$ rake db:migrate:status

で現在どのファイルがmigrateされているのか確認できます。

*ちなみに db:resetやっても意味ないです。スキーマファイルから作り直すだけなので。

原因

deviceをインストールした際、デフォルトでコメントアウトされている項目をそのままにしてしまい
使用したいメソットが生成されなかったため。
もう一度マイグレーションをやり直すことで解決するはず。

Q.heroku上で、idが10刻みで付与される

開発環境では問題ないが、本番環境でのみ、変わってしまう。
あまり気になる人はいない気がしますが、これはclearDBのデフォルトの設定です。
herokuでは、dbサーバーとしてcleardbを使っているようです。

【参照】
http://w2.cleardb.net/faqs/#general_16
When I use auto_increment keys (or sequences) in my database, they increment by 10 with varying offsets. Why?
ClearDB uses circular replication to provide master-master MySQL support. As such, certain things such as auto_increment keys (or sequences) must be configured in order for one master not to use the same key as the other, in all cases. We do this by configuring MySQL to skip certain keys, and by enforcing MySQL to use a specific offset for each key used. The reason why we use a value of 10 instead of 2 is for future development.

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【ruby】splitメソッドで、文字列から配列にしたい。逆も然り。

文字列を配列化させて、配列を文字列にして、、、というパターンの時に、どういう書き方が期待する値になってくれるでしょうか。

ということで、ダメなパターンも交えて、整理していきましょう!

文字列を配列にする

splitメソッドを使っていきます。

split 英訳:分断する
つまり、まとまりのあるもの(文字列等)を分断させて、要素とさせるメソッドになります。(配列化)
引数は、切り取る部分の境目を指定するイメージになります

様々なまとまりのパターンから、配列化をしてみました。
させたい配列は、["foo", "bar", "baz"]とします。

さて、どの書き方が合っているでしょうか。

# 配列化                       # 返り値
"foo bar baz".split           ["foo", "bar", "baz"]  # ○
"foo bar baz".split('')       ["f", "o", "o", " ", "b", "a", "r", " ", "b", "a", "z"]
"foo bar baz".split(',')      ["foo bar baz"]

"foobarbaz".split             ["foobarbaz"]
"foobarbaz".split('')         ["f", "o", "o", "b", "a", "r", "b", "a", "z"]
"foobarbaz".split(',')        ["foobarbaz"]
"fooxbarxbaz".split('x')      ["foo", "bar", "baz"]  # ○

"foo, bar, baz".split         ["foo,", "bar,", "baz"]
"foo, bar, baz".split('')     ["f", "o", "o", ",", " ", "b", "a", "r", ",", " ", "b", "a", "z"]
"foo, bar, baz".split(',')    ["foo", " bar", " baz"]

"foo,bar,baz".split           ["foo,bar,baz"]
"foo,bar,baz".split('')       ["f", "o", "o", ",", "b", "a", "r", ",", "b", "a", "z"]
"foo,bar,baz".split(',')      ["foo", "bar", "baz"]  # ○

%w[foo bar baz]               ["foo", "bar", "baz"]  # ○

この中から、期待する配列になる書き方は、4通りということになります。

配列から、文字列にしたい

joinメソッドを使っていきます。
引数に、要素と要素の間に差し込む値を入れていくイメージになります

# 文字列化                           # 返り値
["foo", "bar", "baz"].join        "foobarbaz"
["foo", "bar", "baz"].join('')    "foobarbaz"
["foo", "bar", "baz"].join(',')   "foo, bar, baz"

おまけ 範囲を配列化

# 範囲を配列化                #戻り値
(0..9).to_a                 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
('a'..'z').to_a             ["a",..,"z"]
(1..5).map{ |i| i**2 )      [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

リスト処理関数(cons,car,cdr,atom,list)実装例まとめ

拙作記事『7行インタプリタ実装まとめ』について,そろそろSchemeとPython以外にも対応しないとなあと思っていろいろ整理した結果,『S式入力の実装部分がほとんどじゃないこれ?』→『あと,リスト処理内容に基準を設けてないと言語ごとに実装方針がバラバラになりそう』となり,とりあえず『cons car cdr atom listが使える』ようにする記述例を先にまとめていくことにした次第.ターゲット言語上での純LISP機能実装に近いとでもいいますか.

※Python版については,これを用いたS式入出力記述例も掲載しています(他の言語版も揃ったら別記事に移すかも).

仕様

  • ドット対(cons cells)を定義
  • アトムは全て文字列,空リストはNULL
  • cons car cdrを実装
  • アトムか否かを判定するatomを実装
  • 文字列の羅列から単方向リストを生成するlistを実装

Python(CPython 3.7.3)

ドット対はペア要素のタプルで定義(不変としたいため).空リストNULLはNoneを使用.

#### Cons cells are created by using tuple.
#### All of atoms are string and the null value is None.
def cons(x, y): return (x, y)
def car(s): return s[0]
def cdr(s): return s[1]
def atom(s): return isinstance(s, str) or s == None
def list(ts):
    if not ts:
        return None
    else:
        return cons(ts[0], list(ts[1:]))

利用例は次の通り.

def mkassoc(a, b):
    if a == None or b == None:
        return None
    else:
        return cons(cons(car(a), car(b)), mkassoc(cdr(a), cdr(b)))

def assoc(k, vs):
    if vs == None:
        return None
    else:
        if car(car(vs)) == k:
            return car(vs)
        else:
            return assoc(k, cdr(vs))
>>> vs = mkassoc(list(("hoge", "hage", "hige")), list(("10", "20", "30")))
>>> assoc("hage", vs)
('hage', '20')
>>> car(assoc("hage", vs))
'hage'
>>> cdr(assoc("hage", vs))
'20'

(上記定義を用いたS式入出力記述例)

#### Cons cells are created by using tuple.
#### All of atoms are string and the null value is None.
def cons(x, y): return (x, y)
def car(s): return s[0]
def cdr(s): return s[1]
def atom(s): return isinstance(s, str) or s == None
def list(ts):
    if not ts:
        return None
    else:
        return cons(ts[0], list(ts[1:]))

#### s_read

# '(a b c)'
# => ['(', 'a', 'b', 'c', ')']
def s_lex(s):
    return s.replace('(', ' ( ').replace(')', ' ) ').split()

# ['(', 'a', 'b', 'c', ')']
# => ('a', 'b', 'c')
def s_syn(s):
    t = s.pop(0)
    if t == '(':
        r = []
        while s[0] != ')':
            r.append(s_syn(s))
        s.pop(0)
        return tuple(r)
    else:
        if t == 'None':
            return None
        else:
            return t

# ('a', 'b', 'c')
# => ('a', ('b', ('c', None)))
def s_sem(s):
    if atom(s):
        return s
    elif len(s) == 0:
        return None
    elif s[0] == '.':
        return s_sem(s[1])
    else:
        return cons(s_sem(s[0]), s_sem(s[1:]))

def s_read(ss): return s_sem(s_syn(s_lex(ss)))

#### s_print

def s_prcons(s):
    sa_r = s_print(car(s))
    sd = cdr(s)
    if sd == None:
        return sa_r
    elif atom(sd):
        return sa_r + ' . ' + sd
    else:
        return sa_r + ' ' + s_prcons(sd)

def s_print(s):
    if atom(s):
        return s
    elif s == None:
        return None
    else:
        return '(' + s_prcons(s) + ')'
>>> s_print(s_read('((Apple . 100) (Orange . 120) (Lemmon . 250))'))
'((Apple . 100) (Orange . 120) (Lemmon . 250))'
>>> x = s_read('((Apple . 100) (Orange . 120) (Lemmon . 250))')
>>> car(x)
('Apple', '100')
>>> car(car(cdr(x)))
'Orange'
>>> s_print(cdr(x))
'((Orange . 120) (Lemmon . 250))'

C言語(gcc 8.3.0)

atom実装のため,まず,文字列とドット対ポインタの両方を扱うことができるnode_t構造体を定義,それを用いてドット対cons_t構造体を定義.空リストNULLはNULLポインタを使用.

#include <stdio.h>
#include <stdlib.h>

/* Cons cells are created by using typedef struct. */
/* All of atoms are char* and the null value is NULL. */

typedef unsigned int value_t;
enum NODE_TAG { NODE_STRG, NODE_CONS };

typedef struct _node_t_ {
  value_t value;
  enum NODE_TAG tag;
} _node_t, *node_t;

node_t node(value_t value, enum NODE_TAG tag)
{
  node_t n = (node_t)malloc(sizeof(_node_t));
  n->value = value; n->tag = tag;
  return (n);
}

typedef struct _cons_t_ {
  node_t x;
  node_t y;
} _cons_t, *cons_t;

node_t cons(node_t x, node_t y)
{
  cons_t c = (cons_t)malloc(sizeof(_cons_t));
  c->x = x; c->y = y;
  node_t n = node((value_t)c, NODE_CONS);
  return (n);
}

#define str_to_node(s)  (node((value_t)(s), NODE_STRG))
#define node_to_str(s)  ((char *)(s->value))

#define car(s)  (((cons_t)(s->value))->x)
#define cdr(s)  (((cons_t)(s->value))->y)
#define atom(s) (s->tag == NODE_STRG)

#define MAXSTR 64

node_t list(const char s[][MAXSTR], const int n)
{
  node_t r = str_to_node(NULL);
  for (int i = n - 1; i >= 0; i--) {
    r = cons(str_to_node(s[i]), r);
  }
  return (r);
}

利用例は次の通り.

#include <string.h>

node_t mkassoc(node_t a, node_t b)
{
  if (node_to_str(a) == NULL || node_to_str(b) == NULL) {
    return NULL;
  } else {
    return cons(cons(car(a), car(b)), mkassoc(cdr(a), cdr(b)));
  }
}

node_t assoc(node_t k, node_t vs)
{
  if (node_to_str(vs) == NULL) {
    return NULL;
  } else {
    if (strcmp(node_to_str(car(car(vs))), node_to_str(k)) == 0) {
      return car(vs);
    } else {
      return assoc(k, cdr(vs));
    }
  }
}

int main(void)
{
  const char s1[][MAXSTR] = { "hoge", "hage", "hige" };
  const char s2[][MAXSTR] = { "10", "20", "30" };
  node_t vs = mkassoc(list(s1, 3), list(s2, 3));

  node_t k = str_to_node("hage");
  node_t r = assoc(k, vs);
  printf("car(assoc(\"hage\", vs)) = %s\n", node_to_str(car(r)));
  printf("cdr(assoc(\"hage\", vs)) = %s\n", node_to_str(cdr(r)));

  free(vs);
  free(k);
  free(r);

  return (0);
}
car(assoc("hage", vs)) = hage
cdr(assoc("hage", vs)) = 20

Common Lisp(SBCL 1.4.16)

あくまで参考.ドット対はクロージャで実現.オリジナルと区別するため,s_cons s_car s_cdr s_atom s_listの名前で定義.空リストNULLはNILを使用.

;;;; Cons cells are created by using lambda closure.
;;;; All of atoms are string and the null value is NIL.
(defun s_cons (x y) (lambda (f) (funcall f x y)))
(defun s_car (c) (funcall c (lambda (x y) x)))
(defun s_cdr (c) (funcall c (lambda (x y) y)))
(defun s_atom (s) (and (not (functionp s)) (not (equal s NIL))))
(defun s_list (s) (if (null s) NIL (s_cons (car s) (s_list (cdr s)))))

利用例は次の通り.

(defun s_mkassoc (a b)
  (if (or (equal a NIL) (equal b NIL)) NIL
      (s_cons (s_cons  (s_car a) (s_car b))
              (s_mkassoc (s_cdr a) (s_cdr b)))))

(defun s_assoc (k vs)
  (if (equal vs NIL) NIL
      (if (equal (s_car (s_car vs)) k)
          (s_car vs)
          (s_assoc k (s_cdr vs)))))
* (defparameter vs
    (s_mkassoc (s_list '("hoge" "hage" "hige")) (s_list '("10" "20" "30"))))
VS
* (s_assoc "hage" vs)
#<CLOSURE (LAMBDA (F) :IN S_CONS) {50F3E645}>
* (s_car (s_assoc "hage" vs))
"hage"
* (s_cdr (s_assoc "hage" vs))
"20"

Ruby(CRuby 2.5.5)

ドット対は二要素の(凍結)配列で定義.空リストNULLはnilを使用.

#### Cons cells are created by using Array.
#### All of atoms are string and the null value is nil.
def cons(x, y) [x, y].freeze end
def car(s) s[0] end
def cdr(s) s[1] end
def atom(s) s.is_a?(String) || s == nil end
def list(s) s.size == 0 ? nil : cons(s[0], list(s[1..-1])) end

利用例は次の通り.

def mkassoc(a, b)
  if a == nil || b == nil then
    return nil
  else
    return cons(cons(car(a), car(b)), mkassoc(cdr(a), cdr(b)))
  end
end

def assoc(k, vs)
  if vs == nil then
    return nil
  else
    if car(car(vs)) == k then
      return car(vs)
    else
      return assoc(k, cdr(vs))
    end
  end
end
>> vs = mkassoc(list(["hoge", "hage", "hige"]), list(["10", "20", "30"]))
=> [["hoge", "10"], [["hage", "20"], [["hige", "30"], nil]]]
>> assoc("hage", vs)
=> ["hage", "20"]
>> car(assoc("hage", vs))
=> "hage"
>> cdr(assoc("hage", vs))
=> "20"

JavaScript (Node.js 10.21)

ドット対は二要素の(凍結)配列で定義.空リストNULLはnullを使用.

//// Cons cells are created by using Array.
//// All of atoms are string and the null value is null.
function cons(x, y) { return Object.freeze([x, y]); }
function car(s) { return s[0]; }
function cdr(s) { return s[1]; }
function atom(s) { return typeof s == 'string' || s == null; }
function list(s) { return s.length == 0 ? null : cons(s[0], list(s.slice(1))); }

利用例は次の通り.

function mkassoc(a, b) {
  return a == null || b == null
         ? null
         : cons(cons(car(a), car(b)), mkassoc(cdr(a), cdr(b)));
}

function assoc(k, vs) {
  if (vs == null) {
    return null;
  } else {
    if (car(car(vs)) == k) {
      return car(vs);
    } else {
      return assoc(k, cdr(vs));
    }
  }
}
> vs = mkassoc(list(["hoge", "hage", "hige"]), list(["10", "20", "30"]))
[ [ 'hoge', '10' ], [ [ 'hage', '20' ], [ [Array], null ] ] ]
> assoc("hage", vs)
[ 'hage', '20' ]
> car(assoc("hage", vs))
'hage'
> cdr(assoc("hage", vs))
'20'

備考

記事に関する補足

  • 参照用を想定していることもあり,エラーチェックもモジュール化もガーベジコレクションもなにそれおいしいの状態.実用のS式パーサとかは既にたくさんあるしなあ.
  • 現バージョンのlistだと,Common Lisp版を含めて『リストのリスト』が作れない…cons使えばいっか(いいかげん).

変更履歴

  • 2020-08-31:JavaScriptの実装例を追加
  • 2020-08-30:利用例を連想リスト実装に統一
  • 2020-08-30:Rubyの実装例を追加
  • 2020-08-30:初版公開(Python,C,Common Lisp)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

配列の使い方(高卒の備忘録)

はじめに

個人的な配列についてのまとめ。

配列の定義

array = []

array1 = [1, 2, 3, 4, 5]

array2 = ["A", "B", "C"]

array3 = (1..5).to_a
=> [1, 2, 3, 4, 5]

array4 = ("a".."c").to_a
=> [a, b, c]

配列に要素を追加

array = [1, 2, 3]

## 先頭に追加
array.unshift(10)
p array
=> [10, 1, 2, 3]

## 最後に要素を追加
array << 10
p array
=> [1, 2, 3, 10]

array.push(10)
p array
=> [1, 2, 3, 10]

## 指定した位置に要素の追加
array.insert(2, 5)
p array
=> [1, 2, 5, 3]

insertメソッドは指定位置に追加できるため便利。

配列の要素を削除

array = [1, 2, 3, 4, 5]

## 指定した要素の削除
array.delete(4)
p array
=> [1, 2, 3, 5]

## 先頭の要素を削除
array.shift
p array
=> [2, 3, 4, 5]

## 最後の要素を削除
array.pop
p array
=> [1, 2, 3, 4]

## 指定した位置の要素を削除
array.delete_at(2)
p array
=> [1, 2, 4, 5]

## 指定した範囲の要素の削除
array.slice!(1, 3) 
p array
=> [1, 5]

## trueの要素のみ削除
array.select! { |n| n % 2 == 0 }
p array
=> [2, 4]

## falseの要素のみ削除
array.reject! { |n| n % 2 == 0 }
p array
=> [1, 3, 5]

配列の出力

array = [1, 2, 3, 4, 5, 6, 7]

## 指定した位置の出力
puts array[0]
=> 1

puts array[5]
=> 6

## 指定した範囲の出力
puts array.slice(3, 4).join
=> 4567

## trueの最初の要素のみ出力
puts array.find { |n| n % 3 == 0 }
=> 3

## trueの最初の要素の位置を出力
puts array.find_index { |n| n % 3 == 0 }
=> 2

## trueの要素のみ出力
puts array.select { |n| n % 2 == 0 }.join
=> 246

## falseの要素のみ出力
puts array.reject { |n| n % 2 == 0 }.join
=> 1357

## false手前の要素を出力
puts array.take_while { |n| n < 5 }.join
=> 1234

## false以降の要素を出力
puts array.drop_while { |n| n < 5 }.join
=> 567

終わりに

基本的なことはこれでできると思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

配列の使い方(個人的な備忘録)

はじめに

個人的な配列についてのまとめ。

配列の定義

array = []

array1 = [1, 2, 3, 4, 5]

array2 = ["A", "B", "C"]

array3 = (1..5).to_a
=> [1, 2, 3, 4, 5]

array4 = ("a".."c").to_a
=> [a, b, c]

配列に要素を追加

array = [1, 2, 3]

## 先頭に追加
array.unshift(10)
p array
=> [10, 1, 2, 3]

## 最後に要素を追加
array << 10
p array
=> [1, 2, 3, 10]

array.push(10)
p array
=> [1, 2, 3, 10]

## 指定した位置に要素の追加
array.insert(2, 5)
p array
=> [1, 2, 5, 3]

insertメソッドは指定位置に追加できるため便利。

配列の要素を削除

array = [1, 2, 3, 4, 5]

## 指定した要素の削除
array.delete(4)
p array
=> [1, 2, 3, 5]

## 先頭の要素を削除
array.shift
p array
=> [2, 3, 4, 5]

## 最後の要素を削除
array.pop
p array
=> [1, 2, 3, 4]

## 指定した位置の要素を削除
array.delete_at(2)
p array
=> [1, 2, 4, 5]

## 指定した範囲の要素の削除
array.slice!(1, 3) 
p array
=> [1, 5]

## trueの要素のみ削除
array.select! { |n| n % 2 == 0 }
p array
=> [2, 4]

## falseの要素のみ削除
array.reject! { |n| n % 2 == 0 }
p array
=> [1, 3, 5]

配列の出力

array = [1, 2, 3, 4, 5, 6, 7]

## 指定した位置の出力
puts array[0]
=> 1

puts array[5]
=> 6

## 指定した範囲の出力
puts array.slice(3, 4).join
=> 4567

## trueの最初の要素のみ出力
puts array.find { |n| n % 3 == 0 }
=> 3

## trueの最初の要素の位置を出力
puts array.find_index { |n| n % 3 == 0 }
=> 2

## trueの要素のみ出力
puts array.select { |n| n % 2 == 0 }.join
=> 246

## falseの要素のみ出力
puts array.reject { |n| n % 2 == 0 }.join
=> 1357

## false手前の要素を出力
puts array.take_while { |n| n < 5 }.join
=> 1234

## false以降の要素を出力
puts array.drop_while { |n| n < 5 }.join
=> 567

終わりに

基本的なことはこれでできると思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Aizu Online Judge

この記事は、Aizu Online Judgeに取り組む中で勉強したこと等を忘れないようにするため、備忘録として作成するもの。

gets(文字列の入力を受け付ける)

name = gets
#Taroと入力し、エンター
#=>"Taro\n"
name = gets.chomp
#Taroと入力し、エンター
#=>"Taro"
number = gets.to_i
#1と入力
#=>1 

getsは文字列

join (配列の連結)

配列を連結して1つの文字列として返す

[1,2,3].join  
#"abc"
[1,2,3].join(" ")
#"a b c"
[1,2,3].join("+")
#"1+2+3"

繰り返し

times

1000.times do
  puts "Hello World"
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

そこらへんにいるフリーターがdevise使ってみた。

どうも、

未経験からエンジニアを目指しているフリーターです。

今回は初心者でも簡単に、

ゼロからユーザー管理機能を作れることで有名なgem

devise

について、

ところどころ解説をはさみながら、

簡単に紹介させてもらいたいと思います。

まず最初はrailsアプリを作りましょう

rails _6.0.0_ new (ご自身の作りたいアプリ名) -d mysql

(最後の-dはオプションなのでいらない人はつけなくて大丈夫です)

インストールが終わったら、今作成したフォルダに移りましょう

ターミナルを開き以下のコマンドを実行してください

% cd  (ご自身が作成したアプリ名)

とりあえずデータを入れるためのデータベースを作ります。

ターミナルを開き以下のコマンドを実行してください

% rails db:create

次はdeviceのジェムをGemfileにて追加していきます

gem 'devise'

Gemfileにて追加したら忘れずに

bundle installをしてください!!
(rails sで起動も!!)

続いて、ターミナルを開いた状態で
次のコマンドを打ってください

rail g devise:install

このコマンドによりdeviceが始動し始めます
個人的な感想としてはこのコマンド打った時が一番気持ちいです笑

コントローラーも忘れずに作成します。

% rails g devise:controllers users

このコマンドはdeviceのユーザー関係のコントローラーを
一気に作成してくれます

コレによりuserのマイグレーションファイルが生成されるので

送り出す工程を忘れてはいけません。

rake db:migrate

そしてこのコマンドです

rails g devise:views

device関係のviewを全部一気に
作ってくれます!!

僕最初コレ知らなくて、

全部自分で書いてしまってました、、、

もうあの経験はしなくていいんだ!

と考えると心が安らぎます。

以上でdevice関連のコマンド紹介は終わりです!

こんなに簡単に誰もがユーザー管理機能作れちゃうなんて、、、

gemの能力恐るべし、、

ユーザー登録機能に、sns認証を入れたい!

という方は

https://developers.facebook.com/

というところにアクセスして

色々と登録した上で、

gem 'omniauth-facebook'

というgemを使うと

Facebookでの認証が可能になります!

(他にもやることあります、、)

ぜひこの機会に一度調べてみてはどうでしょう!!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rubyで高速素因数分解したい (ABC177E)

参考

https://atcoder.jp/contests/abc177/editorial/82
(これを読んでからじゃないと記事が意味不明だと思います)

本題

A以下の数がたくさん与えられて、それらを素因数分解したいとき、
エラトステネスの篩を行って、ついでにふるい落とした数を入れておくと、
素因数分解のときに楽

cache = {key(その値) => value(keyをふるい落とした最小の素因数) }

みたいなcacheを作ると楽だよという話です。

例) 100を素因数分解する場合

cache[100] 
#=> 2 = 2で割れる
cache[100/2]
#=> 2 = 2で割れる
cache[50/2] 
#=> 5 = 5で割れる
cache[25/5] 
#=> 5 = 5で割れる

#∴ 100 は 2で2回、5で2回割れる

このcacheを作っておけば、素因数分解をO(logN)でできるねという話です。
今回はこれを用いて素因数分解を高速にできるクラスを作ってみたので、
既存のInteger#prime_division との性能比較をしたいと思います。

作ったもの

https://github.com/k-karen/ruby-samples/blob/master/sieve/prime_div_with_sieve.rb

ソースコード
# エラトステネスの篩で素数列挙して高速に素因数分解したい!
# ref: https://atcoder.jp/contests/abc177/editorial/82
class PrimeDivWithSieve
  def initialize(n)
    @sieve = [] # nまでの素数を入れる
    @min_div = {} # keyの値の最小の素因数を入れる
    # 他を篩落とし得る素数はsqrtを上限にできる
    (2..Math.sqrt(n).floor).each do |i|
      next if @min_div[i] # ここに値が入ってる = ふるい落とされている
      @sieve << i # ふるい落とされずに来たらそいつは素数

      sieve_target = i * i
      while sieve_target <= n do
        @min_div[sieve_target] ||= i
        sieve_target += i
      end
    end
    (Math.sqrt(n).floor.next..n).each do |i|
      next if @min_div[i]
      @sieve << i
    end
  end

  # Integer#prime_division と同じ値を返すようにする
  # https://docs.ruby-lang.org/ja/latest/method/Integer/i/prime_division.html
  def prime_division(num)
    return [[num, 1]] if !@min_div[num] # 素数のときすぐ返す

    return_array = [] # [[a, x], [b, y]] <=> num = a^x * b^y
    while num > 1 do
      prime = @min_div[num] # 最小の素因数, nil => numが素数
      break return_array.push([num, 1]) if !prime

      div_total = 0
      while num % prime == 0 do
        num /= prime
        div_total += 1
      end
      return_array.push([prime, div_total])
    end

    return_array
  end

  def prime_list
    @sieve
  end
end

性能比較

(テストコード全文)[https://github.com/k-karen/ruby-samples/blob/master/sieve/bench_prime_division.rb]

N = 1_000_000
times = N/25 # テスト件数
TESTCASES = (1..N).to_a.sample(times)
require 'prime'

ans1 = []
ans2 = []
Benchmark.bm 10 do |r|
  r.report 'MyDivsor' do
    divisor = PrimeDivWithSieve.new(N)
    TESTCASES.each do |i|
      ans1.push(divisor.prime_division(i))
    end
  end

  r.report 'PrimeDiv' do
    TESTCASES.each do |i|
      ans2.push(i.prime_division)
    end
  end
end
# times = N/25 (40,000件)
# Result
# user     system      total        real
# MyDivsor     0.875262   0.032392   0.907654 (  0.926605)
# PrimeDiv     0.849263   0.012468   0.861731 (  0.879886)

# times = N/2 (500,000件)
# Result
# user     system      total        real
# MyDivsor     1.659268   0.058786   1.718054 (  1.758668)
# PrimeDiv    10.787444   0.118755  10.906199 ( 11.071594)

件数少ないと微妙ですが、件数増えると篩利用してるほうが早そうです。

ABC177E

https://atcoder.jp/contests/abc177/submissions/16390851
これで勝つると思ってsubmitしたんですが、1つTLEがどうしても消えませんでした。
今回は何回割れるかという情報がいらないので、
もう篩作るときにその値が持ってる素因数をメモしておけばいいじゃんということになりました。
例) 100 => [2,5], 99 => [3, 11]

https://atcoder.jp/contests/abc177/submissions/16391235
これで通りました。
(今回の高速素因数分解とは違うろじっくなのでおまけ程度にどうぞ)

nまでの各値の素因数を計算(with篩)
https://github.com/k-karen/ruby-samples/blob/master/sieve/enum_elments.rb

ソースコード
# 素因数だけをnまで計算する
class EnumElements
  def initialize(n)
    @sieve = []
    @elements = {}
    (2..n).each do |i|
      next if @elements[i]
      @sieve << i
      @elements[i] = [i]

      sieve_target = i * 2
      while sieve_target <= n do
        if @elements[sieve_target]
          @elements[sieve_target].push(i)
        else
          @elements[sieve_target] = [i]
        end
        sieve_target += i
      end
    end
  end

  def elements(num)
    @elements[num] || []
  end
end

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby で解く AtCoder ABC177 D UnionFind

はじめに

AtCoder Problems の Recommendation を利用して、過去の問題を解いています。
AtCoder さん、AtCoder Problems さん、ありがとうございます。

今回のお題

AtCoder Beginner Contest D - Friends
Difficulty: 676

今回のテーマ、UnionFind

典型問題の B - Union Find - AtCoder の応用です。

Ruby

ruby.rb
class UnionFind
  def initialize(n)
    @parents = Array.new(n, -1)
  end
  def find(x)
    @parents[x] < 0 ? x : @parents[x] = find(@parents[x])
  end
  def parents
    @parents
  end
  def union(x, y)
    x = find(x)
    y = find(y)
    return if x == y
    if @parents[x] > @parents[y]
      x, y = y, x
    end
    @parents[x] += @parents[y]
    @parents[y] = x
  end  
end

n, m = gets.split.map(&:to_i)
u = UnionFind.new(n)
m.times do
  a, b = gets.split.map(&:to_i)
  u.union(a - 1, b - 1)
end
puts -u.parents.min
sub.rb
    @parents = Array.new(n, -1)

    @parents[x] += @parents[y]

配列@parentsに初期値-1を代入します。
次に、ペアとなった配列の初期値-1を加算します。
これを繰り返すことで、ペアの集合の要素数を取得することができます。

sub.rb
@parents = [-3, 0, -2, 2, 0]

入力例 1の場合、マイナスの数値を見ますと、32のグループに分かれることが分かります。
よって出力は、グループの要素が大きい方の3になります。

Ruby
コード長 (Byte) 548
実行時間 (ms) 260
メモリ (KB) 15824

まとめ

  • ABC 177 D を解いた
  • Ruby に詳しくなった

参照したサイト
AtCoder Beginner Contest 177 参戦記

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初投稿

どうも :shamrock:

エンジニア就職を目指している20代です

現在はTechCamp82期生として最終課題に取り組んでいます

就職までの学習を記録します

既存の内容も多く投稿することになると思います:airplane:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby問題⑦

最終回です。

問題

3つの整数a b cが与えられた場合、bまたはcがaとの差が1で
かつbとcとの数値の差が2以上の場合はTrue。
それ以外はFalse
と出力するメソッドを作りましょう。

出力例:

close_far(1, 2, 10) → True
close_far(1, 2, 3) → False
close_far(4, 1, 3) → True

ヒント

返り値を整数に変換する際はabsメソッドを使いましょう。

abs

対象となる数値に対して「abs」メソッドを実行すると絶対値を取得することができます。すなわち正の数の場合はそのままですが負の数の場合は符号を取って正の数にした数値が取得できます。

実際の使い方は次のようになります。

num = 5.abs
#=> 5

num = (-5).abs
#=> 5




模範回答
def close_far(a,b,c)
  x = (a-b).abs
  y = (a-c).abs
  z = (b-c).abs

  if x == 1 && z >= 2
    puts "True"
  elsif y == 1 && z >= 2
    puts "True"
  else
    puts "False"
  end
end





今回、解説はなかったですが、答えを見れば理解ができる内容でした。
a-bなどの差を代入するのがポイントですね。
思いつかなかったです。
これは、正解に行き着きたかった・・・。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

if,else問題

問題

3つの整数a b cが与えられた場合、bまたはcがaとの差が1で
かつbとcとの数値の差が2以上の場合はTrue。
それ以外はFalse
と出力するメソッドを作りましょう。

出力例:

close_far(1, 2, 10) → True
close_far(1, 2, 3) → False
close_far(4, 1, 3) → True

ヒント

返り値を整数に変換する際はabsメソッドを使いましょう。

abs

対象となる数値に対して「abs」メソッドを実行すると絶対値を取得することができます。すなわち正の数の場合はそのままですが負の数の場合は符号を取って正の数にした数値が取得できます。

実際の使い方は次のようになります。

num = 5.abs
#=> 5

num = (-5).abs
#=> 5




模範回答
def close_far(a,b,c)
  x = (a-b).abs
  y = (a-c).abs
  z = (b-c).abs

  if x == 1 && z >= 2
    puts "True"
  elsif y == 1 && z >= 2
    puts "True"
  else
    puts "False"
  end
end





今回、解説はなかったですが、答えを見れば理解ができる内容でした。
a-bなどの差を代入するのがポイントですね。
思いつかなかったです。
これは、正解に行き着きたかった・・・。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ActiveRecord::NotNullViolation in Deviseエラー

【概要】

1.結論

2.ActiveRecord::NotNullViolationtとは何か

3.なぜActiveRecord::NotNullViolation in Deviseになるのか

4.どのように解決するか

5.補足

1.結論

db/migrate/""""devise_create""""".rbに
記載してある"t.string password(またはpassword_confirmation)"の記載を削除する!


2.ActiveRecord::NotNullViolationtとは何か

スクリーンショット 2020-08-29 20.47.37.png

この意味は、「DBの規則上、空欄(NULL)にしてはいけない項目がデータで保存されかけましたよ!そんなことしちゃいけませんよ!」という機械からのご指摘です!


3.なぜActiveRecord::NotNullViolation in Deviseになるのか

2.と掛け合わせると、「デバイスでDBの規則上、空欄(NULL)にしてはいけない項目がデータで保存されかけましたよ!コントローラーで保存して登録されたときだよ!」と行っています。

なぜこのようなことになるかというと、gem'devise'がわざわざpasswordを作ってくれたのに、
被せて作ろうとしているのでどっちのpasswordがいいかわからずNULLになったと思われます!

gem'devise'というものはpasswordとそれに対するpassword_confirmationを作ってくれるgemです!

なので

db/migrate/""""_devise_create_""""".rb
t.string :password null:false"(password_confirmation)

をプログラムしてカラムを作成する必要はないんです!


4.どのように解決するか

db/migrate/""""_devise_create_""""".rb
t.string password,  null:false"
(またはpassword_confirmation)

と記載されていると思うので削除しましょう!

5.補足

ちなみにgem'devise'にはpasswordに対してもう一つ付け加えれれている機能があります!

それはバリデーションです!

6文字以上にしなければ、入力ができないように制限が既に機能として備わっているので、

model/user
validates :password, length { minimum: 5 }

を記載する必要がなくなります!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

クラスの情報を継承したクラスの作り方

内容

複数のクラスに同じメソッドを定義したい場合、それぞれのクラス全てにそのメソッドを定義すると、同じ記述を何度も繰り返す事になってしまいます。
(例1)
クラス1  クラス2   クラス3
メソッドA メソッドA  メソッドA
メソッドB メソッドC  メソッドD
複数のクラスが同じメソッドを持つときにクラスが増えれば増えるほどコード量が多くなり、管理も難しくなります。これを防ぐためにクラスの継承について学んでいきましょう。

クラスの継承とは

あるクラスに定義されたメソッドを、別の新規クラスで利用できるようにした上でクラスを定義することを継承と言います。

クラスの継承には、親クラスと子クラスの関係があります。元となるクラスを親クラス、親クラスのメソッドを引き継ぎ新しく作成するクラスを子クラスと呼びます。
image.png
パトカーやトラックの上位概念である「車」のクラスを作り、そこへ共通の特徴を定義しておきます。車の特徴(親クラス)を継承することで、パトカー(子クラス)とトラック(子クラス)に車の特徴を記述する必要がなくなります。結果、パトカーとトラックだけの特徴を書くだけで済む上、それぞれの特徴が分かりやすくなっています。

クラスの継承をする際には、クラスを宣言する際に「<」を用いて、以下のように記述します。

class 子クラス名 < 親クラス名
end

それでは、先ほどの車の例を実際にクラスの継承を用いたコードで書いてみます。
まずは親となるクラスを定義します。

Carクラス(親クラス)

class Car
  def speed_up
    puts "加速します"
  end

  def speed_down
    puts "減速します"
  end

  def horn
    puts "プップー"
  end
end

親クラスには、車が持つ共通の動作を定義しています。
次に子クラスをそれぞれ定義します。今回はパトカーとトラックをそれぞれPatrolCar, TruckCarとして定義します。

PatrolCarクラス(子クラス)

class PatrolCar < Car  # クラスの継承
  def siren
    puts "ピーポーピーポー"
  end
end

TruckCarクラス(子クラス)

class TruckCar < Car  # クラスの継承
  def carry
    puts "荷物を載せます運びます"
  end
end

親クラスに共通のメソッドを定義することで、子クラスのコード量が少なくなり見やすくなっています。また、これは継承を使う大きなメリットですが、親クラスで定義された共通のメソッドを変更するだけで、変更を子クラスへ容易に反映できることが上記のコードから分かります。

最後に

クラスの継承を使うことによって共通のメソッドを繰り返し書くことなくスッキリとしたコードを書けるので皆さん書いてみてください!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む