Hatena::ブログ(Diary)

くりまるwebつくる

ふぅ、疲れた。今日はここまで。
カレンダー
2008 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 |

2008年02月13日

[][]mysqlのGRANTやって、ついでにGUIのツールを入れておく

昨日macに入れたmysqlにユーザーを作った。

rootと同じ権限

mysql> GRANT ALL PRIVILEGES ON *.* TO user@"%"
    -> IDENTIFIED BY 'パスワード' WITH GRANT OPTION;
mysql> GRANT ALL PRIVILEGES ON *.* TO user@localhost
    -> IDENTIFIED BY 'パスワード' WITH GRANT OPTION;
mysql> FLUSH PRIVILEGES;

参考

http://www.bitscope.co.jp/tep/MySQL/quickMySQL.html

ついでにmysqlGUIのツールも入れておく

http://dev.mysql.com/downloads/gui-tools/5.0.html

ダウソ

querybrowserでつなぐとき、localhostだとおこられた

127.0.0.1だとつながった。

[]rails2.Xでscaffoldで/admin/usersとかのコントローラ作りたいとき

rails2でscaffoldすると、migrateも作られるようになったのはわかった。

で、usersがある状態で/admin/usersみたいな会員管理コントローラを作りたいとき。

#いや、管理ページはRestfullにする必要ないかもしれないけど。。/mypage/xxxとかありうると思うから

scaffold

$ script/generate scaffold Admin::user --skip-migration
      create  app/models/admin
      create  app/controllers/admin
      create  app/helpers/admin
      create  app/views/admin/users
      create  app/views/layouts/admin
      create  test/functional/admin
      create  test/unit/admin
      create  app/views/admin/users/index.html.erb
      create  app/views/admin/users/show.html.erb
      create  app/views/admin/users/new.html.erb
      create  app/views/admin/users/edit.html.erb
      create  app/views/layouts/admin/users.html.erb
   identical  public/stylesheets/scaffold.css
  dependency  model
      exists    app/models/admin
      exists    test/unit/admin
      create    test/fixtures/admin
      create    app/models/admin/user.rb
      create    test/unit/admin/user_test.rb
      create    test/fixtures/admin_users.yml
      create  app/controllers/admin/users_controller.rb
      create  test/functional/admin/users_controller_test.rb
      create  app/helpers/admin/users_helper.rb
       route  map.resources :users

で、localhost:3000/admin/usersにアクセスすると

 NoMethodError in Admin/users#index

Showing admin/users/index.html.erb where line #7 raised:

You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each

Extracted source (around line #7):

4:   <tr>
5:   </tr>
6: 
7: <% for user in @users %>
8:   <tr>
9:     <td><%= link_to 'Show', user %></td>
10:     <td><%= link_to 'Edit', edit_user_path(user) %></td>

/admin/user/index.html.erbの7行目に文句言われる

<% for user in @users %>

コントローラーを見ると

  def index
    @admin_users = Admin::User.find(:all)

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @admin_users }
    end
  end

indexメソットだけ@admin_usersになってるので@usersに戻す。

view直す

<%= link_to 'New user', new_user_path %>

は多分:name_prefix=adminということだから

<%= link_to 'New user', new_admin_user_path %>

xmlの整形でコケル

admin/users.xmlとかでエラーになる

users = Admin::User.find(:all)
#中略
format.xml  { render :xml => @users }

だと

#<Admin::User id: 1, name: "hogehoge", created_at: "2008-02-12 23:14:05"(略)

インスタンスからxmlパースしようとして

<admin/usre id:(略

みたいにしてパースエラーになるのでAdmin::Userモデルはクビでいいと思う。

そもそも同じスキーマに複数モデルがあったらきっと美しくない気がしてきた。

ので、Admin::User.newとかを全部User.newとかにする。

たぶん

これで、ふつーのscaffoldした感じと同じになる気がする。

つまり/admin以下にコントローラを作る場合

  • scaffoldする
  • route.rbにnamespace書く
  • 生成されたcontorollerの
    • indexの@admin_usersを@usersにする
    • Admin::Users.new等をUsers.newにする
    • /models/admin/user.rbを消す
  • 生成されたviewの
    • migrationをskipしてるのでスキーマ情報がないので書く
    • new_user_pathとかをnew_admin_user_pathとかに書き換える

くらいでおkかな。

全部試してないけど。

参考

Rails2.0のRouting(config/routes.rb)の記述方式についてのまとめ。 - RAILS PRESS

大場寧子のホームページ - モジュール下のコントローラをRESTfulにする

大場寧子のホームページ - コントローラをRESTfulにする

大場寧子のホームページ - コントローラのRESTfulインターフェースをカスタマイズする

大場寧子のホームページ - 親子構造のあるモデルを扱うコントローラをRESTfulにする

Ruby On Rails ピチカート街道 - Rails 2.0・その1(RESTful なコントローラのメソッド追加) -

Ruby On Rails ピチカート街道 - Rails 2.0・その3(map.resources の has_one が扱いやすく) -

[][]認証。acts_as_authenticatedとrole_requirementとopenid_login_generatorで、両対応な感じを目指す。

acts_as_authenticated

インスコ→じぇねる→migrate

$ ./script/plugin install acts_as_authenticated
$ ./script/generate authenticated user account
$ rake db:migrate

で、おk

role_requirement

インスコ→じぇねる→migrate

$ script/plugin install http://rolerequirement.googlecode.com/svn/tags/role_requirement/
$ script/generate roles Role User
$ rake db:migrate

モデル書く

app/models/role.rb

class Role < ActiveRecord::Base
  has_and_belongs_to_many :users
end

ロールの管理をscaffold

ruby script/generate scaffold role --skip-migration

migrationをskipしてるからか、スキーマ情報が

入ってないのでviewを直す。

(略)

openid_login_generator

既にgemインスコしてあって、ジェネレータも直してる状態で、

generate

Userモデルはもうあるのでその辺はnで

$ ./script/generate openid_login openid
      create  lib/openid_login_system.rb
      create  app/controllers/openid_controller.rb
      create  test/functional/openid_controller_test.rb
      create  app/helpers/openid_helper.rb
overwrite app/models/user.rb? (enter "h" for help) [Ynaqdh] n
        skip  app/models/user.rb
overwrite test/unit/user_test.rb? (enter "h" for help) [Ynaqdh] n
        skip  test/unit/user_test.rb
overwrite test/fixtures/users.yml? (enter "h" for help) [Ynaqdh] n
        skip  test/fixtures/users.yml
      create  app/views/layouts/scaffold.html.erb
   identical  public/stylesheets/scaffold.css
      create  app/views/openid
      create  app/views/openid/welcome.rhtml
      create  app/views/openid/login.rhtml
      create  app/views/openid/logout.rhtml
      create  README_LOGIN

usersにopenid_urlカラムを追加

$ ruby script/generate migration add_column_users_openid_url
      exists  db/migrate
      create  db/migrate/003_add_column_users_openid_url.rb

migarate_fileを編集

class AddColumnUsersOpenidUrl < ActiveRecord::Migration
  def self.up
    add_column :users, :openid_url, :string
  end

  def self.down
    remove_column :users, :openid_url
  end
end

migrate

$ rake db:migrate
(in /home/coek/dev/rails/auth_and_open_id_test)
== 3 AddColumnUsersOpenidUrl: migrating =======================================
-- add_column(:users, :openid_url, :string)
   -> 0.0417s
== 3 AddColumnUsersOpenidUrl: migrated (0.0439s) ==============================

モデル書き足す

  def self.get(openid_url)
    find_by_openid_url(openid_url)
  end
  protected

  validates_uniqueness_of :openid_url, :on => :create
  validates_presence_of :openid_url

で、controllerとかを

http://d.hatena.ne.jp/crimaru/20080212/1202793189

http://d.hatena.ne.jp/crimaru/20080212/1202812083

とかでやったように全部直す。

validateでコケる

今回はopenidからのログイン(登録)の場合は、idとopenid_urlだけ入れるってのでいいかなと思ってる。

で、普通にサインアップしたときは、openid_urlがNULLでいいかな、と。

なので

validates_presence_of     :login, :email

だと、openidから使うときダメになるので

Userモデルに

  def openid?
    self.openid_url.blank? #入ってたらfalseが返る
  end

なのを書き足して、

  validates_presence_of     :login, :email, :if => :openid?
  validates_presence_of     :password,                   :if => :password_required?
  validates_presence_of     :password_confirmation,      :if => :password_required?
  validates_length_of       :password, :within => 4..40, :if => :password_required?
  validates_confirmation_of :password,                   :if => :password_required?
  validates_length_of       :login,    :within => 3..40, :if => :openid?
  validates_length_of       :email,    :within => 3..100, :if => :openid?
  validates_uniqueness_of   :login, :email, :case_sensitive => false, :if => :openid?
(中略)
  validates_uniqueness_of :openid_url, :on => :create, :unless => :openid?
  validates_presence_of   :openid_url, :unless => :openid?

な、感じでやればとりあえずよくなる。

とりあえずね。とりあえず。

あとpassword_required?もちょっとだけ手を入れる

    def password_required?
      if openid? then
        crypted_password.blank? || !password.blank? 
      else
        openid?
      end
    end

すんません。頑張ります><

これで一応両対応

http://localhost:3000/login/signup

から普通にサインアップ

http://localhost:3000/openid/

からOpenidログイン

usersに書かれる。

openid_controllerでのログイン処理

def complete

#中略

  when OpenID::Consumer::SUCCESS

  #中略
  #OpenID::Consumer::SUCCESSの最後で

      #サイト側の認証
      @user = User.get(oidresp.identity_url)
      if @user.blank? then
        @user = User.new(:openid_url => oidresp.identity_url)
        @user.save
      end
      self.current_user = @user
            
      redirect_to :action => 'mypage/top', :action => "index"

[]VMwareCentOSsendmailから外にメールだす

1. /etc/mail/sendmail.mc 中、「DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA')」をコメントアウト

http://q.hatena.ne.jp/1179711865

の部分だけまねしたら出て行った。

[]acts_as_authenticatedとrole_requirementでロール付きの認証。

消えちゃったよ。。

はてなダイアリー素人なので書いたのをなんか間違って消してしまった。。orz

後半だけクリップボードに残ってた。orz

なので、書き直した前半は適当。

acts_as_authenticatedをインストール

$ ruby script/plugin discover
$ ruby script/plugin install acts_as_authenticated

ジェネってmigration

$ ./script/generate authenticated user account
$ rake db:migrate

その他の機能はあとで

メール認証だの、アクティベーションだのはまた今度。

ログインが必要なコントローラ

before_filter :login_requiredで認証箇所のコントロール

class HogeController < ApplicationController
  include AuthenticatedSystem
  before_filter :login_required, :except => [:nologin]
  def index
    #ログイン必要
  end
  
  def nologin
    #ログイン不要
  end
  
end

ロールを追加。

どうせ必要なので。

Acts_as_authenticatedにRole機能を追加する,RoleRequirementっーのがあるみたい。

インストールしる。

$ script/plugin install http://rolerequirement.googlecode.com/svn/tags/role
_requirement/
+ ./ChangeLog
+ ./MIT-LICENSE
+ ./README
+ ./generators/role/role_generator.rb
+ ./generators/role/templates/001_add_role_to_users_migration.rb.erb
+ ./generators/role/templates/_user_functions.erb
+ ./generators/role_generator_helpers.rb
+ ./generators/roles/roles_generator.rb
+ ./generators/roles/templates/001_roles_migration.rb.erb
+ ./generators/roles/templates/_user_functions.erb
+ ./generators/roles/templates/role_model.rb.erb
+ ./generators/roles/templates/roles.yml
+ ./generators/roles/templates/roles_users.yml
+ ./generators/roles/templates/users_admin_fixture_with_roles.yml
+ ./generators/shared_templates/hijacker.rb
+ ./generators/shared_templates/role_requirement_system.rb.erb
+ ./generators/shared_templates/role_requirement_test_helper.rb.erb
+ ./init.rb
+ ./test/authenticated_system.rb
+ ./test/controller_stub.rb
+ ./test/functional/test_role_controller.rb
+ ./test/test_helper.rb
+ ./test/user_stub.rb

generate

Role:ロールのモデル名 User:ユーザのモデル名

(ユーザがいくつもロールを持つ:多対多)

script/generate roles Role User

(ユーザは一種類のロールしか持たない:一対多)

script/generate role User

多対多で作っとく。

$ script/generate roles Role User
Generating Role against User
Added the following to the top of app/models/user.rb:



  # ---------------------------------------
  # The following code has been generated by role_requirement.
  # You may wish to modify it to suit your need
  has_and_belongs_to_many :roles

  attr_protected :roles


  # has_role? simply needs to return true or false whether a user has a role or not.
  # It may be a good idea to have "admin" roles return true always
  def has_role?(role_in_question)
    @_list ||= self.roles.collect(&:name)
    return true if @_list.include?("admin")
    (@_list.include?(role_in_question.to_s) )
  end
  # ---------------------------------------




Added ApplicationController include to /home/xxxx/dev/rails/auth_test/app/controllers/application.rb
Added RoleRequirement include to /home/xxxx/dev/rails/auth_test/app/controllers/application.rb
Added RoleRequirementTestHelper include to /home/xxxx/dev/rails/auth_test/test/test_helper.rb
      create  test/fixtures/roles_users.yml
      create  test/fixtures/roles.yml
      create  app/models/role.rb
      create  lib/role_requirement_system.rb
      create  lib/role_requirement_test_helper.rb
      create  lib/hijacker.rb
      exists  db/migrate
      create  db/migrate/002_create_roles.rb

migrate

DB反映

$ rake db:migrate
(in /home/coek/dev/rails/auth_test)
== 2 CreateRoles: migrating ===================================================
-- create_table("roles")
   -> 0.1138s
-- create_table("roles_users", {:id=>false})
   -> 0.0181s
-- add_index("roles_users", "role_id")
   -> 0.0337s
-- add_index("roles_users", "user_id")
   -> 0.0298s
== 2 CreateRoles: migrated (0.1980s) ==========================================

モデルを定義

Roleモデルにhabtmを書き足す

has_and_belongs_to_many :users

ロール設定の画面scaffold

    • skip-migrationつけて
$ ruby script/generate scaffold role --skip-migration
      exists  app/models/
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/roles
      exists  app/views/layouts/
      exists  test/functional/
      exists  test/unit/
      create  app/views/roles/index.html.erb
      create  app/views/roles/show.html.erb
      create  app/views/roles/new.html.erb
      create  app/views/roles/edit.html.erb
      create  app/views/layouts/roles.html.erb
      create  public/stylesheets/scaffold.css
  dependency  model
      exists    app/models/
      exists    test/unit/
      exists    test/fixtures/
        skip    app/models/role.rb
      create    test/unit/role_test.rb
        skip    test/fixtures/roles.yml
      create  app/controllers/roles_controller.rb
      create  test/functional/roles_controller_test.rb
      create  app/helpers/roles_helper.rb
       route  map.resources :roles

スキーマ情報とらないからviewをチョコチョコ自分でなおして。。

とりあえず、adminとuserを作っておく。

試してみる

さっき作ったroles_controllerに

require_role "admin"

書いてみて、ログインしないでアクセスすると。ログイン画面に飛ばされる

adminロールを持ってないユーザーでログインしてアクセスすると、画面真っ白。。

画面真っ白がヘボイ

http://d.hatena.ne.jp/clayfish/20080101/1199195090

を参考に

applicationコントローラーに手入れるのめんどかったので

とりあえずリダイレクトだけされすようにした。

/lib/role_requirement_system.rb L110

    def access_denied
      if logged_in?
        #render :nothing => true, :status => 401
        redirect_to("/")
        return false
      else
        super
      end
    end

ロールがある場合も試す。

とりあえずconsoleでロールを与える

$ ruby script/console
Loading development environment (Rails 2.0.2)
>>
?>
?> @user = User.find_by_login('admin')
=> #<User id: 2, login: "admin", email: "xxxx@xxxxx", crypted_password: "xxxxxx", salt: "xxxxxxxx", created_at: "2008-02-12 19:35:08", updated_at: "2008-02-12 19:35:08", remember_token: nil, remember_token_expires_at: nil>
>> @user.roles << Role.find_by_name('admin')
=> [#<Role id: 1, name: "admin">]
>> @user.save
=> true
>>

で、さっきのroles_controllerにアクセスしたら、アクセスできた。

参考

http://blog.japan.zdnet.com/yoshimi/a/2007/10/acts_as_authent.html

http://eringi.com/weblog/archives/2007/07/acts_as_authenticated.html

http://idm.s9.xrea.com/ratio/2007/09/Monthly.html#id_20acts_as_authenticatede381a8e381af

http://chn.co.jp/blog/20080107.html#p08

http://d.hatena.ne.jp/clayfish/20080101/1199195090