2008年12月10日水曜日

あぁあ〜...

イヤなことに気が付いちゃった...

(略)
CURRENT FEATURES
(略)
  - Authentication Plugins 
    - restful_authentication, open_id_authentication, role_requirement, recaptcha
  - UI Plugins 
    - custom-err-msg, permalink_fu, uberkit, will_paginate
  - Debug Plugins 
    - exception_logger, rails-footnotes, query_analyzer, query_stats, rows_logger
  - Development and Performance Plugins
    - auto_migrations, pseudo_cursors
  - Testing 
    - rspec, rspec_rails
  - Gems
    - ruby-openid-2.1.2
(略)
え?
何それ?
ゴメン、云ってる意味が解らない。
聞きたくない。
聞きたくないったら、聞きたくないwww

あ゛あ゛あ゛ー解らないったら解らないっ

ああっ、もうっ
ちょっと気分転換するっ

ついでに、もう少しマシなブログ探すwww

コードのブラッシュ・アップ

まあ、職安行って、失業認定とやらを申請してきた訳ですが。
次回の受給金額が、年末年始の絡みもあり、21日分でして。

あの...家賃と光熱費とケータイ代で、消えちゃうんですがwww


まあ、そんなことは置いといて。

これまでのコードを、ちょっとキレイにしちゃおうかな、と。

まず、new_user_pathなんて形でリンク先のurlをせいせいしているところが幾つかあるんだけど、これを、signup_pathに書き換えた。
だって、sessions/newは、login_pathになってるんだよ?

だったら、users/newは、signup_pathだよねぇ?w

あと、アタシゃ古いタイプのコード書きのようでして、やっぱり、メソッドの後ろの引数には、括弧が付いていないと、気持ちが悪いのよ。
なんで、片っ端から、括弧付けw

なんて無駄なwww
つうか、restful_authenticationの制作者様も、コーディング・スタイルが一貫してないぞwww

もちろん、bells and whitslesの人もだwww

でも、基本的に、コーディング・スタイルは、Rubyコーディング規約に準ずることにしたよ。

他人の決めたルールに則るのって、ラクチンだよねw

だがしかし、外すところでは、外すよ。
例えば、ファイル名は、「-」じゃなくって、「_」繋ぎにするとか。
まあ、これも、railsがそうなってるから、なんだけどね;-p

メソッドの引数に関しても、宣言くさいもの、
  • include、require
  • belongs_to、has_many、has_one、has_and_belongs_to_many
  • validate_hogehoge
  • attr_hogehoge
なんかは、敢えて()を付けないことにした。
特に、validate_hogehogeは、付いてない方が、可読性が良い気がする。
良い気がすれば、おk。wwww


それから、user_controller.rbのnewアクションに付けてた、current_user?での分岐を外した。
before_filterでかかってるからね。
-    if logged_in?
-      redirect_to(:controller => "users", :action => "show", :id => current_user.id)
-    else
-      @user = User.new
-    end
+    @user = User.new

ん。

2008年12月9日火曜日

どうよ? じゃねえよwww

いきなりレイアウト崩れてんじゃねぇよwww->blogger.com
ホンキ、使えねえなwww

また引っ越しちゃうぞwwwww


で。
メソッド、全然足りてねえでやんのwww
lib/authentication_system.rb
+    def permission_denied
+      respond_to do |format|
+        format.html do
+          #Put your domain name here ex. http://www.example.com
+          domain_name = "http://localhost:3000"
+          http_referer = session[:refer_to]
+          if http_referer.nil?
+            store_referer
+            http_referer = ( session[:refer_to] || domain_name )
+          end
+          flash[:error] = "You don't have permission to complete that action."
+          #The [0..20] represents the 21 characters in http://localhost:3000
+          #You have to set that to the number of characters in your domain name
+          if http_referer[0..20] != domain_name  
+            session[:refer_to] = nil
+            redirect_to root_path
+          else
+            redirect_to_referer_or_default(root_path)  
+          end
+        end
+        format.xml do
+          headers["Status"]           = "Unauthorized"
+          headers["WWW-Authenticate"] = %(Basic realm="Web Password")
+          render :text => "You don't have permission to complete this action.", :status => '401 Unauthorized'
+        end
+      end
+    end

+    def store_referer
+      session[:refer_to] = request.env["HTTP_REFERER"]
+    end

+    def redirect_to_referer_or_default(default)
+      redirect_to(session[:refer_to] || default)
+      session[:refer_to] = nil
+    end

ん。
んで、http://localhost:3000/usersに行ってみると...

NoMethodError in Users#index
Showing app/views/users/_user.html.erb where line #4 raised:

undefined method `enabled' for #

!?
なんだよ? "enabled"って?
で、見てみたら、どうも、メソッドではなくって、スキーマくさい。
どうも、今のバージョンのrestrul_authentication --aasmだと、enabledじゃなくって、statusになってるっぽい。
んじゃあ、ってんで、書き換えよう。
app/views/users/_user.html.erb

-  <td><%= user.enabled ? 'yes' : 'no' %>
+  <td><%= user.state == "active"  ? 'yes' : 'no' %>

-      <% if user.enabled %>
+      <% if user.state == "active" %>
ん。動いた。
動いたことは動いたんだけど、ブラウザで表示して、「enable」のリンクをクリックしても、何の変化もなし。

んー...
っていうか、enableなんてメソッド、作ってないわwww
じゃあ、移植しましょう、ってことで。
でも、メソッド名は変えるよ。それっぽく。
app/controllers/users_controller.rb
+  def forcible_activate
+    @user = User.find(params[:id])
+    if @user.update_attribute(:state, "active")
+      flash[:notice] = "User activated"
+    else
+      flash[:error] = "There was a problem activating this user."
+    end
+      redirect_to :action => 'index'
+  end
あと、administrator_role_requiredの:enabelも書き換えなきゃな。
-before_filter :administrator_role_required, :only => [:index, :destroy, :enable]
+before_filter :administrator_role_required, :only => [:index, :destroy, :forcible_activate]

んで、ルーティングも変更。
config/routes.rb
+  map.forcible_activate '/forcible_activate/:id', :controller => "users", :action => "forcible_activate"

んで、viewも変更。
app/views/users/_user.html.erb
-  <td><%= user.enabled ? 'yes' : 'no' %>
-    <% unless user == current_user %>
-      <% if user.enabled %>
-        <%= link_to('disable', user_path(user.id), :method => :delete) %>
-      <% else %>
-        <%= link_to('enable', enable_user_path(user.id), :method => :put) %>
-      <% end %>
-    <% end %>
-  </td>

+  <td>
+    <%= h user.state %>
+    <% unless user == current_user %>
+      <% if user.state == "active" %>
+        <%= link_to('inactivate', user_path(user.id), :method=> :delete) %>
+      <% else %>
+        <%= link_to('activate', forcible_activate_path(user.id), :method => :put) %>
+      <% end %>
+    <% end %>
+  </td>
よし。これで、ユーザ管理画面チックなものが出来たよね?:-)

2008年12月8日月曜日

じゃあ、role機能でもやっちゃいますか。

職安にって、職業相談とやらを受けるも、なんか、ちょろっと話をしただけで終わったぞ?
大丈夫か? 俺www

んで、帰りにブックオフで「きのう何食べた? 2」と「不思議な少年 7」を買ってくる。
マンガ買うなんて、まだ余裕あるつもりなのか? 俺www


んじゃあ、もう一度、例のページの頭に戻って、roleに関するところのみピックアップして、やっていきますか。

で、ずうっと飛ばして、
$ script/generate scaffold Role rolename:string
$ script/generate model Permission
から。
つうか、scaffold、いるのか?www

んで、db/migrate/*数字*_create_permissions.rb。
...ん?
って、これ、adminのデータ、作ってるよね?
じゃあ、その部分、飛ばして、別に作ろう。
class CreatePermissions <>
def self.up
create_table :permissions do |t|
t.integer :role_id, :user_id, :null => false
t.timestamps
end
end

def self.down
drop_table :permissions
end
end
よし。

アレ?
*数字*_create_roles.rb、編集してないよね?
つうか、ここにも載ってないよね?
じゃあ、最新版restful_authentication_tutorialの方から拾ってくる方面で。
db/migrate/*数字*_create_roles.rb。
def self.up
create_table "roles" do |t|
t.string :name
end
# generate the join table
create_table "roles_users", :id => false do |t|
t.integer "role_id", "user_id"
end
add_index "roles_users", "role_id"
add_index "roles_users", "user_id"
end

def self.down
drop_table "roles"
drop_table "roles_users"
end
ありゃ?
scaffoldの時にはrolenameだったのに、こっちはnameになってるな...
まあ、いいやwww
こっちを採用。
Role.nameの方が、Role.rolenameより自然だよね?

混同しそうだけどwwwwww

んじゃあ、modelの関連付け、しましょうか。
app/models/role.rb
class Role <>
has_many :permissions
has_many :users, :through => :permissions
end
app/models/permission.rb
class Permission <>
belongs_to :user
belongs_to :role
end
んで、app/models/user.rbにも関連付けを。
+ has_many :permissions
+ has_many :roles, :through => :permissions
これで、userとroleとpermissionが結びついたよね?
ああ、あと、find_for_forget?とhas_role?メソッドも追加してるね。
+ def self.find_for_forget(email)
+ find :first, :conditions => ['email = ? and activated_at IS NOT NULL', email]
+ end
+
+ def has_role?(rolename)
+ self.roles.find_by_name(rolename) ? true : false
+ end
次は、filter用のメソッドの追加。
lib/authenticated_system.rb
+ def role_requiered(role)
+ unless logged_in? && @current_user.has_role?(role)
+ if logged_in?
+ permission_denied
+ else
+ store_referer
+ access_denied
+ end
+ end
+ end
+
+ def administrator_role_required
+ role_requiered('administrator')
+ end
メソッド名は、それぞれ、っぽく変えといた;-p

んで、app/controllers/users_controller.rbにbefore_filterする。
+ before_filter :administrator_role_required, :only => [:index, :destroy, :enable]

んじゃあ、app/controllers/roles_controller.rbまで飛ばして。
class RolesController <>
before_filter :administrator_role_required
def index
@user = User.find(params[:user_id])
@all_roles = Role.find(:all)
end
def update
@user = User.find(params[:user_id])
@role = Role.find(params[:id])
unless @user.has_role?(@role.name)
@user.roles << @role
end
redirect_to :action => 'index'
end
def destroy
@user = User.find(params[:user_id])
@role = Role.find(params[:id])
if @user.has_role?(@role.name)
@user.roles.delete(@role)
end
redirect_to :action => 'index'
end

end
そういえば、respond_toって、いままで付けてなかったな...

まあ、いいやwww
また今度。

次。roleのview。
scaffoldで生成したものの内、index以外はいらないんで、削除。
んで、partial作る。
app/views/roles/_role.html.erb
<li>
<%= role.name %>
<% if @user.has_role?(role.name) %>
<%= link_to 'remove role', user_role_url(:id => role.id, :user_id => @user.id), :method => :delete %>
<% else %>
<%= link_to 'assign role', user_role_url(:id => role.id, :user_id => @user.id), :method => :put %>
<% end %>
</li>
んで、app/views/roles/index.html.erb
<h2>Roles for <%=h @user.nickname %></h2>
<h3>Roles assigned:</h3>
<ul><%= render :partial => 'role', :collection => @user.roles %></ul>
<h3>Roles available:</h3>
<ul><%= render :partial => 'role', :collection => (@all_roles - @user.roles) %></ul>
おk。

で、今まで敢えて作ってこなかったviewを。
まず、app/users/_user.html.erb
<tr class="<%= cycle('odd', 'even') %>">
<td><%=h user.nickname %></td>
<td><%=h user.email %></td>
<td><%= user.enabled ? 'yes' : 'no' %>
<% unless user == current_user %>
<% if user.enabled %>
<%= link_to('disable', user_path(user.id), :method => :delete) %>
<% else %>
<%= link_to('enable', enable_user_path(user.id), :method => :put) %>
<% end %>
<% end %>
</td>
<td><%= link_to 'edit roles', user_roles_path(user) %>]</td>
</tr>
んで、app/views/users/index.html.erb。
<h2>All Users</h2>
<table>
<tr>
<th>Username</th>
<th>Email</th>
<th>Enabled?</th>
<th>Roles</th>
</tr>
<%= render :partial => 'user', :collection => @users %>
</table>
おk。

後は、adminユーザの初期データのマイグレーションですか。
これは、最新版restful_authentication_tutorialから持ってきたものを基にしよう。
$ script/generate migration AddAdminUserToUser
で、
db/migrate/*数字*_add_admin_user_to_user.rb
class AddAdminUserToUser <>
def self.up
#Be sure to change these settings for your initial admin user
unless User.find_by_email("email@hogehoge.com")
User.create(
:nickname => "admin",
:family_name => "管理者",
:middle_name => "ザ",
:given_name => "アドミン",
:password => "password",
:password_confirmation => "password",
:email => "email@hogehoge.com")
end
#Admin role name should be "admin" for convenience
unless Role.find_by_name("administrator")
Role.create(
:name => "administrator")
end

admin_user = User.find_by_email("email@hogehoge.com")
admin_role = Role.find_by_name("administrator")
admin_user.state = "active"
admin_user.activated_at = Time.now.utc
admin_user.roles <<>
admin_user.save(false)
end

def self.down
admin_user = User.find_by_email("email@hogehoge.com")
admin_role = Role.find_by_name("administrator")
admin_user.roles = []
admin_user.save
admin_user.destroy
admin_role.destroy
end
end
どうよ?


こんな感じじゃ良くなかったwww


いやいや、passwords_controller.rbの中で、



before_filter :not_logged_in_required, :only => [:new, :create]



ってしているけど、"not_logged_in_required"ってメソッド、どこかにあるのか? と思ってたら、lib/authenticated_system.rbに書くんだなwww


で、restful_authentication_tutorialの方を見てみたら、メソッドの名前を変えて、新たに作ってあったから、それ使った。


lib/authenticated_system.rb



# Prevents logged in users from accessing actions reserved for


# non-authenticated users such as the login or signup forms


# Make sure to redirect to a path they can access to avoid an infinite loop


def login_prohibited


!logged_in? || (redirect_to root_path)


end



んで、passwords_controller.rbとaccounts_controller.rbを変更した。



/app/controllers/passwords_controller.rb



- before_filter :not_logged_in_required, :only => [:new, :create]



+ before_filter :login_prohibited, :only => [:new, :create]


/app/controllers/accounts_controller.rb


- before_filter :not_logged_in_required, :only => :show


+ before_filter :login_prohibited, :only => :show






んじゃあ、sessions_controllerとusers_controllerも書き換えれるよね。


logged_in?で見ていたところも、login_prohibitedをbefore_filterしちゃえばいいんだもんな。


と思って、やってみたら、sessions_controllerは、ダメだwww


だって、root_pathを、sessions/newにしてるんだもんwww


app/controllers/sessions_controller.rb




- skip_before_filter :login_required


+ skip_before_filter :login_required, :only => [:new, :create]




後々、root_pathを変えることになったなら、その時は考えましょう;-p


app/controllers/users_controller.rb



skip_before_filter :login_required, :only => [:new, :create, :activate, :suspend, :unsuspend, :destoy, :purge]

+ before_filter :login_prohibited, :only => [:new, :create, :activate, :suspend, :unsuspend, :destoy, :purge]



おk。


あと、usersのview、全然作ってないじゃんwwww


とりあえず、内容はあまり考えずに、プレース・ホルダとして、ベタバリしましょうかwww


app/views/users/edit.html.erb




<h2>Edit Your Account</h2>


<p><%= link_to 'Show Profile', user_path(@user) %> | <%= link_to 'Change Password', change_password_path %></p>


<%= error_messages_for :user %>


<% form_for :user, :url => user_url(@user), :html => { :method => :put } do |f| %>


<p>Email:<br /><%= f.text_field :email, :size => 60 %></p>


<%= submit_tag 'Save' %>


<% end %>



って、これじゃあ、メールアドレスしか変更出来ねぇwww


ん、あとで考える。


index.html.erbと_user.html.erbは、また今度。


role絡みのロジック入れないと、エラー返ってくるし。


new.html.erbとshow.html.erbは、前に書いたヤツのほうが、イイ感じ;-p


あと、userモデルにpassword_reset_codeのカラム、追加するの忘れてたwww



$ script/generate migration AddColumnPassWordResetCodeToUser password_reset_code:string



で、




class AddColumnPassWordResetCodeToUser <>

def self.up


add_column :users, :password_reset_code, :string, :limit => 40


end


def self.down


remove_column :users, :password_reset_code


end


end





んな感じで。





2008年12月7日日曜日

とりあえず、パスワードを忘れた時の処理を追加(?)

とりあえず、Restful Authentication with all the bells and whistlesを、順番に追っかけてみましょうかね。

app/models/user.mailer.rbに、
  • forgot_password
  • reset_password
の、2つのメソッドを追加。
こんな感じ。
  def forgot_password(user)
    setup_email(user)
    @subject    += 'You have requested to change your password'
    @body[:url]  = "http://localhost:3000/reset_password/#{user.password_reset_code}"
  end

  def reset_password(user)
    setup_email(user)
    @subject    += 'Your password has been reset.'
  end
はい。
次に、app/models/user_observer.rbに追記。
UserMailer.deliver_forgot_password(user) if user.recently_forgot_password?
UserMailer.deliver_reset_password(user) if user.recently_reset_password?
で、次に、って、アレ?
permission云々って、書いてあるな...

んー、飛ばすwww

で、app/models/user.rbに
  • forgot_password
  • reset_password
  • recently_forgot_password?
  • recently_reset_password?
  • make_password_reset_code (protected)
を追加。
以下、コード。 
 # Forgot password
  def forgot_password
    @forgotten_password = true
    self.make_password_reset_code
  end
  # Reset password
  def reset_password
    # First update the password_reset_code before setting the
    # reset_password flag to avoid duplicate email notifications.
    update_attribute(:password_reset_code, nil)
    @reset_password = true
  end

  #used in user_observer
  def recently_forgot_password?
    @forgotten_password
  end
 
  def recently_reset_password?
    @reset_password
  end
(略)
protected
(略)
    def make_password_reset_code
        self.password_reset_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
    end
こんな感じですか。
次。lib/authenticated_system.rbを書き換えてるようですが、permission絡みみたいなんで、飛ばす。

次は、app/controller/users_controller.rb。
とりあえず、indexとeditとupdateのメソッドの追加。
  def index
    @users = User.find(:all)
  end

  # render edit.html.erb
  def edit
    @user = current_user
  end

  def update
    @user = User.find(current_user)
    if @user.update_attributes(params[:user])
      flash[:notice] = "User updated"
      redirect_to :action => 'show', :id => current_user
    else
      render :action => 'edit'
    end
  end
ほい。
updateは、viewが無いんだね。

そりゃそうだwww

次は、app/controllers/sessions_controller.rb。
...なんかいるか?
...飛ばすwww

次。
ん?
passwords_controller.rb?
accounts_controller.rb?
roles_controller.rb?

ん?
飛ばすwww

んで?
application.html.erbも、飛ばす。
なんか、role絡みのコードが入ってるし。後だね、後。

次は、app/views/passwords/edit.html.erb。
あれ?
app/views/passwords/new.html.erbとapp/views/accounts/edit.html.erbも、とりあえず、飛ばそう。

あ、そうか!
これ、password変更のロジックだな。

おk。後回しwww

んで、...
なんか、role関係のviewが続くんで、まとめて飛ばし。

次。
やっとだよwww
app/views/sesisons/new.html.erb。
まあ、別にどうでも良いんだけど、とりあえず、users_controllerのnewアクションへのリンクを足す。

new_user_pathなんて云う書き方、今、はじめて気が付いたwww
"アクション名_コントローラ名(単数系)_path"で、そのurlが生成できるんだな。
イヤ、便利っぽくない?www
後で書き換えよう:-)

app/views/user_mailer/activation.erb
<%= h @user.real_name %>, your account has been activated.  Welcome aboard!

  <%=h @url %>
@user.loginは、loginを削除してしまっているんで、real_nameメソッドを使って、本名を使うようにした。
後述のforgot_password.erbとreset_password.erbも一緒。

app/views/user_mailer/forgot_password.erb
<%= h @user.real_name %>, your account has been activated.  To visit the site, follow the link below:
<%= @url %> 
app/views/user_mailer/reset_password.erb
<%= h @user.real_name %>, Your password has been reset

こんな感じ?

app/views/user_mailer/signup_notification.html.erbは、real_nameとemailを使って、passwordは送らないようにしましょうか。再発行できるんだから、ね?
Your account has been created.

  Real Name: <%= h @user.real_name %>
  Email: <%= h @user.email %>
  Password: <%= h @user.password %>

Visit this url to activate your account:

  <%= h @url %>

って、あれ?
だとすると、さっき飛ばしたロジック、入れとかないと、マズいよね?
じゃあ、入れましょうか。
$ script/generate controller Passwords
$ script/generate controller Accounts
んで、
app/controllers/passwords_controller.rb
class PasswordsController <>
   skip_before_filter :login_required :only => [:new, :creat]
  :not_logged_in_required, :only => [:new, :create]
  
  # Enter email address to recover password 
  def new
  end
 
  # Forgot password action
  def create    
    return unless request.post?
  if @user = User.find_for_forget(params[:email])
      @user.forgot_password
      @user.save      
      flash[:notice] = "A password reset link has been sent to your email address."
      redirect_to login_path
    else
      flash[:notice] = "Could not find a user with that email address."
      render :action => 'new'
    end  
  end
  
  # Action triggered by clicking on the /reset_password/:id link recieved via email
  # Makes sure the id code is included
  # Checks that the id code matches a user in the database
  # Then if everything checks out, shows the password reset fields
  def edit
    if params[:id].nil?
      render :action => 'new'
      return
    end
    @user = User.find_by_password_reset_code(params[:id]) if params[:id]
    raise if @user.nil?
  rescue
    logger.error "Invalid Reset Code entered."
    flash[:notice] = "Sorry - That is an invalid password reset code. Please check your code and try again. (Perhaps your email client inserted a carriage return?)"
    #redirect_back_or_default('/')
    redirect_to new_user_path
  end
    
  # Reset password action /reset_password/:id
  # Checks once again that an id is included and makes sure that the password field isn't blank
  def update
    if params[:id].nil?
      render :action => 'new'
      return
    end
    if params[:password].blank?
      flash[:notice] = "Password field cannot be blank."
      render :action => 'edit', :id => params[:id]
      return
    end
    @user = User.find_by_password_reset_code(params[:id]) if params[:id]
    raise if @user.nil?
    return if @user unless params[:password]
      if (params[:password] == params[:password_confirmation])
      #Uncomment and comment lines with @user to have the user logged in after reset - not recommended
        #self.current_user = @user #for the next two lines to work
        #current_user.password_confirmation = params[:password_confirmation]
        #current_user.password = params[:password]
        #@user.reset_password
    #flash[:notice] = current_user.save ? "Password reset" : "Password not reset"
    @user.password_confirmation = params[:password_confirmation]
    @user.password = params[:password]
    @user.reset_password        
    flash[:notice] = @user.save ? "Password reset." : "Password not reset."
      else
        flash[:notice] = "Password mismatch."
        render :action => 'edit', :id => params[:id]
      return
      end  
      redirect_to login_path
  rescue
    logger.error "Invalid Reset Code entered"
    flash[:notice] = "Sorry - That is an invalid password reset code. Please check your code and try again. (Perhaps your email client inserted a carriage return?)"
    redirect_to new_user_path
  end
    
end
ほぼベタ張りwww
しっかし、長えな、これwww
ロジックがどう動いているのか、サッパリ理解してないぞwww

続いて、app/controllers/accounts_controller.rb。
class AccountsController <>
  skip_before_filter :login_required :only => [:show]
  before_filter :not_logged_in_required, :only => :show
 
  # Activate action
  def show
    # Uncomment and change paths to have user logged in after activation - not recommended
    #self.current_user = User.find_and_activate!(params[:id])
  User.find_and_activate!(params[:id])
    flash[:notice] = "Your account has been activated! You can now login."
    redirect_to login_path
  rescue User::ArgumentError
    flash[:notice] = 'Activation code not found. Please try creating a new account.'
    redirect_to new_user_path 
  rescue User::ActivationCodeNotFound
    flash[:notice] = 'Activation code not found. Please try creating a new account.'
    redirect_to new_user_path
  rescue User::AlreadyActivated
    flash[:notice] = 'Your account has already been activated. You can log in below.'
    redirect_to login_path
  end
 
  def edit
  end
  
  # Change password action  
  def update
  return unless request.post?
    if User.authenticate(current_user.email, params[:old_password])
      if ((params[:password] == params[:password_confirmation]) && !params[:password_confirmation].blank?)
        current_user.password_confirmation = params[:password_confirmation]
        current_user.password = params[:password]        
    if current_user.save
          flash[:notice] = "Password successfully updated."
          redirect_to root_path #profile_url(current_user.login)
        else
          flash[:error] = "An error occured, your password was not changed."
          render :action => 'edit'
        end
      else
        flash[:error] = "New password does not match the password confirmation."
        @old_password = params[:old_password]
        render :action => 'edit'      
      end
    else
      flash[:error] = "Your old password is incorrect."
      render :action => 'edit'
    end 
  end
  
end
つうか、ね?
newアクション、いるのか?www
あと、User.authenticateでcurrent_user.loginを放り込んでるから、current_user.emailに変更ね。

んじゃあ、viewも作りましょうか。
app/views/passwords/edit.html.erb
<% form_tag url_for(:action => "update", :id => params[:id]) do %>
    Password:<br />
    <%= password_field_tag :password %><br />
    Confirm Password:<br />
    <%= password_field_tag :password_confirmation %><br />
    <%= submit_tag "Reset Your Password" %>
<% end %>

app/views/passwords/new.html.erb
<h2>Forgot Password</h2>
<% form_tag url_for(:action => 'create') do %>
    What is the email address used to create your account?<br />
    <%= text_field_tag :email, "", :size => 50 %><br />
    <%= submit_tag 'Reset Password' %>
<% end %>

app/views/accounts/edit.html.erb
<% form_tag url_for(:action => "update") do %>
  <p><label for="old_password" class="block">Old Password</label><br />
  <%= password_field_tag 'old_password', @old_password, :size => 45 %></p>
 
  <p><label for="password" class="block">New Password</label><br />
  <%= password_field_tag 'password', {}, :size => 45 %><br />
  <small>Between 4 and 40 characters</small></p>
 
  <p><label for="password_confirmation"  class="block">Confirm new password</label><br />
  <%= password_field_tag 'password_confirmation', {}, :size => 45 %></p>
 
  <%= submit_tag 'Change password' %>
 
<% end %>
な感じで。
何も変えてないぞwwww

んで、config/routes.rbに以下を追記。
map.forgot_password '/forgot_password', :controller => 'passwords', :action => 'new'
map.reset_password '/reset_password/:id', :controller => 'passwords', :action => 'edit'
map.change_password '/change_password', :controller => 'accounts', :action => 'edit'

map.resources :users, :member => { :enable => :put } do |users|
 users.resource :account
 users.resources :roles
end

map.resource :password
こんな感じで、いいんじゃね?
ね?

じゃあ、restful_authenticationで作ったUserモデルの機能拡張をしようか。

参考にするのは、主に以下のページ。
後者は、前者の基になったページのようですな。
で、後者は、既にアップデートされているんだけども。
これが、また、もう、全く別物って云うくらいにいじられまくりwww
github.comに、restful_authentication_tutorialてな形で、プロジェクトが置いてあるんだけど。

イヤ、もう、全く別物www

そんなややこしいのの中を見てコードを理解するのなんか、イヤじゃwww

という訳で、上記のページを参考にしながら、徐々に機能をアップデートしていきましょうよ。

Blogger、使いにくい...

なに、このクソシステム?www

テキストのエスケープとか、されないし。
blockquoteあっても、pre無いし。

コード書いて貼り付けるのには、あんまりにも手間暇が掛かるんですがwww

笑いごっちゃねえよっ!!


...やばい、はてなの方がマシに思えてきたwww
はてなは、記事の扱いが、日付単位になっている事以外を除けば、そこそこ使いやすいんだよね。
少なくとも、コードを貼り付ける分には。

でも、戻るのは、なあ...

「オンナのダメさ加減に嫌気が差して、別れて、他のオンナと付き合っては見ましたが、やっぱりお前がサイコーだったよ」って?www
んで、
「やっぱり、お前とやり直したいんだ」って?wwwwwwww


ねえよwwwwwwwwwwwwww

とりあえず、Userモデルの初期データを放り込むマイグレーションを作るとしようか。

まあ、面倒くさい事を何度もやるのは、馬鹿馬鹿しい訳で。
Userモデルの初期データを、いちいち登録して、認証して、なんて、面倒だよね。

バカなの? ry

な感じでwww

で、マイグレーション。
$ script/generate migration AddTestDataToUser
内容は、こんな感じ。
class AddTestDataToUser < ActiveRecord::Migration
  def self.up
    down

    User.create(
      :nickname => "ほげほげ",
      :family_name => "名字",
      :middle_name => "",
      :given_name => "名前",
      :password => "pass",
      :password_confirmation => "pass",
      :email => "who@where.com")
    User.create(
      :nickname => "ふがふが",
      :family_name => "みょうじ",
      :middle_name => "ミドルネーム",
      :given_name => "なまえ",
      :password => "pass",
      :password_confirmation => "pass",
      :email => "dare@soko.com")

    User.update_all("state = 'active'")
  end

  def self.down
    User.delete_all
  end
end
いやあ、User.createが、DBに直接、値を放り込むんじゃなくって、Userモデルのcreateを介するとは、思いも寄りませんでした。
どっぷりはまりましたよ、半日www
あと、update_allではなくって、upate()を使うと、なぜかアップデートできない。
なんでだろ?
User.update(1, :state => "active")
なんか、書き方、間違えてる?
script/consoleでやってみても、出来てないんだよね...

なんで?www

ユーザ・プロファイル画面を作る。

なんか、段々実況するのが面倒になってきたwww

つうか、ね?
コード書いてるより、ブログかいてる方が、時間がかかってる気がするんだけどwww

まあ、いいやwwwwww
今回は、
  • 姓とミドルネームと名を連結したものを「本名」として扱う
  • 姓とミドルネームと名のvalidation
  • app/views/users/newとshowのブラッシュ・アップ
な感じで。
diff。

app/models/user.rb

+  validates_presence_of     :family_name
+  validates_format_of       :family_name,     :with => Authentication.name_regex,  :message => :bad_name_message, :allow_nil => true
+  validates_length_of       :family_name,     :maximum => 100
+
+  validates_format_of       :middle_name,     :with => Authentication.name_regex,  :message => :bad_name_message, :allow_nil => true
+  validates_length_of       :middle_name,     :maximum => 100
+
+  validates_presence_of     :given_name
+  validates_format_of       :given_name,     :with => Authentication.name_regex,  :message => :bad_name_message, :allow_nil => true
+  validates_length_of       :given_name,     :maximum => 100

-  attr_accessible :email, :nickname, :password, :password_confirmation
+  attr_accessible :email, :nickname, :family_name, :middle_name, :given_name, :password, :password_confirmation

+  def real_name
+    name = family_name + " "
+    name += "\"#{middle_name}\" " unless middle_name.nil?
+    name += given_name
+    name
+  end

   protected

app/views/layouts/application.html.erb

 <% form_for :user, :url => users_path do |f| -%>
+<dl class="account">
+  <%= content_tag("dt", label_tag('email', t('actionview.label.common.email'))) %>
+  <%= content_tag("dd", f.text_field(:email)) %>
+  <%= content_tag("dt", label_tag('password', t('actionview.label.common.password'))) %>
+  <%= content_tag("dd", f.text_field(:password)) %>
+  <%= content_tag("dt", label_tag('password_confirmation', t('actionview.label.common.password_confirmation'))) %>
+  <%= content_tag("dd", f.text_field(:password_confirmation)) %>
+</dl>
 
-<p><%= label_tag 'nickname', t('actionview.label.common.nickname') %><br />
-<%= f.text_field 'nickname' %></p>
+<dl class="profile">
+  <%= content_tag("dt", label_tag('nickname', t('actionview.label.common.nickname'))) %>
+  <%= content_tag("dd", f.text_field(:nickname)) %>
+  <%= content_tag("dt", t('actionview.label.common.real_name')) %>
+  <dd>
+    <dd>
+      <%= content_tag("dt", label_tag('family_name', t('actionview.label.common.family_name'))) %>
+      <%= content_tag("dd", f.text_field(:family_name)) %>
+      <%= content_tag("dt", label_tag('middle_name', t('actionview.label.common.middle_name'))) %>
+      <%= content_tag("dd", f.text_field(:middle_name)) %>
+      <%= content_tag("dt", label_tag('given_name', t('actionview.label.common.given_name'))) %>
+      <%= content_tag("dd", f.text_field(:given_name)) %>
+    </dd>
+  </dd>
+</dl>
 
-<p><%= label_tag 'email', t('actionview.label.common.email') %><br/>
-<%= f.text_field :email %></p>
-
-<p><%= label_tag 'passoword', t('actionview.label.common.password') %><br/>
-<%= f.password_field :password %></p>
-
-<p><%= label_tag 'password_confirmation', t('actionview.label.common.password_confirmation') %><br/>
-<%= f.password_field :password_confirmation %></p>
-
<p><%= submit_tag t('actionview.submit.user.signup') %></p>
<% end -%>

app/views/users/show.html.erb

+<dl>
+  <%= content_tag("dt", t('actionview.label.common.nickname'), :class => "nickname") %>
+  <%= content_tag("dd", @user.nickname) %>
+  <%= content_tag("dt", t('actionview.label.common.real_name'), :class => "real_name") %>
+  <%= content_tag("dd", @user.real_name) %>
+</dl>

こんな感じか?
real_nameメソッドは、実は、www.railscast.comRefactoring User Name Part 1を参考にして作ったんだけど、でも、これ、modelでやるよりも、helperで、user.idを基にして、フルネーム作った方がいいような気がしないか?

まあ、ヨシとしよう;-p
困った時は、その時考えよう。

2008年12月6日土曜日

ちょっとルーティングを考える。

えーっと、とりあえず、"hogehoge"は、SNSです。
つうか、SNSになる予定です。

SNSの条件としては、いっぱいあるんだろうけど、とりあえず、
  • 登録しなければログインできない
  • ログインしなければコンテンツにはアクセスできない
というものがあるかと。

なんで、それに合わせて、ルーティングを考えましょうか。
条件になるのは、

  • ログインしていない状態ならば、/signup(/users/new)と/login(/session/new)以外は、全て / へリダイレクト
  • / は、/login(/sessions/new)
  • /users/user_idは、ユーザ・プロファイルを表示
  • ログインしている場合の / へのアクセスは、/users/user_idへ
ってな感じ?

で、app/controllers/application.rbに、before_filter :login_requiredをつけて、う〜ん、どうしよう...
actionに対応して、exceptは出来るけど、controllerに対応させるのは、出来ないよな...

と思っていたら、良いのを見つけました:-)
skip_before_filterなんていうメソッドがあるじゃないですか:-)

んで、こんな感じ。
diffで。

app/controllers/application.rb

+  before_filter :login_required

app/controllers/users_controller.rb

+  skip_before_filter :login_required, :only => [new:, :create, :activate, :suspend, :unsuspend, :destoy, :purge] 
 
+  #render show.rhtml
+  def show
+    @user = User.find(params[:id])
+  end

   def new
-    @user = User.new
+    if logged_in?
+      redirect_to(:controller => "users", :action => "show", :id => current_user.id)
+    else
+      @user = User.new
+    end
   end

app/controllers/sessions_controller.rb

+  skip_before_filter :login_required

   # render new.rhtml
   def new
+    if logged_in?
+      redirect_to(:controller => "users", :action => "show", :id => current_user.id)
+    end
   end
こんな感じで、おk?
users_controllerのskip_before_filter : login_requiredは、restful_authenticationが作ったactionだけに対応させた。
んで、ユーザ・プロファイル用に、users_controller.rbに、showを作ったよ。
で、sessions_controller.rbのnewアクションで、logged_in?して、合ってたら、current_userのidで、usersのshowアクションへリダイレクトする。
あと、users_controller.rbのnewアクションも、同じ事をするように。

おk?
おkでしょ?:-)

んで、諸々を書き換える。

emailで認証して、ニックネームを利用してウンヌンカンヌンにする為に、とりあえず、諸々書き換える。
あと、flash見たいんで、app/layouts/application.html.erbも書き換えた。
diff。

app/helpers/users_helper.rb

-    options.reverse_merge! :content_method => :login, :title_method => :login, :class => :nickname
+    options.reverse_merge! :content_method => :email, :title_method => :email, :class => :nickname

app/controllers/sessions_controller.rb

-      @login       = params[:login]
+      @login       = params[:email]

-    flash[:error] = "Couldn't log you in as '#{params[:login]}'"
-    logger.warn "Failed login for '#{params[:login]}' from #{request.remote_ip} at #{Time.now.utc}"
+    flash[:error] = "Couldn't log you in as '#{params[:email]}'"
+    logger.warn "Failed login for '#{params[:email]}' from #{request.remote_ip} at #{Time.now.utc}"

app/models/user.rb

-  attr_accessible :login, :email, :name, :password, :password_confirmation
+  attr_accessible :email, :nickname, :password, :password_confirmation

app/views/layouts/application.html.erb

   <%= render(:partial => "users/user_status") %>
 
+  <%= flash[:error] %>
+  <%= flash[:notice] %>
+
   <%= yield %>

app/views/users/new.html.erb

 <% form_for :user, :url => users_path do |f| -%>
 
+<p><%= label_tag 'nickname', t('actionview.label.common.nickname') %><br />
+<%= f.text_field 'nickname' %></p>
+
 <p><%= label_tag 'email', t('actionview.label.common.email') %><br/>

app/views/users/_user_status.html.erb

-    <%= link_to_current_user :content_method => :email %>
+    <%= link_to_current_user :content_method => :nickname %>

こんな感じ。

:nameを削除したら、

validation消さなきゃいけないよね?www
スッカリ忘れてたわwww
つうか、これ、nicknameで再利用する事にした。

 app/models/user.rb

-  validates_format_of       :name,     :with => Authentication.name_regex,  :message => :bad_name_message, :allow_nil => true
-  validates_length_of       :name,     :maximum => 100
+#  validates_format_of       :nickname,     :with => Authentication.name_regex,  :message => :bad_name_message, :allow_nil => true
+#  validates_length_of       :nickname,     :maximum => 100

-  attr_accessible :login, :email, :name, :password, :password_confirmation
+  attr_accessible :email, :nickname, :password, :password_confirmation
こんな感じで。

2008年12月5日金曜日

Usersモデルに名字やら名前やらを追加しようと思ったら、

あまりにも変更点が多いんで、面倒臭いから、全部書き直す事にしたwww

svnで、*数字*_remove_login_from_users.rbを消す。
$ svn delete db/migrate/*数字*_remove_login_from_users.rb
んで、db/migrate/*数字*_create_users.rbを編集。
こんな感じになりました。
class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table "users", :force => true do |t|
      t.column :nickname,                  :string, :limit => 100
      t.column :family_name,               :string, :limit => 100
      t.column :middle_name,               :string, :limit => 100, :default => '', :null => true
      t.column :given_name,                :string, :limit => 100
      t.column :email,                     :string, :limit => 100
      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, :limit => 40
      t.column :remember_token_expires_at, :datetime
      t.column :activation_code,           :string, :limit => 40
      t.column :activated_at,              :datetime
      t.column :state,                     :string, :null => :no, :default => 'passive'
      t.column :deleted_at,                :datetime
    end
    add_index :users, :email, :unique => true
    add_index :users, :nickname
  end

  def self.down
    drop_table "users"
  end
end
loginとnameを削除して、ニックネームと名字とミドルネームと名前を追加して、loginのインデックスはなかった事にして、emailとnicknameをインデックスするようにしました。

ホントは、migrateファイルを直接いじるのは、あまり好きじゃない。
やるべきじゃないとも思ってるんだけどwww

なんで、今後は、あまりしないようにしたいな、と思いますです。
ハイ。

2008年12月4日木曜日

restful_authenticationで、メールアドレスを使ってログインする。

つうか、ね?
今どき、ログインIDでのログインって、在り得なくない?
普通に、メールアドレスでログインだよね?
つうか、:loginって、いらなくね?

つう訳で、restful_authentication howto, step-by-step (part 2)を参考に、いじった。

で、もう、ソースを書き写すのが面倒臭くってwww
diffです。
app/models/user.rb

-  validates_presence_of     :login
-  validates_length_of       :login,    :within => 3..40
-  validates_uniqueness_of   :login
-  validates_format_of       :login,    :with => Authentication.login_regex, :message => :bad_login_message
+#  validates_presence_of     :login
+#  validates_length_of       :login,    :within => 3..40
+#  validates_uniqueness_of   :login
+#  validates_format_of       :login,    :with => Authentication.login_regex, :message => :bad_login_message

-    attr_accessible :login, :email, :name, :password, :password_confirmation
+    attr_accessible :email, :name, :password, :password_confirmation

-    u = find_in_state :first, :active, :conditions => {:login => login} # need to get the salt
+#    u = find_in_state :first, :active, :conditions => {:login => login} # need to get the salt
+    u = find_in_state :first, :active, :conditions => {:email => login} # need to get the salt

app/controllers/sessions_controller.rb

-    user = User.authenticate(params[:login], params[:password])
+    user = User.authenticate(params[:email], params[:password])

app/views/users/_user_bar.html.erb

-   <div id="user-bar-greeting">Logged in as <%= link_to_current_user :content_method => :login %></div>
+   <div id="user-bar-greeting">

+   </div>

app/views/users/new.html.erb

-<p><%= label_tag 'login', t('actionview.label.common.login') %><br/>
-<%= f.text_field :login %></p>

app/views/user_mailer/signup_notification.erb

-   Username: <%=h @user.login %>
+   Email: <%=h @user.email %>

 app/views/sessions/new.html.erb

-<p><%= label_tag 'login', t('actionview.label.common.login') %><br />
-<%= text_field_tag 'login', @login %></p>
+<p><%= label_tag 'email', t('actionview.label.common.email') %><br />
+<%= text_field_tag 'email', @login %></p>


こんな感じ?
じゃあ、usersモデルから、loginカラムを削っちゃおう。
$ script/generate migration RemoveLoginFromUsers login:string
マイグレーションついでに、DBをリセットしましょうか。
$ rake db:migrate:reset
こんな感じで。
で、新規登録し直して、script/serverのログから認証url拾ってきて、ログインして、おk?
おk。

諸々のウザさの軽減。

とりあえず、
  • ログイン状態が確認できないのが面倒臭い
  • public/index.htmlへ飛ばされるのがウザい

な感じなんで、
  • app/views/layouts/application.html.erbを作って書く
  • public/index.htmlを削除して、config/routes.rbを修正
する事にした。

でapp/views/layouts/application.html.erb。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
<head>
  <title>untitled</title>
</head>

<body>

  <%= render(:partial => "users/user_bar") %>

  <%= yield %>

</body>
</html>
な感じ。
headは、適当に。
users/user_barは、app/views/users/_user_bar.html.erbとして、ganerateされていたものを取り込んでるだけ。

_user_bar.html.erbも多言語化仕様かな、とも思ったんだけど、よくよく考えたら、クローズドなSNSなんだから、ログインしていない時は、全て、/loginに飛ばせばいいんだよね。
他のページが表示できているのなら、それは、ログインできているって事なんだからwww

んで、routes.rbの修正。
map.root :controller => 'sessions', :action => 'new'
を、追記しただけ。

簡単単純:-)

restful_authenticationで、メール認証。

これやらないと、ユーザ登録のテストとか、出来ないじゃんね?www

まず、/config/routes.rbに、以下を追記。
  map.activate '/activate/:activation_code', :controller => 'users', :action => 'activate', :activation_code => nil

続いて、config/initializers/mail.rbを作って、そこに以下を追記。
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    :address => 'your.smtp.domain',
    :port => 25,               # or 587 SMTP 設定に依存
    :domain => 'localdomain',  # 分かるなら FQDN を設定
    :authentication => :login, # SMTP 認証設定に依存
    :user_name => 'username',  # 認証がないなら削除
    :password => 'password'    # 認証がないなら削除
  }
いやいや、自分の設定を晒すほど、お間抜けじゃないっすよwww

で、とりあえず、テスト。


うはっ! 待てど暮せど、メール来ないやwwww
とりあえず、放っておいて、script/serverのログから、url拾って、認証してみる。

おk。
いやいや、おいおいwww

まあ、でも、メールの認証とか、後回しで良いしw
出来る事さえ解っていれば、良いのですよ。

そんな感じ。

restful_authenticationの日本語化。の続き。

で、config/locales/model_ja.ymlを見ていて、ふっ、と気が付いた。
loginとかemailとかnameとかなんて、モデルに限定されずに、使い回す訳じゃない?

ほら、DRYじゃない?
オイラって、DRYな訳じゃない?
むしろ、女の娘にDRYにあしらわれ続けてきた訳じゃない?www

じゃあ、DRYにしようよ、ってことを考えた。
でも、なんか、model_ja.ymlの中の、activerecord:attribute:hogehogeって、DBスキーマと結びついている筈だから、なあ...

でも、逆に考えれば、DBスキーマに結びついていないものは、共有できるよね。
で、こんな風に書き換えた。
ja:
  activerecord:
    models:
      user: ユーザ
      session: セッション
    attributes:
      user:
        login: ログイン
        name: 名前
        email: メールアドレス
        deleted_at: で削除された
        password: パスワード
        password_confirmation: 確認用パスワード
        crypted_password: 暗号化パスワード
        salt: 塩
        remember_token: 覚えているトークン
        remember_token_expires_at: トークンを忘れないで期限が切れる
        activation_code: 認証コード
        activated_at: でアクティブ
        state: 状態
      session:
        
  actionview:
    header:
      user:
        new: 新規ユーザー登録
      session:
        new: ログイン
    label:
      common:
        login: ログイン
        name: 名前
        email: メールアドレス
        password: パスワード
        password_confirmation: 確認用パスワード
      session:
        remember_me: ログイン状態を記憶する
    submit:
      common:
        submit: 送信
      user:
        signup: 登録
      session:
        log_in: ログイン

あんまりDRYな気がしないよね...www
まあ、でも、viewの中で使っているもの=hogehoge_tagメソッドとかに使いそうなものは、ja:action_view:サブクラスを作って、その中に突っ込んだよ。
viewで使うものは、activerecordとは絡めない方が、規約っぽいでしょ?

設定より規約っ!www

んで、viewも書き換えたよ。
<h1><%= t('actionview.header.user.new') %></h1>
<% @user.password = @user.password_confirmation = nil %>

<%= error_messages_for :user %>
<% form_for :user, :url => users_path do |f| -%>
<p><%= label_tag 'login', t('actionview.label.common.login') %><br/>
<%= f.text_field :login %></p>

<p><%= label_tag 'email', t('actionview.label.common.email') %><br/>
<%= f.text_field :email %></p>

<p><%= label_tag 'passoword', t('actionview.label.common.password') %><br/>
<%= f.password_field :password %></p>

<p><%= label_tag 'password_confirmation', t('actionview.label.common.password_confirmation') %><br/>
<%= f.password_field :password_confirmation %></p>

<p><%= submit_tag t('actionview.submit.user.signup') %></p>
<% end -%>

んで、app/views/sessions/new.html.erbも、書き換えた。
<h1><%= t('actionview.header.user.new') %></h1>
<% @user.password = @user.password_confirmation = nil %>

<%= error_messages_for :user %>
<% form_for :user, :url => users_path do |f| -%>
<p><%= label_tag 'login', t('actionview.label.common.login') %><br/>
<%= f.text_field :login %></p>

<p><%= label_tag 'email', t('actionview.label.common.email') %><br/>
<%= f.text_field :email %></p>

<p><%= label_tag 'passoword', t('actionview.label.common.password') %><br/>
<%= f.password_field :password %></p>

<p><%= label_tag 'password_confirmation', t('actionview.label.common.password_confirmation') %><br/>
<%= f.password_field :password_confirmation %></p>

<p><%= submit_tag t('actionview.submit.user.signup') %></p>
<% end -%>
んじゃあ、ちょっとこの辺でペンディング。
別の事を始める事にしよう。

restful_authenticationの日本語化。の続きをやろうとしていたら

面白い事に気が付いた。
ひょっとして、i18n_generatorって、DBのスキーマ構造見て、生成してね?

つうことは、アレ、だ。
DBのスキーマ変更した度に、生成だ。

イヤ、待て?
でも、script/generate i18n_generatorって、diffは見れても、マージは出来ないよね?

んんんん...
ま、いっかwwww

restful_authenticationの日本語化。

与太話書いてたら、長くなったんで、分けたwww

restful_authenticationをいれたんだから、まず、これをi18nで日本語化しましょうかね?
ああ、いきなり、
$ script/generate i18n ja
なんてやってるけど、そんなgenerator、rails 2.2.2には、入っていません。
んで、当然ながら、
$ script/plugin install git://github.com/amatsuda/i18n_generators.git
などとして、インストールする事に。
今回はplugin版をセレクト。
gem版もあるけどね。


で、N7 - sandbox | Ruby on Rails, iPhone開発 etc.は、凄く参考になったんだけど、ちょっと情報が古くなってたりなんかする。
i18nジェネレータは、今は、ja.ymlとmodel_ja.ymlの2つしか、生成しません。

あと、ここのやり方で、ちょっと腑に落ちないところがあったんで、オイラ的アレンジを。
続きのページ、「Rails 2.2の国際化(i18n)を試す(3) restful_authentication #2では、h1要素を、

ってしてるけど、こりゃあ、オイラ的には、

だね。
んで、model_ja.ymlは、
ja:
(省略)
  header:
    user: 
      new: 新規ユーザー登録

  lable:
    user:
      signup: 登録
ってな具合にする。
h1要素の「新規ユーザー登録 」は、labelじゃなくってheaderだからね:-)

あと、「エラーメッセージの日本語化」のところで、user.rbの:login、:name、:emailをrails標準のエラーメッセージを使うように変更しているけど、これは、なんかオイラ的には、嫌いなんで、
  validates_presence_of     :login
  validates_length_of       :login,    :within => 3..40
  validates_uniqueness_of   :login
  validates_format_of       :login,    :with => Authentication.login_regex, :message => :bad_login_message

  validates_format_of       :name,     :with => Authentication.name_regex,  :message => :bad_name_message, :allow_nil => true
  validates_length_of       :name,     :maximum => 100

 こんな調子に書き換えた。
んで、ja.ymlを、
  activerecord:
    errors:
(略)
      messages:
(略)

        bad_login_message: "は英数字と\".\"、\"-\"、\"_\"、\"@\"のみを使用して下さい。"
        bad_name_message: "には不可視キャラクタと\"\\\"、\">\"、\"<\"、\"/\"を使用しないで下さい。"
        bad_email_message: "を正確に入力して下さい。"
こんな調子に。

あと、app/views/users/new.html.erbの書き方が、非常にマズいwww
for属性をコロしちゃってますやんwww
なんで、こんなふうに書き換えた。
<h1><%= t('header.user.new') %></h1>
<% @user.password = @user.password_confirmation = nil %>

<%= error_messages_for :user %>
<% form_for :user, :url => users_path do |f| -%>
<p><%= label_tag 'login', t('activerecord.attributes.user.login') %><br/>
<%= f.text_field :login %></p>

<p><%= label_tag 'email', t('activerecord.attributes.user.email') %><br/>
<%= f.text_field :email %></p>

<p><%= label_tag 'passoword', t('activerecord.attributes.user.password') %><br/>
<%= f.password_field :password %></p>

<p><%= label_tag 'password_confirmation', t('activerecord.attributes.user.password_confirmation') %><br/>
<%= f.password_field :password_confirmation %></p>

<p><%= submit_tag 'Sign up' %></p>
<% end -%>
これで、http://localhost:3000/hogehoge/users/newを見て、何も記入せずにsubmitボタンを押してみれば、日本語化しているのが確認できるでしょう。

ステキ(ハート)

クリスマス・ソングな話。

いつの間にやら、クリスマス・ソングの季節になりましたが。
ナニゲ、クリスマス・ソングって、名曲ぞろいだったりなんかしますな。
にも関わらず、季節もんな訳で、今時分しか聞けないのが、悲しい性ですな。

月並みですが、「A Very Special Christmas」なんかは、名盤中の名盤で。
「Christmas (Baby Please Come Home) / U2」なんかは、そりゃあ、聞きまくりましたし、今も聞いてますよ。
このシリーズ、1枚買えば、2曲くらいは名曲があったりなんかしまして。
A Very Special Christmas 3」には、「Blue Christmas / Sheryl Crow」、「Christmas / Blues Traveler」なんかが、「A Very Special Christmas 5」には、「Merry Christmas Baby / Stevie Wonder/Wyclef Jean」、「Back Door Santa / B.B.King/John Popper」、「I Love You More / Stevie Wonder/Kimberly Brewer」なんかがよろしくって。
A Very Special Acoustic Christmas」には、「Only You Can Bring Me Cheer (Gentleman's Lady) - Alison Krauss」なんて素敵な曲がはいってますな。

特に最近のお気に入りは、「Christmas」と「I Love You More」と「Only You Can Bring Me Cheer (Gentleman's Lady)」で。
この3曲で、軽くドンブリ3杯はいけますよ、ハイ。

んー、プリーズ・カム・ホームな娘、現れませんかねぇー...

2008年12月3日水曜日

忘れる前に、書いておく。

restful_authenticaionの、今、現時点でのリポジトリでは、インストール/ジェネレートで、ほとんどの設定が自動的になされます。
あと、plugin名にハイフンが含まれている為、Name Errorがでるので、インストール後のディレクトリ名は、「restful-authentication」ではなく、「restful_authenticaion」にしなければなりませぬ。
あと、gitのリポジトリから取ってくる事になるかと。
あと、rubyist-aasmに対応させます。
$ cd ~/Rails/hogehoge
$ git clone git://github.com/technoweenie/restful-authentication.git vendor/plugins/restful_authentication
$ script/generate authenticated user sessions --aasm
そんで、app/controllers/application.rbに、以下を追記。
require 'aasm'
簡単やね:-)

で、何が消えたかって、

大したもんでもないんだけど、さ。
railsでプロジェクト作って、リポジトリに押し込んで、capistranoのセットアップして、i18nのセットアップして、restful_authenticationのセットアップして、なんていう、大した事ではないような事しか書いてないけど、さ。

イヤ、誰の為に書いているかって、オレの為に書いてるんだよ。
んな、毎日々々、同じような事を繰り返してやれるようなタチじゃないし、このプロジェクトをずっと続けて、でも、途中で新たにプロジェクトを作る事になった時に、その流れを覚えておけるほど、オレぁ頭良くねぇからよ。

その為に書いてるんだよ。

railsなんて、今日ググって出てきたものが、今日使える知識なのかどうかも怪しいくらいのスピードで進化してるから、さ。
せめて、時系列と体験を合わせて、自身の中に蓄えておきたいのよ。
解るかね?

restful_authenticationなんて、ホント、変わってるぜ?
また、一からやり直して書き直すなんて、まっぴらゴメンだよ、なあ?

なんで、この先は、既にrestful_authenticationがインストールされていて、i18nの基本設定が終わった状態から始まります。

です。

イヤ、もうホントに呆れ返ったよ=>Hatena::Diary

そう、前にもあったんだ、おんなじ事。
そりゃあ、ね?
いってしまえば、オイラのウッカリミスですわ。突き詰めてしまえば。

でも、ね?
そんなウッカリが起きるようなシステム組むバカって、どうよ?

世の中には、そんなにいないのか?
Hatena::Diary使っていて、同日記事の更新で、想定外の記事を削除してしまったヤツは?

「年金貰えなくなるような行政に掛け金収め続けていたのは、国民の個人的責任」くらいの自己責任か?

そんなことでいいのか?

怒れ! はてなユーザよ!!
その怒りを、是非とも元・厚生省の事務次官にだうわっあqwせdrftgyふじこlp