harukazepc’s blog

インターネッツとAndroidなどが大好きです。あとは日々のことなど。

偽diggを作るbyRails(その1)

では、ざっくり大枠を作る工程を、作った後の後追いで記述。


1. データベース
phpmyadmin経由でざっくりやったので、エクスポート機能の結果を転載。
sitesテーブルは、サイトの登録データ。URL、投票総数、コメント、登録ユーザの情報など。
countsテーブルは、集計・2重登録チェック用。現在はREMOTE_ADDRによる二重投稿制限のみに利用。のちのち集計データとして使いたい。

CREATE DATABASE `digg`;

CREATE TABLE `sites` (
  `id` int(11) NOT NULL auto_increment,
  `url` varchar(255) NOT NULL default '',
  `count` int(255) NOT NULL default '0',
  `comment` varchar(255) NOT NULL default '',
  `userid` int(11) NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `url` (`url`),
  KEY `userid` (`userid`)
) TYPE=InnoDB;

CREATE TABLE `counts` (
  `siteid` int(255) NOT NULL default '0',
  `remote_addr` varchar(15) default NULL,
  `date` datetime NOT NULL default '0000-00-00 00:00:00',
  KEY `siteid` (`siteid`,`remote_addr`)
) TYPE=InnoDB;

2. config/database.yml
利用するDBにあわせて設定。ばっさり省略。

3. モデル生成
作ったテーブルのORマッパー用モデルを作成。(言ってることがおぼつかないな。。。)

generate model site
generate model count

4. コントローラ生成
なぜかrecommendというコントローラ名にしてしまったようです、、、。

generate controller recommend

5. scaffoldでビューを。
生成したモデル・コントローラに合わせてviewやらなんやらを生成。scaffold。モデル名とコントローラ名を指定する。

generate scaffold site recommend

実際に直接ユーザがいじる(=recommendで操作する)のはsiteなので、モデルにsiteを指定。

6. サーバ起動、確認
この時点で確認。これでsiteテーブルオンリーなphpmyadmin的なもの完成。

ruby script/server


ここからが本番ですね!


7. 「Digg it!」ボタン的なaction追加

リンクを押すとカウント追加、という機能(action名:countup)を追加する。
ちょろちょろ修正追加。
REMOTE_ADDRによる、重複ボタン落下規制。

recommend_controller.rb ↓

...
  def countup
    id = params[:id]
    ra = @request.env['REMOTE_ADDR']
    if Count.find(:first, :conditions => ["siteid = ? and remote_addr = ?",id,ra])
      flash[:notice] = 'You have already digged it!'
    else
      count = Count.new
      count.siteid = id
      count.remote_addr = ra
      t = Time.now
      t.strftime("%Y-%m-%d")
      count.date = t.to_s
      count.save
      site = Site.find(id)
      site.count += 1
      site.save
    end
    # リスト表示
    redirect_to :action => 'list'
  end
...

list.rhtml ↓

...
  <% end %>
    <td><%= link_to 'Digg it!!', :action => 'countup', :id => site %></td>
    <td><%= link_to 'Show', :action => 'show', :id => site %></td>
...

この時点で、サイト登録・投票アプリ完成。


ユーザ認証を入れましょうか

8. Engine, Login_Engin Pluginの設定

radrailsでのplugin追加・設定。
右下ウィンドウのRails Pluginsから、EngineとLogin_Engineを追加


rakeの設定。
id:Kantaさんによるご紹介の通りに。多謝。


その後、右下ウィンドウのRake Tasksから、
engine_migrate ENGINE=login Go.
既存テーブルのレコードへ若干ゴミが。ううむ。手動削除。


あとは各種ファイル修正。
こちらはpylori*style wikiさんより。多謝。

environment.rb

module LoginEngine
  config :salt, "xxxx"
  config :email_from, "xxxx@xxx.xx.xx"
  config :admin_email, "xxxx@xxx.xx.xx"
  config :app_name, "fake Digg"
end

Engines.start :login

application.rb

require 'login_engine'

class ApplicationController < ActionController::Base
  include LoginEngine
  helper :user
  model :user
  
  before_filter :login_required, :except => [:list, :countup]
end

actionのうち、listとcountupのみ、無認証での実行許可。

application_helper.rb

module ApplicationHelper
  include LoginEngine
end

development.rb

ActionMailer::Base.server_settings = {
  :address => "smtp.xxxxx.xx.xx",
  :domain => "xxxxxx.xx.xx",
  :port => 25
}

ここまでで、
・listとcountup以外のactionでは認証が必須
・認証をクリアーしていない場合、ログイン画面
・登録時に確認メールが飛び、メールのURLクリックで本登録
まで実装。すげーなplugin。

9. 「登録済みサイトを編集できるのはその登録者だけ」の実装

実際に、認証情報を利用する。

recommend.rb

...
  def update
    @site = Site.find(params[:id])
    # 自分のものだけ直す
    if session[:user] == nil || @site.userid != session[:user].id
      flash[:notice] = 'You can\'t edit it.'
      redirect_to :action => 'list'
    elsif
      @site.update_attributes(params[:site])
      flash[:notice] = 'Site was successfully updated.'
      redirect_to :action => 'show', :id => @site
    else
      render :action => 'edit'
    end
  end
...

_form.rhtml

...
<%= text_field 'site', 'comment'  %></p>

<p><label for="site_userid">Userid</label><br />
<input type="hidden" name="site[userid]" value="<%= session[:user].id %>">
</p>
<!--[eoform:site]-->
...

hiddenのら辺、もっと書きようがあるはずですね。

で、登録者しか登録できなくなりました。めでたしめでたし。

その2に続く!?

© harukazepc️