Git Immersion (Git漬け)を訳しながら使い方を覚えてみる.その4

なかなか進められないけど地道にアップします。


LAB 7 ステージに乗せてコミットする
Gitにおいて分離されたステージに乗せる操作は,これまで自分でソースの管理をする必要があった状況から抜け出すための哲学にのっとっている.
自分の作業用ディレクトリに変更を加え続けることができ,またソース管理に関わりたいときには,gitによって細かいコミットの実際の作業記録における変更を残しておける.
たとえば,a.rb, b.rb, c.rbという3つのファイルを変更した時について考えよう.全ての変更をコミットしたいが,a.rb とb.rb は一つのコミットで,c.rb は最初の二つのファイルと論理的につながらないので別のコミットにすべきである.
こうすればよい.


git add a.rb
git add b.rb
git commit -m "Changes for a and b"

git add c.rb
git commit -m "UNrelated change to c"


ステージに上げる操作とコミットの操作を分けることで,コミットに加える変更を調整することができるようになる.



LAB 8 変更をコミットする
目標:リポジトリに変更をコミットする方法を学ぶ

1.変更をコミットする
OK.ステージングについてはもう十分だろう.ステージングした変更をリポジトリにコミットしてみよう.
以前最初のバージョンのhello.rbファイルをリポジトリにコミットするためにgit commitを使った時,-mフラグを含めてコマンドラインからコメントを追加した,そのcommitコマンドによってコミットに対話的にコメントを編集することができる.それじゃあやってみよう.
コマンドラインで-mフラグを省くと,gitはエディタを選択するように求めてくる.エディタは以下のリストから選ばれる.(優先度順)
環境変数のGIT_EDITOR
・core.editorの設定
環境変数のVISUAL
環境変数のEDITOR
// 自分の環境では環境変数で設定するのがうまくいかなかったので
// git config --global core.editor "vi"
エディタの設定をしたらcommitで状態を見てみよう.
git commit
設定したエディタが出てくるので,最初の行にUsing ARGVと書き加える.

Using ARGV
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# (use "git reset HEAD ..." to unstage)
#
# modified: hello.rb
#

[master 8888ecf] Using ARGV
1 files changed, 1 insertions(+), 1 deletions(-)

2.状態チェックする
最後にもう一度状態をチェックしてみよう.
git status
すると,出力はこうなるはず.

# On branch master
nothing to commit (working directory clean)

作業用ディレクトリはクリーンで,続行できる状態だ.

Git Immersion (Git漬け)を訳しながら使い方を覚えてみる.その3

1日2項目じゃ遅いかな?と思いはじめた今日この頃です。

ついでに、英語力も足りない怪しい直訳がダサすぎて死にそうなんて言えない←


LAB 5 変更を加える(作業用ディレクトリ)
http://gitimmersion.com/lab_05.html
目標:作業用ディレクトリの状態の追跡の仕方を学ぶ
1.”Hello, world"プログラムを変更する
HelloWorlsdプログラムを変更してコマンドラインから引数を一つとれるようにする.
変更後のファイルは次のようになる.
vi hello.rb

puts "Hello, #{ARGB.first}!"

2.状態を調べる
作業用ディレクトリの状態を調べてみよう.
git status
出力はこうなる.

# On branch master
# Changed but not updated:
# (use "git add ..." to update what will be committed)
# (use "git checkout -- ..." to discard changes in working directory)
#
# modified: hello.rb
#
no changes added to commit (use "git add" and/or "git commit -a")

最初に注意しないといけないのはgitはhello.rbが変更されたことを検知していることだ.でもgitはこれらを通知されてはいない.
もう一つ注意すべきは,この状態メッセージは次に何をする必要があるのか示唆してくれる.
もしこれらの変更をリポジトリに加えたいなら,git add コマンドを使えばいい.
そうでなければgit checkout コマンドで変更を破棄することができる.

3.次の段階へ
変更をステージに乗せてみよう.
// stage -> コミット前の緩衝地帯のことらしい.

LAB 6 変更をステージングする
http://gitimmersion.com/lab_06.html
目標:最新のコミットの変更をステージングする方法を学ぶ

1.変更を加える
ではgitに変更を反映させて状態を見てみよう.
git add hello.rb
git status

# On branch master
# Changes to be committed:
# (use "git reset HEAD ..." to unstage)
#
# modified: hello.rb
#

hello.rbファイルの変更が反映された.
これはgitはその変更内容を知っているが,この変更はまだリポジトリに記録されてはいない.
次のコミット操作がリポジトリに変更を加える.

結局変更をコミットしたくない場合には,git reset コマンドを使って変更をステージから削除することができることをstatusコマンドが思い出させてくれている.

Git Immersion (Git漬け)を訳しながら使い方を覚えてみる.その2

まったり追記していきますよ.
今回はLAB3と4.
リポジトリ(倉庫,貯蔵所,宝庫)ってそのままカタカナで呼ばれてるけど,あえて訳すならなんなんだろ?

なお,作業履歴もかねているのでシェルコマンド部分も書いてます.
エディタはviを使っているので,適宜読み替えてください.



LAB3 プロジェクトを作る
http://gitimmersion.com/lab_03.html
目標:スクラッチで(=ゼロから)Gitのリポジトリを作成する方法を学ぶ


1."Hello world"プログラムを作成する
空の作業用ディレクトリ(さっき解凍したwork)から作業を始める.
cd work
helloという名前でディレクトリを作る
mkdir hello
cd hello
hello の中にhello.rbを作成する.中身は以下.
vi hello.rb

puts "Hello, World."


2.リポジトリを作成する
ここまでで一つのファイルからなるディレクトリができている.
このディレクトリからリポジトリを作成し,gitのinitコマンドを実行する.
git init

Initialized empty Git repository in /home/toki/git_tutorial/work/hello/.git/

3.プログラムをリポジトリに追加する
Hello, worldプログラムをリポジトリに追加しよう.
git add hello.rb
git commit -m "First Commit"
出力はこうなる.

[master (root-commit) 718f5be] First Commit
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 hello.rb


LAB 4 状態を調べる
http://gitimmersion.com/lab_04.html
目標:リポジトリの状態の調べ方を学ぶ


1.リポジトリの状態を調べる
git status コマンドを使えばリポジトリの状態を調べることができる
git status

# On branch master
nothing to commit (working directory clean)

このstatusコマンドはコミットされたものがないことを示している.
これはリポジトリの中が全て作業用ディレクトリの最新の状態であることを表している.
未適用の記録の変更はない.

git statusコマンドは継続してリポジトリと作業用ディレクトリの状態の差を追跡する時に使う.

Git Immersion (Git漬け)を訳しながら使い方を覚えてみる.その1

Railsや研究用のMATLABでソースを書き散らしているうちに,修正個所と内容が把握できなくなってきた.
ほぼ同じ内容のバックアップが大量にあるような状態で,手が付けられない.

と,いうわけでバージョン管理システムのGitを導入してみる.

参考にしたのはこのチュートリアル

Git Immersion
http://gitimmersion.com/index.html

Git漬け,って感じですかね.英語漬けみたいな.


とりあえずUbuntu環境に入れてみる.
$ sudo apt-get install git-core
(※いつの間にか入れてたらしい.)
バージョンを確認.
$ git --version
git version 1.7.0.4


LAB 1 Setup
http://gitimmersion.com/lab_01.html
目標:作業の準備のためにGitを設定する

1.名前とEmailの設定
$ git config --global user.name "Your Name"
$ git config --global user.email "your_email@whatever.com"

2.行末の設定
//Ubuntuに入れたのでUnix/Mac用の設定にする
$ git config --global core.autocrlf input
$ git config --global core.safecrlf true


LAB 2 More Setup
http://gitimmersion.com/lab_02.html
目標:チュートリアル用の素材を取得して実行する準備をする

1.Gitのチュートリアルパッケージを取得する
$ wget http://onestepback.org/download/git_tutorial.zip

2.チュートリアルパッケージを解凍する
// の,前にunzipが入ってなかったのでインストール
// $ sudo apt-get install unzip
$ unzip git_tutorial.zip
git_tutorialの中身は,
html:このチュートリアルのHTMLファイル一式
work:空の作業用ディレクトリ.この中にリポジトリを作る.
repos:予めパッケージ化されたリポジトリ.workにコピーすれば任意の場所からチュートリアルを始められる.


2〜3章ずつ訳してアップしていけばいいかな.

Crontabを利用したRailsのモデルメソッドの定期実行

備忘録メモ.

Botもどきを作成するには,定期的にポストできるようにしなきゃいかん訳ですね.

と,いうわけでCrontabを使ってモデルメソッド実行(→ボットの投稿)するためのメモ.

参考

rails の model メソッドを簡単に daemon 化する方法
http://doruby.kbmj.com/red/20100707/rails___model___daemon__
rvm+railsなアプリケーションをcronで動かす
http://sanojimaru.com/tag/rvmrails


Cronで動かす場合,非RVM環境でRailsを動かさないといけない.
→rvm wrapper rubyのバージョン@gemsetの名前 action gem
ex.

rvm wrapper 1.8.7@rails3_n1 runner rails

Ubuntu10.04の環境だと,$HOME/bin/runner_railsが作成された.
ちなみにrunnerを動かすから・・・と思って書いたけどファイルの中身を見てもrunnerとか入ってない.
actionってこれのことじゃないのかな?(動いているみたいなのがまた謎)


[RAILS_ROOT]は対象のRailsプロジェクトのルートディレクトリ.

適当にcron.shを作成
vi [RAILS_ROOT]/batch/cron.sh

#!/bin/sh
cd [RAILS_ROOT]
$HOME/bin/runner_rails runner -e development "User.auto_post()" >> cron.log 2>&1

叩いてみる(RVMでgemsetを適用していない環境での確認が必要.)
[RAILS_ROOT]/batch/cron.sh

ログはこの場合は[RAILS_ROOT]/cron.logに出力されるので,なんかちゃんと動いてなさそうだったら中身を見てみる.
必要なGemが入ってねえよ!って趣旨のメッセージが出力されているようならGemfileに足してbundle install
※でも多分RVMのGemsetが使えてないとかそういう系の理由な気がする.
 rvm wrapper に設定したgemsetとかを確認してやり直してみるとうまくいくことも.


動くようなら,Cronの設定.
数字は,左から順に分,時,日,月,曜日.
試しに毎月毎日11時〜22時の0分に定期実行するようにすると,こうなる.
crontab -e

# m h dom mon dow command
0 11-22 * * * [RAILS_ROOT]/batch/cron.sh


ちゃんと定時に動けばOKです.

Rails + Devise + omniauthでTwitterの認証

ずいぶん間が空いてしまいましたが技術ネタで更新したいと思います.

最近さくらのVPSを借りまして,Railsなんか入れて遊んでみようと思ったわけです.
Twitterと連携できたらなおさら楽しいよね,ということで,
練習がてらBotのようなものでも作ってみようかとも思っています.

んで,TwitterのOAuthも使える認証機構としてDevise(Devi'c'eじゃなかった)ってのがあったので
使い始めるまでの記録をメモがてら残してみます.

参考にしたページはこのあたりです.
Rails3 認証エンジン「devise」
http://d.hatena.ne.jp/glpgsinc/20110503/1304395983
Rails3 deviseによるtwitter認証
http://d.hatena.ne.jp/glpgsinc/20110508/1304786181
Rails で Devise と OmniAuth を連携させる
http://blog.twiwt.org/e/14b25f
241: 簡単なOmniAuth
http://ja.asciicasts.com/episodes/241-simple-omniauth

//==========作業履歴==========//

// 環境
// Ubuntu 10.04, rvm 1.6.22, ruby 1.8.7, rubygems 1.6.2, rails 3.0.7

// rvmは次のようなgemsetを作成済み
rvm use 1.8.7@rails3

rails new test_d -d mysql

cd test_d

vi .rvmrc

rvm use 1.8.7@rails3


// Gemfileの編集.
// Rails3ではmysql2のバージョンが新しすぎるとハマるので0.3系以上を使わないようにする
vi Gemfile

gem 'mysql2','<0.3'
gem 'devise'
gem 'oa-oauth', :require => "omniauth/oauth"


// gemとdbの準備をする
bundle install
rake db:create
rake db:migrate

// deviseのインストール
rails g devise:install

// Oauthのconsumer_keyとconsumer_key_secretの情報を追加
// 予めdev.twitter.comで取得する
vi config/initializers/devise.rb

config.omniauth :twitter, "consumer_key","consumer_key_secret"


// deviseの機能を使えるモデルの生成
rails g devise User
// omniauthを使うためには :omniauthable
vi app/models/user.rb

class User < ActiveRecord::Base
devise :trackable, :omniauthable
end


// migrationの作成
// 要らないものは消す.足りないカラムは後からrake db:migrateで追加するので今は気にしない
vi db/migrate/20110715043006_devise_create_users.rb

class DeviseCreateUsers < ActiveRecord::Migration
def self.up
create_table(:users) do |t|
t.trackable
t.timestamps
end
end

def self.down
drop_table :users
end
end

// uid, screen_name, access_token, access_secret を入れるカラムの追加
rails g migration AddTokenToUser uid:integer screen_name:string
access_token:string access_secret:string
// DBに関係する記述が終了.migrationする
rake db:migrate

// routesの確認
rake routes
> user_omniauth_callback /users/auth/:action/callback(.:format) {:controller=>"devise/omniauth_callbacks", :action=>/twitter/}

// callbackにカスタムのコントローラーを使えるようにする為にroutesを設定
vi config/routes.rb

devise_for :users, :controllers => {:omniauth_callbacks => "omniauth_callbacks"}

> user_omniauth_callback /users/auth/:action/callback(.:format) {:controller=>"omniauth_callbacks", :action=>/twitter/}

// callback用のカスタムコントローラーの作成
rails g controller OmniauthCallbacks twitter

vi app/controllers/omniauth_callbacks_controller.rb

class OmniauthCallbacksController < ApplicationController
def twitter
# You need to implement the method below in your model
@user = User.find_for_user_oauth(env["omniauth.auth"],nil)

if @user.persisted?
flash[:notice] = I18n.t "devise.omniauth_callbacks.success",
:kind => "User"
sign_in_and_redirect @user, :event => :authentication
else
session["devise.twitter_data"] = env["omniauth.auth"]
redirect_to root_path
end
end
end



// Userモデルにメソッド追加.
// DBに既に保存されていればそれを返す.そうでなければ新しく保存する
vi app/models/user.rb

class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable,

timeoutable and
omniauthable

devise :trackable, :omniauthable

# Setup accessible (or protected) attributes for your model
#attr_accessible :email, :password, :password_confirmation, :remember_me

def self.find_for_user_oauth(access_token, signed_in_resource=nil)
data = access_token['extra']['user_hash']
if user = User.find_by_uid(access_token['uid'].to_i)
user
else
User.create!({
:uid => access_token['uid'].to_i,
:screen_name => data['screen_name'],
:access_token => access_token['credentials']['token'],
:access_secret => access_token['credentials']['secret']}
)
end
end
end


// トップページを作成,サーバーのrootに設定
rails g controller welcome index

vi config/routes.rb

root :to => 'welcome#index'


// アプリケーション内の共通テンプレートにログイン用のリンクを張る
vi app/views/layout/application.html.erb<% if user_signed_in? %>
Hi! <%= current_user.screen_name %>
|
<%= link_to "Sign Out", destroy_user_session_path %><% else %>
<%= link_to "Sign in with Twitter", user_omniauth_authorize_path(:twitter) %><% end %>


// サインアウトしたときのためのリンクのroutesを張るために編集
vi config/routes.rb

devise_for :users, :controllers => {:omniauth_callbacks =>
"omniauth_callbacks"} do
get '/users/sign_out', :to => 'devise/sessions#destroy', :as =>
:destroy_user_session
end



// 消さないとサーバーのルートが見られない
rm public/index.html
// Webrick起動
rails s

// ログインができるかの確認の為に,WebのTwitterからログアウトしておくといい.
// ブラウザで開く.localhost:3000とか.

// Sign in with TwitterをクリックしてOauth認証画面に遷移

// ログインできていることを確認

// mysqlからDBにも保存されていることを確認できる
mysql -u root test_d_development
select * from users;

//============作業履歴終了=============//

できることの幅が広がりそうなので,興味のある方は試してみてはいかがでしょうか.

条件分岐とルックアップテーブル

バイト先の方のブログでFizzBuzz問題というのをやっていたのでうちでもやってみた.

(参考)FizzBuzz問題Rubyで書くと | ysakaki.com, http://ysakaki.com/?p=167


条件分岐の代わりにルックアップテーブルにしてみた.

fizz = ["Fizz","",""]
buzz = ["Buzz","","","",""]
1.upto 100 do |i|
if ((i%3)*(i%5)==0)
puts fizz[i%3]+buzz[i%5]
else
puts i
end
end

14行→9行に圧縮.
でもやっぱりif文が一つ余るなあ.

似た感じで,牛タンゲームも難しい気がする.
牛タンゲームのn番目の人は牛なのかタンなのかって一発で判別できるのかな.