2007年10月24日水曜日

今日も認証

大文字で始まるメソッドの呼び出し

Module モジュールのクラス。


−−−−−−−−−−−
■ ログイン要求/判別 

class HogeController
include AutheticatedSystem
before_filter :login_required
....
end

これだけである。
これで、HogeController配下のアクションでは全てログインが必要となる。
未ログイン状態でアクセスすると/account/loginにリダイレクトされ、
そこでログインすると元のアクションに戻ってくる。
−−−−−−−−−−−−

とのことだけど、
AccountController・SchedulesController・ApplicationControllerの
3つとも指定しましたが・・・全然ログインを求められません。
キャッシュでも残っているのかな?と思い、
キャッシュの消去もしてみましたが;;
ただ、http://localhost:3000/ や
http://localhost:3000/account/ などのアクセスがlogin画面になっているのは・・・・
/config/routes.rbの中で下記のように指定したからですね。

map.connect '', :controller => 'account', :action => 'login'
map.connect '/account/', :controller => 'account', :action => 'login'
map.connect '/schedules/', :controller => 'account', :action => 'login'

同じ内容を3行って・・・
ApplicationControllerでbefore_filterが効けば必要ないのかな?

● 継承時の Filter

>コントローラを継承している場合、親クラスのコントローラで定義された
>Filter が先に実行されます。
>また、Filter を評価した値(戻り値)が false である場合、
>その時点で Filter の適用は停止され、以降の Filter は実行されません。
>(これは継承とは無関係に Filter の特徴です)

うーなぜfilterがかからないのか
全然分からない・・・・なにがいけないんだぁ

● routes

同じ内容3行でも良さそう。
でも、認証させたいコントローラーが多くなったらどうするのだろう?

例えば
map.connect '/:controller/', :controller => 'account', :action => 'login'
など、色々当てずっぽうに入れて為してみましたが、

http://localhost:3000/schedules/ にアクセスすると

<エラー文> Unknown action
No action responded to login

となってしまいます。
たぶん、schedulesにloginなんてアクション無いぞ。と言われている。

どんな処理でエラーになっているか?

Processing SchedulesController#login
Parameters: {"action"=>"login", "controller"=>"schedules"}

ここが気になりますね。SchedulesControllerのloginにparamを
持っていってますね。やはり。

しかし、http://localhost:3000/account/ にアクセスすると・・・

Processing ApplicationController#index
Parameters: {}

login画面が表示されるし、ApplicationControllerにプロセスしてる!
んんーーーー? これは、actionメソッドが同じだからぽい。

Processing SchedulesController#month
Parameters: {"action"=>"month", "controller"=>"schedules"}

でも、ApplicationControllerにはプロセスしていない。

あー分からないので、とりあえず進んでいきます。
urlではaction名を指定すればログイン無しで入れます!

・・・・・・・

★明日-最終日-の課題★

1.スケジュール新規登録でファイル添付をしていないとエラーが出るのを直す
<エラー文> NoMethodError in SchedulesController#create
undefined method `original_filename' for "":String
app/controllers/schedules_controller.rb:102:in `set_file_name'

2.認証・・・


明日は、今までの振り返りプレゼンをして、
残り時間で上記の課題をやろうと思います。

2007年10月23日火曜日

signup画面

さて。サインアップ画面のカスタマイズです。
acts_as_authenticatedで作ってくれるsignup.rhtmlの中は下記のように
書いてあります。
<%= error_messages_for :user %>
<% form_for :user do |f| -%>
<label for="login">name
<%= f.text_field :login %>



で、今回新規登録にもプルダウンで部署を選択できるようにするために
collection_selectで書いたのが、以下。
<label for="group_id">部署
<%= collection_select(:groups, :id, @groups, :id, :name) %>


これでは、:userに放りこまれてません。
頭に「f.」を付ければ良い・・・わけありませんでした。


f.を頭に付けてみると、
<エラー文>undefined method `merge' for :name:Symbol と言われます。

---------------------

signup.rhtmlと_userForm.rhtmlの中身が同じような感じなのがよく分からない。
webブラウザに生成されたhtmlをみてみると、_userForm.rhtmlに書かれている

<!--[form:user]-->
<!-- all custom fields here -->

<label for="group_id">所属グループ
<select id="user_group_id" name="groups[id]">
<option value="1" selected="selected">総務
<option value="2">営業
<option value="3">開発
のコメントが入っている。んーどこからどう調べていったら良いのか・・・
signup.rhtmlの頭に書いてある<% form_for :user do |f| -%>と
_userForm.rhtmlの頭の<!--[form:user]-->
これは、signup.rhtmlも_userForm.rhtmlも:userモデルを・・・なんだろう?
どういう意味なのかな??

*** :userモデル回りに関するformということだそうです ***

---------------------

<%= collection_select(:groups, :id, @groups, :id, :name) %>
ここに大きな間違えが!
<select id="user_group_id" name="groups[id]">
ここにも大きな間違えが起こってました。

<%= collection_select(:user, :group_id, @groups, :id, :name) %>
とすれば
<select id="user_group_id" name="user[group_id]">となって、
新規登録で、DBにも部署名(group_id)が登録できました。

さてさてあと2日・・・
最悪、エラーが出ないようにしたい・・・・汗

やっぱりRubyを一通り勉強しないと、カスタマイズは出来ないなぁ。


■ Ruby on Rails を使ってひとりでサービスを作ってみよう

■ パーミッション(所有権)の変更 linux

■ Module ActionView::Helpers::FormOptionsHelper

2007年10月22日月曜日

collection_selectとユーザ一覧

新規ユーザーの登録でも部署名をプルダウンで選択させたい。

collection_select()
selectのなかでHashかArraysを使う

例:select (:artists, :name, @deadArtists)
は@deadArtistsにある全ての芸術家のドロップダウンリストを生成する。
deadArtistは値が@artists.nameに一致するか、それぞれチェックされる。
一致した場合、その芸術家が選択された状態のドロップダウンが生成される。



[/account_controller.rb]
def signup
@groups = Group.find(:all)
@user = User.new(params[:user])
return unless request.post?
@user.save!
self.current_user = @user
redirect_back_or_default(:controller => '/account', :action => 'list_group')
flash[:notice] = "Thanks for signing up!"
rescue ActiveRecord::RecordInvalid
render :action => 'index'
end



[signup.rhtml]

<label for="group_id">部署</label>
<%= collection_select(:groups, :group_id, @groups) %>





query文
Group Load (0.001989) SELECT * FROM groups



クエリはあっているようだけど

<エラー文> wrong number of arguments (3 for 5)

5個のとこが3個しかないっていわれてる?
だとすれば。。。プルダウンに入る値の設定かな?



<%= collection_select(:groups, :group_id, @groups, :id, :name) %>


<エラー文> undefined method `group_id' for #




そりゃそうだった!groups DBには :id と :name の2項目しかありません。



<%= collection_select(:groups, :id, @groups, :id, :name) %>



おお!ちゃんとプルダウンで部署名が表れました。

新規ユーザー登録してみると・・・(まだgroup_idのDBへの登録は設定してない)
あ。やっぱりどのグループにも登録されてない。
が、登録したユーザーでのログインは出来ました。
とりあえず、ユーザー一覧も作っておこう。・・・としたら、
上で書いている『どのグループにも登録されてない』おかげで
うまいこと表示されず、またまた遠回りをしてしまいましたが、
日に日に「ピン!」と来る回数は増えたのですが、
debugが上手に出来ず小さなミスで右往左往している気がします。

明日は、やりかけた、acts_as_authenticatedとは
で勉強しつつ、
authenticatedに無い新しい項目のDB登録を完成させたいです。

2007年10月19日金曜日

Viewとにらめっこ

今日はViewについてさらに深く勉強して、
DBの関連についてもやっと「なるほど!」と分かった。
contorollerをさわり、AとBとCのデータベースにそれぞれに登録されている
学生名とか学校名とか出身地をViewにならべて表示出来た!

さて、週明けにこれを仕上げるぞ〜〜

早いもので週明けからはたった4日でOJTが終わります。
ん〜本当に早い!



Listing students





<% for column in Student.content_columns %>

<% end %>

-----------------------------------
 カラム名が入る
-----------------------------------
 ■Studentとは

 [student.rb]

 class Student < ActiveRecord::Base
 belongs_to :school
 has_one :profile
 end

 ■.content_columns()とは
 "_id" または "_count" で終わる全カラム、
 つまりプライマリ id と、単一テーブル継承に
 使用されるカラムを全て取り除いた
 カラムオブジェクトの配列を返します。
 
 ■obj.human_name
  英単語の頭を大文字に変換する。
  日本語の場合不要。
-----------------------------------

<% for student in @students %>
-----------------------------------
 ■@studentsとは

 [ students_controller.rb ]

 def list
  @student_pages, @students =
paginate :students, :per_page => 10
 end
 
 ▽paginate collection_id, options={}

「ページ管理オブジェクト」,「オプションで指定した個数のインスタンスが入ってる」=
paginate「第一引数 ARモデル(モデルクラスの複数形/対象とするテーブル名)」,「オプション」
-----------------------------------

<% for column in Student.content_columns %>


-----------------------------------
 DBの中に入っている値が出る。
-----------------------------------
 ■send(name[, args ... ])
  オブジェクトのメソッド name を、引数に args を渡して呼び出し、
  メソッドの実行結果を返します。
  ブロック付きで呼ばれたときはブロックもそのまま引き渡します。
  メソッド名 name は文字列かSymbol です。
 
 ■obj.name
  オブジェクトのnameを返す。
-----------------------------------
<% end %>





<% end %>
<%= column.human_name %>
<%=h student.send(column.name) %> <%= link_to 'Show', :action => 'show', :id => student %> <%= link_to 'Edit', :action => 'edit', :id => student %> <%= link_to 'Destroy', { :action => 'destroy', :id => student },
:confirm => 'Are you sure?', :method => :post %>



■ update(id, attributes)

update は、複数のカラムを更新し、save します。

update は find(id) して得られる AR オブジェクトに対して update_attributes(attributes) を行います。 update_attributes(attributes) は self.attributes = attributes して save します。戻り値は save の戻り値です。

2007年10月18日木曜日

データベースの関連について

今日は、一日関連について勉強してましたが、
schoolデータベースと関連付けたはずの
students データベースのschool_idカラムがなぜかnilのまま!

id | name |school_id
1 | 田中 | nil
2 | 中田 | nil
3 | 山田 | nil

と、イライラ〜としながらRailsで作るAjax住所録のサンプルソースなんかを
取り込んでいじってみたりしてましたが、
またしても完全な思い込み・・・・
関連づけても、school_idは自動で入ってくれるわけではないのですね。
ん〜 どうして思い込むのだろう?

また、基本をすっ飛ばして触り始めたRailsだったので、
今日初めて .rhtml の中身をじっくり見てみました。
なんだかすこしずつ頭の中の「?」がほどけていってる気がします。
まだまだ「?」多いですけど。



SQLiteで間違えてカラムを追加しちゃった場合。
SQLite−カラムの削除方法。

テーブルそのものの操作方法(テーブル名変更・列の増減など)



sqlite> ALTER TABLE schools ADD COLUMN school_id integer;
sqlite> select * from schools;
id|name|school_id
1|工学院|

sqlite> select * from students;
id|name|school_id
1|01|
2|02|
3|山田|


sqlite> BEGIN TRANSACTION;
sqlite> CREATE TEMPORARY TABLE schools_backup(id,name);
sqlite> INSERT INTO schools_backup SELECT id,name FROM schools;
sqlite> DROP TABLE schools;
sqlite> CREATE TABLE schools(id,name);
sqlite> INSERT INTO schools SELECT id,name FROM schools_backup;
sqlite> select * from schools;
id|name
1|工学院
sqlite> DROP TABLE schools_backup;
sqlite> commit;


2007年10月17日水曜日

関連について

今日は、「Ruby on Rails 入門 -優しいRailsの育て方 」 p83〜 を勉強。
「1:多」の関連までやったところで、昨日から痛めている首が辛くなってしまい、
腰までひびいてきたので、早退をさせてもらいます。

すみません。

2007年10月16日火曜日

Aptanaでacts_as_authenticated

acts_as_authenticatedを分かる範囲で調べたところ
script/generate authenticated user account してからmigrateする。
と書いてあるけど、今回は「user」というモデルと「account」という
コントローラーが既にあるので、プラグインすることで
今まで作ったファイルが上書きされちゃわないかの確認。

「実際には変更しない = -p, --pretend」オプションで走らせてみる。
/*Aptanaの「Generator」ではうまく動かなかったので、プロンプトで
script/generate authenticated user account を実行*/

overwrite app/models/user.rb? [Ynaqd]
overwrite app/controllers/account_controller.rb? [Ynaqd]
overwrite test/functional/account_controller_test.rb? [Ynaqd]
overwrite app/helpers/account_helper.rb? [Ynaqd]
overwrite test/unit/user_test.rb? [Ynaqd]
overwrite test/fixtures/users.yml? [Ynaqd]

計6つのファイルが上書きされてしまう模様なので、
別フォルダを作って上記6つのファイルを移動させておく。

-pオプションなしで実行。




exists app/models/
exists app/controllers/
exists app/helpers/
exists app/views/account
exists test/functional/
exists test/unit/
create app/models/user.rb
create app/controllers/account_controller.rb
identical lib/authenticated_system.rb
identical lib/authenticated_test_helper.rb
create test/functional/account_controller_test.rb
create app/helpers/account_helper.rb
create test/unit/user_test.rb
create test/fixtures/users.yml
identical app/views/account/index.rhtml
identical app/views/account/login.rhtml
identical app/views/account/signup.rhtml
exists db/migrate
Another migration is already named create_users: db/migrate/004_create_users.rb




で、できた。が。んん?見落としていたけど、最後の行は−pの時も出ていた。
User modelを作った時に出来たmigrateスクリプトも移動しておかなきゃ
いけなかったんですね。たぶん。
移動させて、もう一度authenticatedしたら、新たにdb/migrate/004_create_users.rbが
出来ました。中身を見てみると・・・




class CreateUsers < force =""> true do |t|
t.column :login, :string
t.column :email, :string
t.column :crypted_password, :string, :limit => 40
t.column :salt, :string, :limit => 40
t.column :created_at, :datetime
t.column :updated_at, :datetime
t.column :remember_token, :string
t.column :remember_token_expires_at, :datetime
end
end

def self.down
drop_table "users"
end
end


うわー高機能ですね。

さて、ここで問題が。以前に作ったUsersテーブルはどうすればいいのか?

もともと作っていたuserテーブルの中身は、:group_idと:nameだけなので、
group.rb は has_many :users のまま、新しい user.rb に belongs_to :group してもう。


[ /model/user.rb ]

require 'digest/sha1'
class User <>
 [ /controller/account_controller.rb ]

(略)

def logout
self.current_user.forget_me if logged_in?
cookies.delete :auth_token
reset_session
flash[:notice] = "You have been logged out."
redirect_back_or_default(:controller => '/schedules', :action => 'month')
end

の後ろに、昨日までに作ったaccount_controller.rbの内容を
とりあえずドバっとコピペしてみたら、ユーザー管理からログインした後に
グループ一覧へ行けるようになり、グループについては新規追加/削除/編集が出来た。
ログアウトも出来る!
・・・・と、一通り喜んでみたものの、まだDBは何も触ってません。
ので、明日はDBを:includeや:has_manyなどを使って作ろうと思ってます。