下級エンジニアの綴

新しく発見したことを綴っていこうと思っています。夢はでっかく上級エンジニアになることです。

linux(centos)の公開鍵を置いているサーバーにsshが出来なくて嵌まったのでメモ。

今回は公開鍵を置いているサーバーにsshが出来なくて嵌まって調べたメモになります。

状況

  • .sshフォルダの権限は700で所有者はログインユーザー
  • authorized_keysの権限は600で所有者はログインユーザー
  • 公開鍵と秘密鍵は対になっている
  • タイポもしていない

この状況でsshが出来ませんでした。

理由

view /var/log/secure

ここに

User your_username not allowed because account is locked

と書かれていました。

↑のログはssh_configの設定でパスワードの設定をしてないユーザーがsshしようとする時に出るみたいです(アクセスを弾いちゃいます)。

view /etc/shadow

↑を見るとUSERNAME:の次に「!!」と書いて有る場合は lockされているみたいです。(パスワードが設定されていると「!!」ではなくランダムの文字列になっているみたいです。

解決

passwd user_name

↑のようにloginユーザーのpasswordを設定してあげるとsshが出来るようになりました。

参考URL

tkuchiki.hatenablog.com

Rspecでインスタンスメソッドのテストに苦労したのでメモ

今回はRspecでメソッドのテストをしたかったのですが、メソッド内で定義しているメソッド先の処理のテストは記述したくなかったので、それを解決したメモになります。

rubyのコード

# 今回テストしたかったのはTest1のexecuteメソッドになります
Class Test1
  def self.execute(test_params)
    Test2.execute(test_params)
    Test3.new(test_params).execute(test_params) # ←こいつが一番の曲者でした
  end
end

Class Test2
  def self.execute(test_params)
    p test_params + 'test2'
  end
end

Class Test3
  def initialize(test_params)
    @test = test_params + 'test3'
  end

  def execute(test_params)
    p @test + test_params + 'test3'
  end
end

テストコード

require 'rails_helper'

RSpec.describe Test1 do
  describe 'テスト1'
    it 'interfaceのテスト'
      test = double('Test3:00000000')
      allow(Test2).to receive(:execute).and_return(true)
      allow(Test3).to receive(:new).and_return(test)
      allow(Test3.new("")).to receive(:execute).and_return(true)
      Test1.execute(anything)
    end
  end
end

Test3のテストコードですが、。最初は下記のように記述していました。

allow(Test3).to receive(:new)
allow(Test3.new("")).to receive(:execute)

↑だとexecuteを呼ぶ時にno method errorがでます。

Test3で定義しているexecuteはクラスメソッドではなくインスタンスメソッドなので、インスタンスにメソッドを定義しないとエラーが出てしましました。

なので、

test = double('Test3:00000000')

↑でインスタンスを定義して

allow(Test3).to receive(:new).and_return(test)

↑でnewした時の戻り値にインスタンスを返えすようにします。

allow(Test3.new("")).to receive(:execute)

↑でインスタンスにexecuteメソッドを定義することによって

Class Test1
  def self.execute(test_params)
    Test2.execute(test_params)
    Test3.new(test_params).execute(test_params) # ←こいつのテストが通るようになる
  end
end

Test3のテストが通るようになります。(解決するまでにめっちゃ時間がかかりました。

参考URL

qiita.com

docker-composeでRAILS_ENVを切り替えて実行する方法を調べたのでメモ

今回はrspecを実行したいけど、わざわざdockerのコンテナの中に入って実行するのはイケてないと思い、調べたそのメモになります。

docker-compose exec test bash
RAILS_ENV=test_docker rake db:migrate:reset
RAILS_ENV=test_docker rspec

↑のコマンドを叩きたくないので

docker-compose exec test RAILS_ENV=test_docker rake db:migrate:reset
docker-compose exec test RAILS_ENV=test_docker rspec
## rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:262: starting container process caused "exec: \"RAILS_ENV=test_docker\": executable file not found in $PATH"

と叩くと↑のようなエラーが出て上手く動きませんでした。

なので、

docker-compose run -e RAILS_ENV=test_docker test rake db:migrate:reset
docker-compose run -e RAILS_ENV=test_docker test rspec

↑のようにrunする時に-eをつけると、envの指定が出来たので、上手く動きました。

ログインするというより、使い捨てのインスタンスを立てるって感じですね。

参考URL

blog.codeship.com

railsのhash#tryでちょっと躓いたのでメモ

railsでhashにtryをかけているとエラーが出たので、その時に調べた内容をメモ。(一度先輩に教えてもらった気がするのですが完全に忘れてましたorz

本題

この書き方だとhashにkeyが存在する時は問題無いのですが、

{ name: 'yantera' }.try(:fetch, :name)
# => "yantera"

hashにkeyが存在しない時はerrorになります

{}.try(:fetch, :name)
# KeyError: key not found: :name
# from /usr/local/bundle/gems/activesupport-4.1.8/lib/active_support/core_ext/object/try.rb:45:in `fetch'

解決するには以下の2パターンがありました。

  • 自分でdefault値を設定する
    • 同時に好きな値を定義できる
  • []メソッドを設定する
    • メリットはシンプルに書ける
{}.try(:fetch, :name, nil)
{}.try(:fetch, :name, 1)
{}.try(:fetch, :name, 'yantera')
# => nil
# => 1
# => "yantera"

{}.try(:[], :name)
# => nil

参考リンク

qiita.com

小ネタ

  • tryの中身はこのようになってます
    • aにはtryを呼ぶときの引数が配列で入って、bにはブロック文が入ります。
def try(*a, &b)
  if a.empty? && block_given?
    yield self
  else
    public_send(*a, &b) if respond_to?(a.first)
  end
end

要は下のように呼ぶと

{}.try(:fetch, :test, 1) do
  p 'test'
end
# a
# => [:fetch, :test, 1]
# b
# => #<Proc:0x007f5b9bf15f88@(pry):2>

が入ります。

  • if文を見るとaがemptyでかつブロック文が投げられている時、自分で作成したブロックぶんが呼ばれるという内容ですね。
{}.try() do
  p 'test'
end
# => 'test'

というように使えます。(用途はわからないですが)

続いてelseの方ですが

def try(*a, &b)
  if a.empty? && block_given?
    yield self
  else
    public_send(*a, &b) if respond_to?(a.first)
  end
end

self(Hash)にa.firstのメソッドがあれば実行されるので

{}.try(:fetch, :test, 1) do
  p 'test'
end
# a
# => [:fetch, :test, 1]

この場合fetchが呼ばれます。fetchメソッドははhashのkeyをとって実行するので、

{}.fetch(:test, 1)
# => 1
{}.fetch(:test)
# KeyError: key not found: :test

の形になり、hashの中にkeyが存在していると、そのkeyの値が返りますが、デフォルト値を定義していないとKeyErrorになります。

[]はhashからkeyを取るメソッドなので

{}.[] :test
# => nil

という風にかけます。

また、

hoge = {}
hoge.[] :test
# => nil

hoge.default = 1
hoge.[] :test
# => 1

hashにdefault値を設定できるみたいで、指定しなければnilが返りますが、指定すると好きな値に出来るみたいでした。

rubyの特異メソッドのprivateについて気になったから調べたのでメモ

特異メソッドでprivateなメソッドを呼ぶ方法

  • sendを使う
    • privateの特異メソッド、privateのインスタンスメソッドを関係なく呼べる
    • 最終手段な感じがするので、あまり推奨できないと思った
class A
  def self.hoge
    A.new.send(:fuga)
  end

  def self.aaa
    A.send(:bbb)
  end

  def self.bbb
    p 'bbb'
  end

  private

  def fuga
    p 'fuga'
  end

  private_class_method :bbb
end

A.hoge      # "fuga"
A.aaa       # "bbb"
A.new.fuga  # private method `fuga' called for #<A:0x007f3ac14fb2f0> (NoMethodError)
A.bbb       # private method `bbb' called for A:Class (NoMethodError)
  • private_class_methodを使う
    • 特異メソッドが少ない時はこちらを使用する
    • privateにしたいメソッドを定義した後にprivate_class_methodで定義する
class A
  def self.hogo
    fugo
  end

  def self.fugo
    p 'fugo'
  end

  private_class_method :fugo
end

A.hogo  # "fugo"
A.fugo  # private method `fugo' called for A:Class (NoMethodError)
  • class << selfを使う
    • 特異メソッドが多い時に使用する
    • 階層が1段多くなるがメソッドにclass << self~endまでに定義したメソッドが特異メソッドになる。
    • private以下に定義したメソッドは特異クラスのprivateメソッドになる
class A
  class << self
    def hoo
      foo
    end

    private

    def foo
      p 'foo'
    end
  end
end

A.hoo  # "foo"
A.foo  # private method `foo' called for A:Class (NoMethodError)

rubyの多次元hashで指定したkeyを削除する時、ActiveSupportのexceptを使うと便利だったのでメモ

require 'active_support'

h = { a: 1, b: 2, c: 3, d: { e: 4, f: { g: 5 }}}

p h.except(:a)      // {:b=>2, :c=>3, :d=>{:e=>4, :f=>{:g=>5}}
p h                 // {:a=>1, :b=>2, :c=>3, :d=>{:e=>4, :f=>{:g=>5}}}
p h[:d].except!(:f) // {:e=>4}
p h                 // {:a=>1, :b=>2, :c=>3, :d=>{:e=>4}}

!を付けると破壊的メソッドになります。
特定のkey以下のkeyを指定することも可能だったのでかなり汎用性が高いメソッドかなと思いました。

参考URL

qiita.com

go初心者が無名関数のクロージャについて学んだのでメモ

スターティングGo言語という本を読んでいるのですが、これは面白そうだなと思った機能があったのでメモ

package main
import "fmt"
func later() func(string) string { 
    // 1 つ 前 に 与え られ た 文字列 を 保存 する ため の 変数 
    var store string 
    // 引数 に 文字列 を とり 文字列 を 返す 関数 を 返す 
    return func( next string) string { 
        s := store store = next 
        return s 
    } 
} 
func main() {
    f := later() 
    fmt.Println(f("Golang")) // => "" 
    fmt.Println(f("is")) // => "Golang" 
    fmt.Println(f("awesome!")) // => "is"
}
a := 1
b := 2 // この変数だけクロージャから参照される
c := 3
return func() int{
    return b
}
package main

import "fmt"

func integers() func() int { 
    i := 0
    return func() int { 
        i += 1 
        return i 
    } 
} 

func main() { 
    ints := integers() 

    fmt.Println(ints()) // => "1" 
    fmt.Println(ints()) // => "2" 
    fmt.Println(ints()) // => "3" 

    otherInts := integers() 
    fmt.Println(otherInts()) // => "1" 

    fmt.Println(ints()) // => "4" 
    fmt.Println(ints()) // => "5" 

  // 初期化
    ints = integers() 

    fmt.Println(ints()) // => "1" 
    fmt.Println(ints()) // => "2" 
}

上手く使いこなせれると便利そうだなと思いました。

スターティングGo言語

スターティングGo言語