FC2ブログ

2019.09 «  - - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 - - » 2019.11
TOP > CATEGORY > 掲示板アプリ

BACK | TOP | NEXT

掲示板を作ってみる・その7【スレッド用コントローラを編集】 

2008年08月07日 ()

掲示板を作ってみる・その1【何を作るの?】
掲示板を作ってみる・その2【モデルを作る パート1】
掲示板を作ってみる・その3【モデルを作る パート2】
掲示板を作ってみる・その4【ルーティングを考える】
掲示板を作ってみる・その5【コントローラを生成】
掲示板を作ってみる・その6【ヘルパを作る】
掲示板を作ってみる・その7【スレッド用コントローラを編集】
掲示板を作ってみる・その8【レス用コントローラを編集】
掲示板を作ってみる・その9【レイアウトファイルとスタイルシートファイルを作成】
掲示板を作ってみる・その10【スレッド用のビューファイルを作成】
掲示板を作ってみる・その11【レス用のビューファイルを作成】
掲示板を作ってみる・その12【ruby-gettext で日本語化】




スレッド用コントローラを編集しましょう。いきなりソースコード。

app/controllers/topic_controller.rb

class TopicController < ApplicationController
  before_filter :set_default_html_title

  def list
    @topics = Topic.age_date_desc
  end

  def create
    @topic = Topic.new(params[:topic])
    @post = Post.new(params[:post])
    Topic.transaction do
      @topic.age_time = Time.now
      @topic.save!

      @post.topic_id = @topic.id
      @post.res_no = 1 #1レス目
      @post.ip_address = request.remote_ip
      @post.save!
    end
    flash[:msg] = '新しいスレが立ちました'
    @topics = Topic.age_date_desc
    render :action => 'list'
  rescue
    @topics = Topic.age_date_desc
    @html_title = 'ERROR'
    render :action => 'list'
  end

private
  def set_default_html_title
    @html_title = 'スレ一覧と作成とヒロシとキーボー'
  end
end



・list メソッド
スレッド一覧な訳ですね。アゲ日時が新しい順から表示してみます。model ファイルで定義した named_scope がここで活きてくる訳です。

・create メソッド
スレッドを立ち上げがら、実は1レス目を書き込むことになりますので、Topic(スレッド) も Post(レス) も新規作成するようになります。
無事スレが立ち上がったら list のビューファイルを表示します。
もしエラーだったら rescue されて、list のビューファイルを表示します。

・set_default_html_title メソッド
@html_title には、<html><head><title>ここに入れるタイトル</title></head> を定義します。詳しくは後で作成する layout ファイルを見てください。
で、before_filter に、:set_default_html_title が指定されているので、この controller の list メソッドや create メソッドを呼ぶ前に、必ず set_default_html_title メソッドが呼ばれます。

説明粗くてスマソ。

おしまい。次回へ続く


【広告】

[2008.08.07(Thu) 11:23] 掲示板アプリTrackback(0) | Comments(0) 見る▼
↑TOPへ

掲示板を作ってみる・その6【ヘルパを作る】 

2008年08月06日 ()

掲示板を作ってみる・その1【何を作るの?】
掲示板を作ってみる・その2【モデルを作る パート1】
掲示板を作ってみる・その3【モデルを作る パート2】
掲示板を作ってみる・その4【ルーティングを考える】
掲示板を作ってみる・その5【コントローラを生成】
掲示板を作ってみる・その6【ヘルパを作る】
掲示板を作ってみる・その7【スレッド用コントローラを編集】
掲示板を作ってみる・その8【レス用コントローラを編集】
掲示板を作ってみる・その9【レイアウトファイルとスタイルシートファイルを作成】
掲示板を作ってみる・その10【スレッド用のビューファイルを作成】
掲示板を作ってみる・その11【レス用のビューファイルを作成】
掲示板を作ってみる・その12【ruby-gettext で日本語化】




controller を生成したので、その中身を定義したいところですが、helper を先に定義してしまいましょう。

controller や view などで使いたいが、controller ファイルや view ファイルの中では定義したくないメソッドを定義しておく、それが helper だったりしますが、さて、helper を定義します。

app/helpers/topic_helper.rb は編集なし。

app/helpers/post_helper.rb

module PostHelper
  def date_format(date)
    wdays = ['日', '月', '火', '水', '木', '金', '土']
    date.strftime('%Y/%m/%d(') + wdays[date.wday] + date.strftime(') %H:%M:%S')
  end

  def generate_id(ip_address, created_at)
    return '???' if ip_address.blank?

    id_chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/'
    today = created_at.strftime("%Y%m%d").to_i
    ip_address_sections = ip_address.split('.')
    for i in (0..3)
      ip_address_sections[i] = ip_address_sections[i].to_i + 1
    end

    res_id = []
    res_id[0] = id_chars[today % ip_address_sections[0] % id_chars.size, 1]
    res_id[1] = id_chars[today % ip_address_sections[1] % id_chars.size, 1]
    res_id[2] = id_chars[today % ip_address_sections[2] % id_chars.size, 1]
    res_id[3] = id_chars[today % ip_address_sections[3] % id_chars.size, 1]
    res_id[4] = id_chars[today % (ip_address_sections[0] + ip_address_sections[0]) % id_chars.size, 1]
    res_id[5] = id_chars[today % (ip_address_sections[1] + ip_address_sections[0]) % id_chars.size, 1]
    res_id[6] = id_chars[today % (ip_address_sections[2] + ip_address_sections[0]) % id_chars.size, 1]
    res_id[7] = id_chars[today % (ip_address_sections[3] + ip_address_sections[0]) % id_chars.size, 1]
    res_id[8] = id_chars[today % (ip_address_sections[1] + ip_address_sections[1]) % id_chars.size, 1]

    res_id.to_s
  end

  def add_link_to_content(content, topic_id)
    content = h(content)
    content = content.gsub(/\r\n/, "<br>")
    content = content.gsub(/\n/, "<br>")
    content = content.gsub(/\r/, "<br>")
    content = content.gsub(/&gt;&gt;([1-9][0-9]?[0-9]?)/, "<a href=\"/post/list/#{topic_id}/\\1\">&gt;&gt;\\1</a>")
    content
  end

  class PostRange
    def initialize(post_range=nil)
      @first = 1
      @last = 1
      parse_range(post_range)
    end

    def first
      @first
    end

    def last
      @last
    end

    def include_first?
      @include_first
    end

    def from_last?
      @from_last
    end

    private
    def parse_range(post_range)
      if /^(\d+)?-(\d+)?$/ =~ post_range
        @first = $1
        @last = $2
        @include_first = true
        @from_last = false
      elsif /^(\d+)n-(\d+)?$/ =~ post_range
        @first = $1
        @last = $2
        @include_first = false
        @from_last = false
      elsif /^(\d+)$/ =~ post_range
        @first = $1
        @last = $1
        @include_first = false
        @from_last = false
      elsif /^l(\d+)$/ =~ post_range
        @first = 1
        @last = $1
        @include_first = false
        @from_last = true
      else
        @first = nil
        @last = nil
        @include_first = true
        @from_last = false
      end
    end
  end
end




がっつり来ちゃいましたね。

date_format では、date 型のオブジェクトを受け取って某巨大掲示板っぽいで表示されている形式の日付に変換します。

generate_id では、IP アドレスとレス書き込み日を元に、某巨大掲示板っぽい書き込み ID を生成しています。ここはいろいろ変えて遊んでみてね。

add_link_to_content では、書き込みの中にある >>233 みたいな文字にリンクを付け加えたりします。

PostRange クラスは、レスの範囲を URL に指定したときに、実際何番から何番までのレスを表示するか(first, last)、1番のレスを表示するか(include_first?)、レス番号の大きい方から特定の数だけ表示するのかどうか(from_last?)、を解析します。
某巨大掲示板でいろいろ試してみたのですが、このルールは奥が深くて参りました。


おしまい。次回へ続く


【広告】

[2008.08.06(Wed) 11:23] 掲示板アプリTrackback(0) | Comments(0) 見る▼
↑TOPへ

掲示板を作ってみる・その5【コントローラを生成】 

2008年08月05日 ()

掲示板を作ってみる・その1【何を作るの?】
掲示板を作ってみる・その2【モデルを作る パート1】
掲示板を作ってみる・その3【モデルを作る パート2】
掲示板を作ってみる・その4【ルーティングを考える】
掲示板を作ってみる・その5【コントローラを生成】
掲示板を作ってみる・その6【ヘルパを作る】
掲示板を作ってみる・その7【スレッド用コントローラを編集】
掲示板を作ってみる・その8【レス用コントローラを編集】
掲示板を作ってみる・その9【レイアウトファイルとスタイルシートファイルを作成】
掲示板を作ってみる・その10【スレッド用のビューファイルを作成】
掲示板を作ってみる・その11【レス用のビューファイルを作成】
掲示板を作ってみる・その12【ruby-gettext で日本語化】




いよいよ司令塔の controller を生成します。スレッド用(Topic)とレス用(Post)のコントローラを生成しようと思います。

# script/generate controller Topic
# script/generate controller Post



それだけ。


おしまい。次回へ続く


【広告】

[2008.08.05(Tue) 11:22] 掲示板アプリTrackback(0) | Comments(0) 見る▼
↑TOPへ

掲示板を作ってみる・その4【ルーティングを考える】 

2008年08月04日 ()

掲示板を作ってみる・その1【何を作るの?】
掲示板を作ってみる・その2【モデルを作る パート1】
掲示板を作ってみる・その3【モデルを作る パート2】
掲示板を作ってみる・その4【ルーティングを考える】
掲示板を作ってみる・その5【コントローラを生成】
掲示板を作ってみる・その6【ヘルパを作る】
掲示板を作ってみる・その7【スレッド用コントローラを編集】
掲示板を作ってみる・その8【レス用コントローラを編集】
掲示板を作ってみる・その9【レイアウトファイルとスタイルシートファイルを作成】
掲示板を作ってみる・その10【スレッド用のビューファイルを作成】
掲示板を作ってみる・その11【レス用のビューファイルを作成】
掲示板を作ってみる・その12【ruby-gettext で日本語化】




今回、コントローラは、スレッド用(Topic)とレス用(Post)を用意したいと思います。

スレッド用のコントローラは、action とスレッド番号さえ URL に乗せれば、なんとかスレ一覧表示とスレ立てができそうです。

一方、レス用のコントローラは、action とスレッド番号とレス番号を URL に乗せれば、レス一覧表示とレス書き込みができそうです。

と言うわけで、config/routes.rb の最後の行の方を↓こう書き換えました。

config/routes.rb




  map.root :controller => "topic", :action => "list"

  map.connect 'post/:action/:topic_id/:range', :controller => 'post'
  map.connect 'post/:action/:topic_id', :controller => 'post'

  map.connect ':controller/:action/:id'
#  map.connect ':controller/:action/:id.:format'
end



最初の行の設定で、http://example.com/ とスラッシュで終わってきたら、「topic」コントローラの「list」メソッドを通過させます。
この設定を有効にさせるのに public/index.html ファイルを削除しましょう。

次の行は、http://example.com/post/list/100002201/1-100 みたいなケースをハンドリングしております。うん、某巨大掲示板っぽい。

一番最後の行は、今回は xml とか atom とか別に使わないのでコメントアウトしてしまいました。

という訳ですが、今回も説明省きすぎ?疑問質問はコメント欄へどうぞ。

おしまい。次回へ続く


【広告】

[2008.08.04(Mon) 11:21] 掲示板アプリTrackback(0) | Comments(0) 見る▼
↑TOPへ

掲示板を作ってみる・その3【モデルを作る パート2】 

2008年08月03日 ()

掲示板を作ってみる・その1【何を作るの?】
掲示板を作ってみる・その2【モデルを作る パート1】
掲示板を作ってみる・その3【モデルを作る パート2】
掲示板を作ってみる・その4【ルーティングを考える】
掲示板を作ってみる・その5【コントローラを生成】
掲示板を作ってみる・その6【ヘルパを作る】
掲示板を作ってみる・その7【スレッド用コントローラを編集】
掲示板を作ってみる・その8【レス用コントローラを編集】
掲示板を作ってみる・その9【レイアウトファイルとスタイルシートファイルを作成】
掲示板を作ってみる・その10【スレッド用のビューファイルを作成】
掲示板を作ってみる・その11【レス用のビューファイルを作成】
掲示板を作ってみる・その12【ruby-gettext で日本語化】




今度は、モデルの定義ファイルをいじって、バリデーションやらいろんなものを加えていきましょう。

モデルの定義ファイルは、最初は空だったりします。

app/models/topic.rb

class Topic < ActiveRecord::Base
end



app/models/post.rb

class Post < ActiveRecord::Base
end



そこにいろいろ書き加えて10分オーブンで焼いた形が次のようになります。


app/models/topic.rb

class Topic < ActiveRecord::Base
  has_many :posts

  validates_presence_of :title, :message => 'スレタイが存在しません'
  validates_uniqueness_of :title, :message => '同じスレタイが存在します'

  named_scope :age_date_desc, :order => 'age_time desc'

  def before_validation
    self.title.gsub!(/^ +/, ' ') #全角スペースを置換
    self.title.gsub!(/ +$/, ' ') #全角スペースを置換
    self.title.strip!
  end
end


has_many では、スレッドにぶらさがっているレスがたくさんあって、スレッドオブジェクトからぶら下がっているレスを参照できるようにします。
validates_ というのは、指定したカラムのエラーチェックに使います。
named_scope は、アゲ日時が新しい順番にスレッドを並び替える時に使います。
before_validation では、スレタイのエラーチェックをする前に、入力されたスレタイの全角スペースを半角スペースに変えて、さらにスレタイの前後の半角スペースを取り除いています。

app/models/post.rb

class Post < ActiveRecord::Base
  attr_reader :topic_id

  belongs_to :topic
  validates_presence_of :content, :message => '本文がありません'
  validates_length_of :name, :maximum => 30, :message => '名前が長すぎます'
  validates_length_of :email, :maximum => 100, :message => 'メールアドレスが長すぎます'
  validates_length_of :content, :maximum => 50000, :message => '本文が長すぎます'

  named_scope :my_topic, lambda{|arg| {:conditions => {:topic_id => arg}}}

  def before_validation
    self.name.gsub!(/^ +/, ' ') #全角スペースを置換
    self.name.gsub!(/ +$/, ' ') #全角スペースを置換
    self.name.strip!
    self.name = '名無しの権兵衛さん' if self.name.blank?
  end
end


attr_reader では、レスオブジェクト.topic_id という感じでスレッド番号を参照できるようにします。普通はこんな宣言しなくても自分のモデルの値を参照できるのだけど。topic_id が references 属性だから特別にこういう宣言をしなければならないのかな?(不明)
belongs_to では、レスはスレッドにぶらさがっていて、レスオブジェクトから自分が属しているスレッドを参照できるようにします。
validates_ というのは、指定したカラムのエラーチェックに使います。
named_scope は、指定したスレッド番号だけのレスを取得したい時に使います。
before_validation では、レスの名前のエラーチェックをする前に、入力された名前の全角スペースを半角スペースに変えて、さらに名前の前後の半角スペースを取り除いています。さらにさらに名前が空な場合は強制的に「名無しの権兵衛さん」を名前に設定します。

ちょっと解説ががさつかなぁ?分からないことがあったらコメントにでも書いてもらえると答えられると思います。

おしまい。次回へ続く


【広告】

[2008.08.03(Sun) 11:21] 掲示板アプリTrackback(0) | Comments(2) 見る▼
↑TOPへ


COMMENT

教えてください by -
before_validationというメソッドはどこで呼ばれるのでしょうか。
この名前にしておけば評価前に勝手にどこかで呼んでくれるのでしょうか?
そうだとしたら、呼ばれるのはこのモデルの中で一回だけですか?

validation の前です by 自分
before_validation というメソッドは勝手に呼ばれるのですよねー。このメソッド名はあらかじめ予約されているようなものですね。
before_validation がいつ呼ばれるかというと validation の前に呼ばれます。
じゃあ validation っていつ起きるの?ってことですが、モデルオブジェクトを使って、save しようとしている行を実行する直前、という感じです。

my_topic = Topic.find(1)
my_topic.title = 'タイトル書き換えてみた'
my_topic.save # 実際 Topic を更新する直前に before_validation を呼ぶ

です。

↑のように my_topic.title の値を元々入っていた値から変更して my_topic.save をするたびに、before_validation が呼ばれることになります。

こういう、save しようとするとその前か後で勝手に呼ばれるメソッドって結構あって、callback コールバックなどと呼ばれています。

さらに、destroy しようとすると、その前か後で勝手に呼ばれるコールバックメソッドもあります。

なかなか一口では説明できないので、新たに記事を書いてみました。(http://rubist.blog77.fc2.com/blog-entry-160.html)こっちも是非のぞいていってください。

コメントを閉じる▲
BACK | TOP | NEXT