【UNIX】ファイルの所有者、所有グループについて入門的にまとめてみた

ファイルの所有者、所有グループについて入門的にまとめてみた。

概要

  • 所有者、所有グループとは
  • 現在の状態の確認
  • 変更方法

所有者、所有グループとは

  • ファイルやディレクトリには、owner(所有者)、group(所属グループ)、others(それ以外)が設定されている
  • ファイルのパーミッションは、それらの単位で設定することができる
  • 所有者を変更できるのは、スーパーユーザのみ
  • 新規ファイルまたはディレクトリを作成した場合は、所有者は現在のユーザー、所属グループは作成者の所属グループ

現在の状態の確認

$ ls -l
total 12
drwxrwxr-x 2 user001 group001 4096 Apr 19 09:37 rails_root
-rw-rw-r-- 1 user002 group002    6 Apr 20 06:22 hoge.html
  • user001, user002 がファイルのowner
  • group001,group002 がファイルのgroup

変更方法について

ownerの変更方法

以下の方法で変更が可能

$ chown user file
  • fileの所有者をuserに変更する

$ chown -R user hoge
  • hoge ディレクトリ内の所有者をすべてuserにする
$ chown usre:user-group file
  • fileの所有者をuser にし、グループをuser-groupにする

groupの変更方法

$ chgrp user-group file
  • fileのグループをuser-groupに変更する
  • 変更が可能なのは、そのファイルの所有者またはスーパーユーザのみ

$ chgrp -R user-group etc
  • etcディレクトリ内の所属グループをすべてuser-groupにする

【UNIX】groupについてあれこれ

概要

  • グループとは
  • グループの確認
  • グループの作成、修正、削除
  • グループへの追加、グループからの削除
  • グループの変更
  • 参考URL

グループとは

  • ユーザーを論理的にまとめているもの
  • ファイルやディレクトリが所属しているグループに与えられている権限は、そのグループに所属しているユーザーにも与えられる
  • ユーザーは複数のグループに所属することができる
  • メインのグループをプライマリグループ、イニシャルグループと呼ぶ
  • それ以外のグループをサブグループと呼ぶ
  • ユーザーが作成したファイル、ディレクトリは、そのユーザーのプライマリグループが設定される

グループの確認

自分の所属しているグループの確認

$ groups
ec2-user wheel

グループ一覧の確認

$ cat /etc/group
root:x:0:
bin:x:1:bin,daemon
daemon:x:2:bin,daemon
sys:x:3:bin,adm
adm:x:4:adm,daemon

表示の見方

wheel:x:10:ec2-user
  • wheel グループ名
  • x 暗号化されたパスワード
  • 10 グループID
  • foo,bar サブグループとして所属しているユーザーのアカウント。カンマ区切りで表示される。

グループの作成、削除、修正

グループの作成

$ groupadd グループ名

オプション

-g GID
  • 作成するグループのIDを指定できる
  • オプションを指定しない場合は、システムが指定する

グループの削除

$ groupdel グループ名
  • 指定したグループを削除する

グループの修正

$ groupmod [-g GID] [-n NEWGROUP] グループ名
  • グループの情報を変更する
  • -g GIDGIDにIDを変更する
  • -n NEWGROUPでグループの名前をNEWGEROUPに変更する

グループへの追加、グループからの削除

グループへの追加

方法は2種類ある

  • usermod
  • gpasswd

usermodの場合

$ usermod -G GROUPNAME USERNAME
  • usermodコマンドは、アカウント情報を変更できる
  • -Gオプションでグループの指定が可能
  • usermod コマンドの場合は、それまで所属したグループからは外れる

gpasswdの場合

$ gpasswd -a USERNAME GROPNAME
  • gpasswdコマンドで、グループの情報を変更できる
  • -a USERNAME で USERNAME をグループに追加する
  • それまで所属していたグループも残る

グループから削除

$ gpasswd -d USERNAME GROUPNAME
  • gpasswdに-dオプションを渡すことでグループから削除できる

グループの変更

以下の方法で指定したグループにログインが可能

$ newgrp グループ名
  • セッションを終了せずにグループを切り替える(グループIDを切り替える)
  • 一時的にグループを変えるときに実行する
  • サブグループとして所属しているグループには、パスワードなしでログインが可能
  • 所属していないグループにはパスワードが必要。
  • パスワードが設定されていないグループにはログインすることができない

参考URL

http://kazmax.zpp.jp/linux_beginner/etc_group.html
http://kazmax.zpp.jp/linux_beginner/lin1.htm
http://codezine.jp/unixdic/w/groupadd
http://www.linux-beginner.com/linux_kihon23.html
http://www.linux-beginner.com/linux_kihon24.html

【UNIX】user一覧の確認コマンド

以下のコマンドで確認できる

コマンド

$ less /etc/passwd  
ec2-user:x:500:500:EC2 Default User:/home/ec2-user:/bin/bash

表示の見方

  • ec2-user ユーザー名
  • x 暗号化されたパスワード
  • 500 ユーザーID
  • 500 グループID
  • EC2 Default User コメント。なければ表示されない
  • /home/ec2-user ユーザーのホームディレクトリ
  • /bin/bash ユーザーのログインシェル名

ユーザー名のみ抽出

覚えておくと割りと便利かも。

$ cut -d: -f1 /etc/passwd  
root
bin
daemon
adm
lp

GitHub Flow についてのまとめ

手順

  1. masterブランチは常にデプロイできるようにしておく
  2. 新しい作業をするときはmasterブランチから何をしているかわかりやすいブランチを作成する
  3. 作業をしたら作成したローカルリポジトリのブランチにコミットする
  4. 同名のブランチをGitHubのリモートリポジトリに作成し、定期的にpushする
  5. masterの差分が大きくなっている場合は、リモートのmasterをローカルのmaster にpullし、ローカルのmasterを作業ブランチにマージする
  6. フィードバックがほしい時は、Pull Requestを作成しやりとりする
  7. 作業を終わったら、GitHub上でmasterに対してPull Requestを出す。
  8. Pull Requestがmasterブランチにマージされたら、ただちにデプロイする

特徴

  • masterブランチを常にデプロイできるようにすること 小さい単位でデプロイする。こうすると大きなバグが複数入ることはない。小さいな単位のバグがはいるときは、そのコミットをrevertするか、修正したコミットを出して対応する。テストや継続的インテグレーションなどのアプローチが必須。

  • 新しい作業をするときはmasterブランチから何をしているかわかりやすいブランチを作成する 作業ブランチの名前をわかりやすいものにすることで、チームのメンバーがどのようなタスクを実施してるのかわかる。

  • 作業ブランチでのコミットの粒度を小さくする Pull Requestのレビュアーがわかるような粒度のコミットにすること。小さいコミットのほうがわかりやすし、レビュアーの負担にもならない。

  • 定期的にpushする pushはローカルと同じ名前のリモートリポジトリにpush する。他のメンバーがコードを見れるようになる。また、コードのバックアップにもなる。

  • Pull Requestを使う masterへのマージ依頼だけではなく、フィードバックがほしい時にPull Requestを出す。そうすれば間違いに早く気づく。マージではないPull Requestを送るときは、[WIP]をつけること。そうすれば間違ってマージするのを防げる。

参考URL

https://gist.github.com/Gab-km/3705015
http://www.atmarkit.co.jp/ait/articles/1401/21/news042.html

【翻訳】そう、コントローラのテストを書くべきなのです!

Rspecでcontroller のテストを書くべきなのかと思うことがあると思います。

Everyday Rails - RSpecによるRailsテスト入門の116ページに以下の記述がありました。

“なぜコントローラをテストするのか? コントローラのメソッドを個別にテストするのにはちゃんとした理由がいくつかあります。 コントローラもメソッドを持ったクラスである。 この点についてはPiotr Solnicaが素晴らしいブログ記事を書いています。そしてRailsアプリケーションにおいて、コントローラはかなり重要なクラス(とメソッド)です。なので、スペック的にモデルと平等に扱うのは良い考えです。”

抜粋:: Aaron Sumner, Junichi Ito (伊藤淳一), AKIMOTO Toshiharu and Shinkou Gyo(魚振江). “Everyday Rails - RSpecによるRailsテスト入門”。 iBooks.

自分のために翻訳してみたので、載せておきます。
原文はこちらにあります。
Yes, You Should Write Controller Tests!

そう、コントローラのテストを書くべきなのです!

コントローラのテストをコーディングすることに意味がないと主張する人がいるのは本当に驚くべきことです。 おそらくもっともありがちなのは、アクションのテストは、ビューが適切に表示されるかのチェックとともに承認テストのなかでカバーされるという主張です。 正しいかといえば、間違っています!遅い承認テストですべての可能性を網羅したコントローラのアクションのシナリオをカバーできるといいはるつもりでしょうか? 例えば、起こるべきすべてのリダイレクトが承認テストの中でテストできると言い張るつもりなのでしょうか? また、承認テストで、すべての無効なリクエストはチェックされているのでしょうか? 存在するコントローラを完全にテストするために、一連の承認テストに27時間13分かけるとでもいうつもりですか? それでは、きっと、あなたの一連の承認テストは多少速くても、おそらくは「都合のよいシナリオ」しかカバーしない、…基本的に、テストがカバーすべき範囲をたくさん外すということになります。

コントローラについての単純な事実

コントローラについて、単純な事実があります。それは複数のメソッドをもつ一つのクラスだということです。もう一度言います。そうなんです、複数のメソッドをもつ一つのクラスなのです。 コントローラーはテストされるべきなのですし、全てのメソッド(アクション)がテストでカバーされるべきなのです。
なぜかといえば、アプリケーションの他のクラスでテストを書くのと同じ理由です。コードが想定通りに動くのか我々は確認したいものです。また、テストをする時には、コントローラーを薄くしておけばずっと楽になります。もし、コントローラ用にテストをコーディングするのが大した作業でないなら、おそらくそれは良いコントローラなのでしょう。 もし、mockのなかで溺れそうになるなら、多分、コントローラをリファクタリングする必要があるでしょう。

ここに、サンプルのcreateアクションをもったユーザーコントローラの例を示します:

class UsersController < ApplicationController
  before_filter :load_group

  rescue_from ActiveRecord::RecordNotFound do
    render :not_found
  end

  def create
    @user = @group.users.create(params[:user])

    if @user.persisted?
      redirect users_path, :notice => ‘User created!’
    else
      render :new
    end
  end

  private

  def load_group
    @group = Group.find(params[:group_id])
  end
end

ご覧のとおり、before_filter においてグループオブジェクトをロードし、そのオブジェクトを使って新しいユーザーを作成します。 非常に、非常に、単純なのです。もし、このコントローラ向けの承認テストをかけと言われても、多分グループが見つからないケースをカバーしたものはできないと断言できます。結局はみんな、普通は、楽観的なシナリオにもとづいて承認テストを書くものです。 もし、すべてのケースをカバーしようとすれば、たぶん納期に間に合わないことでしょう;)

しかし、すべてのpathをカバーすればよいだけではありません!コードの質についてもなのです。 上の例を見てもおそらく、コードのにおいなどしないでしょう。なので、createアクション向けのspecを書いてみましょう:

describe UsersController do
  describe "#create" do
    subject { post :create, :group_id => group_id, :user => attributes }

    let(:group_id) { mock(‘group_id’) }
    let(:group)    { mock(‘group’) }
    let(:user)     { mock(‘user’) }
    let(:users)    { mock(‘users’) }

    before do
      Group.should_receive(:find).with(group_id).and_return(group)
      group.should_receive(:users).and_return(users)
      users.should_receive(:create).with(attributes).and_return(user)
    end

    context ‘when attributes are valid’ do
      it ‘saves the user and redirects to the index page’ do
        user.should_receive(:persisted?).and_return(true)
        subject.should redirect_to(:users)
      end
    end

    context ‘when attributes are not valid’ do
      it ‘saves the user and redirects to the index page’ do
        user.should_receive(:persisted?).and_return(false)
        subject.should render_template(:new)
      end
    end
  end
end

何が起こったのでしょうか?グループオブジェクトに深く入り込み、そのユーザーを取得し、グループオブジェクトを用いて新たなユーザーを生成しているために、 specにはより多くのmockが必要になるし、そうすべきなのです。 ここでの例は、単純なものですが、もしアクションがもっと複雑で、もっと論理が分岐していて、 structural couplingももっとあるなら、specがいったいどんなものになるのかは想像できることでしょう。

簡単にこのアクションをリファクタリングしてみましょう:

class UsersController < ApplicationController
  # stuff

  def create
    @user = @group.create_user(params[:user])

    if @user.persisted?
      redirect users_path, :notice => ‘User created!’
    else
      render :new  
    end
  end

  # more stuff
end

こんどはテストは少し簡単になります:

describe UsersController do
  describe "#create" do
    subject { post :create, :group_id => group_id, :user => attributes }

    let(:group_id) { mock(‘group_id’) }
    let(:group)    { mock(‘group’) }
    let(:user)     { mock(‘user’) }

    before do
      Group.should_receive(:find).with(group_id).and_return(group)
      group.should_receive(:create_user).with(attributes).and_return(users)
    end

    context ‘when attributes are valid’ do
      it ‘saves the user and redirects to the index page’ do
        user.should_receive(:persisted?).and_return(true)
        subject.should redirect_to(:users)
      end
    end

    context ‘when attributes are not valid’ do
      it ‘saves the user and redirects to the index page’ do
        user.should_receive(:persisted?).and_return(false)
        subject.should render_template(:new)
      end
    end
  end
end

グループが見つからないケースもチェックする例も加えるべきです。これはかなりまれなケースではありますが、テストが必要であるという事実に変わりはないのです:

describe UsersController do
  subject { post :create, :group_id => group_id, :user => attributes }

  let(:group_id) { mock(‘group_id’) }
  let(:group)    { mock(‘group’) }

  describe ‘#create’ do
    context ‘when group is not found’ do
      before do
        Group.should_receive(:find).with(group_id).
          and_raise(ActiveRecord::RecordNotFound)
      end

      it { should render_template(:not_found) }
    end
  end
end

これです!小さいテスト、速いテスト。コードがカバーされている。コントローラーも薄い。ここで、ユーザーコントローラ向けのビューのspecも書いてみるのもいいかしれませんが、私は書くつもりはありません、それは面倒です。

総括

やはり、コントローラのためのテストは書くべきなのです。誰かに書くべきかと問われれば、あなたはイエスと答えるべきなのです。コントローラのテストを書かなくてよいとする有効な主張は存在しないのです。 コントローラも、結局はコードであり、テストでカバーされるべきなのです。 テストを設計に組み込めば、コントローラは満足できるものになりますし、さもなければ、滅茶苦茶なものに終わるでしょう。 適切なテストがなければ、コントローラーが、無駄のない、よく設計されたものかどうかを本当の意味で確かめることはできないのです。だから、コントローラ向けのテストを書くべきなのです!

もしまだ見ていないようなら、Avdi の「デメテルの法則」についての素晴らしいポストを読むべきでしょう。この記事でもふれたstructural couplingについて書かれています。

追記(20140408)

一応、元記事の方に掲載の確認?はとってあります。

広告を非表示にする

git push のオプション -u と --set-upstream

git push -u origin master

-u と --set-upstream は同じ意味です。このオプションをつけるとローカルリポジトリの現在のブランチの上流をorigin master に規定したことになります。
このオプションをつけると、次からは git push だけで上記のコマンドと同じことを実施できます。また、git pull だけでも git pull origin master と同じ意味になります。

参考リンク

http://qiita.com/ironsand/items/6c301fef730d53f35bc3 http://usualoma.hatenablog.com/entry/20110214/1297644592

rails で複数一意制約

複数一意制約とは

複数一意制約とは、複数のカラムでセットでユニークにすること。

たとえば、電話番号の連絡先リストを作るとき。 {name: “daisuke”, phone: 111 }が登録されていたとする。

  • {name: “daisuke”, phone; 111 } は登録させたくない
  • {name: “taro”, phone: 111} は登録させたい

つまり、電話番号だけは重複してもいいけど、名前と合わせて重複させたくない。

対応方法

class User < ActiveRecord::Base
   validates :name,:uniqueness => {:scope =>:phone }
end

でOK。

参考URL

http://yoshifumisato.jeez.jp/wordpress/post/rails/902 http://d.hatena.ne.jp/suginoy/20110507/p1