Sunday, March 25, 2012

omuniauth使ったrailsサンプルサイト作成中のメモ


omuniauthを使ったサンプルサイトを作った過程の自分用メモです。まだ途中です。


demo
http://muitter.herokuapp.com/

code
https://github.com/cieux1/muitter

omniauth
https://github.com/intridea/omniauth/wiki

ほぼこちらのサイト通りにやった。感謝。
http://blog.twiwt.org/e/c3afce



# rails app作成

% rails new muitter

#Gemfile
gem 'omniauth'
gem 'omniauth-twitter'

% bundle


# config/initializer/omniauth.rb 作成
# add application info you registered at dev.twitter.com.
# *call back URL at dev.twitter can NOT be empty.

Rails.application.config.middleware.use OmniAuth::Builder do
     provider :twitter,"xxxxxxxxxxxxxxxxx","xxxxxxxxxxxxxxxxxxxxxxxxxxx"
     #provider :facebook,"App ID","App Secret"
end



% rails g controller sessions


# app/sessions_controller.rb

class SessionsController < ApplicationController
  def callback
    auth = request.env["omniauth.auth"]
    user = User.find_by_provider_and_uid(auth["provider"], auth["uid"]) || User.create_with_omniauth(auth)
    session[:user_id] = user.id
    redirect_to root_url, :notice => "Signed in!"
  end

  def destroy
    session[:user_id] = nil
    redirect_to root_url, :notice => "Signed out!"
  end
end



# routes.rb

match '/auth/:provider/callback' => 'sessions#callback'
match "/signout" => "sessions#destroy", :as => :signout



% rails g model user


# app/user.rb

class User < ActiveRecord::Base
  def self.create_with_omniauth(auth)
    create! do |user|
      user.provider = auth["provider"]
      user.uid = auth["uid"]
      user.name = auth["info"]["name"]
      user.screen_name = auth["info"]["nickname"]
    end
  end
end

# チュートリアルでは[user_info]になっているがtwitterAPIの仕様変更で[user]に変更になった?
https://github.com/intridea/omniauth/issues/249#issuecomment-3229038

# user_infoだとauth/failure のcallback routeが見つからないとでるので変更したら動いた。




# db/migrate/XXXXX_create_users.rb

class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table :users do |t|
      t.string :provider, :null => false
      t.string :uid, :null => false
      t.string :screen_name, :null => false, :uniq => true
      t.string :name, :null => false

      t.timestamps
    end
    add_index :users, [:provider, :uid]
    add_index :users, [:screen_name]
  end

  def self.down
    drop_table :users
  end
end



% rake db:migrate



# app/controllers/application_controller.rb

# add helper method

class ApplicationController < ActionController::Base
  protect_from_forgery

  helper_method :current_user

  private

  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end
end


% rails g scaffold Mutter user_id:integer mutterbody:text


# app/views/layouts/application.html.erb
# add login/show twiiter ID part to basic template erb.

<% if current_user %>
  Welcome <%= current_user.name %>!
  <%= link_to "Sign Out", signout_path %>
<% else %>
  <%= link_to "Sign in with Twitter", "/auth/twitter" %>
<% end %>



# route.rb
# set mutter/index as root.

root :to => "mutters#index"



# model/mutter.rb
belongs_to :user


# model/user.rb
has_many :mutters


# _form.html.erb
# ログイン中のuserのidをmutterのuser_idにひもづける処理。(なかなかわからなかった)
<%= f.number_field :user_id, :type => 'hidden', :value => current_user.id %>


このへん省略というか忘れた。。。というかなんで英語で書いてたのか。。。


okinawa ruby毎週meetupでomniauthが入った時点?でUser modelに必要なtableが作成されていてあとは使うだけ、という状態になっていることを教えてもらい道が開けた感。

#rails consoleでデータ呼び出しフォーマットの確認
% rails c

Mutter.all
User.find_by_id(1)

これで例えば、userとmutterをひもづけているmutterのuser_idがnilのままじゃん、とかが確認できた。




view / erb

#ログイン時とログインしていない時の見た目の切り替え
if current_user

# 自分の書き込みかどうかの判定
<% if current_user && mutter.user.screen_name == current_user.screen_name %>
...
<% end %>

#mutters_controller.rb
# ログインしているかどうかの判定

http://guides.rubyonrails.org/action_controller_overview.html

# before_filter ログインしていないと以下の操作ができないように。
    before_filter :require_login, :only => [:new, :create, :edit, :create, :update, :destroy]
...
...
    private

    def require_login
        unless logged_in?
            #flash[:error] = "You must be logged in to create/update a mutter."
            redirect_to root_url, :notice => 'You must sign in to create/update a mutter.'
        end
    end
    def logged_in?
        !!current_user
    end
 

need to be fixed!!!!!!!!!!!!!!!!!!
ログイン時、urlのid指定したら他の人の書き込みが触れてしまう。。。
どこでやるのかな。。これ。



heroku に deploy

#ssh keyの設定

github のssh key と herokuの ssh keyは同一である必要。
2つの端末で同じアカウントからpushしていることはどーなんだ?

ssh keyは端末のID的なもの?privateとpublicのペアができるので、public keyをサーバ側に保存する。
public keyは ~/.ssh/xxx_rsa.pub



レポジトリを登録してそこにpushする。
レポジトリは複数登録できる。
git add remote ....

一覧を見るには
git remote -v



# herokuはsqlite3ではなく、PostgreSQL
# Gemfileを修正
http://railsapps.github.com/rails-heroku-tutorial.html

group :development, :test do
  gem 'sqlite3'
end
group :production do
  gem 'pg'
end


# rails serverをthinに変更。webrickは頼りない?

webrickはlocalのままに残すなら

group :production do
  gem 'thin'
end


# herokuのstackによってrailsやrubyのバージョンが違う。
最新環境は cedar (beta)で、rails3.2の場合はこれでないと動かない?
heroku createする時に指定しなければならない。

http://devcenter.heroku.com/articles/cedar
http://devcenter.heroku.com/articles/cedar-migration

$ heroku create --stack cedar --remote heroku-cedar app名
$ git push heroku-cedar HEAD:master

なぜかHEADにしないとエラー。stackを[変更]するほうのtutorialを参考にしてたからか?
error: src refspec cedar does not match any.
error: failed to push some refs to 'git@heroku.com:app名.git'

http://stackoverflow.com/questions/4181861/src-refspec-master-does-not-match-any-when-pushing-commits-in-git



#gitignoreの設定
gitignoreは設定されるとそのファイルが gitから無視される。
設定される前に上がったものは基本的には消せない。

global_gitignore

globalは端末全体に設定される。
http://d.hatena.ne.jp/passingloop/20110903/p1

~/.global_gitignoreというファイルを作って記述
git config --global core.excludesfile ~/.global_gitignore で有効化。

例多数) https://github.com/github/gitignore/tree/master/Global



# 一度pushしてしまったファイルを消すのは大変&基本やってはいけない。
http://help.github.com/remove-sensitive-data/

git filter-branch
$ git filter-branch --tree-filter 'rm -f ファイル名' HEAD

$ git filter-branch --tree-filter 'rm -f omniauth.rb' HEAD

historyが書き変わるのでcloneされていたらおかしくなる?



# db:migrate

% heroku run rake db:migrate
成功するとlocalの時と同じようなログが出る。

% heroku restart
再起動で反映

% heroku run rakd db:reset
で元に戻す。



#pageを開く
% heroku open




# 修正の流れ

修正
git add app/asset/stylesheets/application.css
git commit -m 'adjusted font size.'
git push heroku-cedar HEAD:master

の繰り返し。


# 気になること
stack変えるために新規でheroku createしたので、githubにpushする方法がよくわからなくなった模様。。。