ユーザーが投稿を追加し、それらすべてを 1 つの集約されたストリームで表示できるシンプルなサイトを開発しようとしています。
問題は、「メッセージ」投稿と「リンク」投稿の 2 つの「タイプ」の投稿があることです。
すべての投稿にはメッセージが必要であり、投稿にはリンクを含めることができます。
投稿にリンクが含まれている場合は一意である必要があるため、(あなたまたは他のユーザーによって) 既に送信されたリンク付きの投稿を追加することはできません。
したがって、ユーザーが提供されたリンク URL を使用して投稿を追加する場合、次のようなリンクの検証が必要です。
- これはリンクですか?
- このリンクは新しいものですか (まだデータベースにありません)?
- これは有効なリンクですか (ドメインが存在し、サーバーの応答が適切であるように (400,301,...)
今、私は次のようなすべての投稿 (リンクありとなし) に対して 1 つのモデルで立ち往生しています。
#
# Table name: posts
#
# id :integer(4) not null, primary key
# message :string(255) default(""), not null
# link :string(2000)
# src_site_id :integer(4)
# link_type :integer(4) default(0)
# explicit :boolean(1) default(FALSE)
# view_times :integer(4)
# hidden_times :integer(4)
# tasted_times :integer(4)
# uid :integer(4)
# created_at :datetime
# updated_at :datetime
#
class Post < ActiveRecord::Base
default_scope :order => 'created_at desc'
attr_accessible :link, :message, :explicit
validates :message, :presence => true,
:length => { :maximum => 255 }
end
私が見ている問題は、NULLになる可能性があるため、モデルの検証をリンクに適用できないことです(一意性または形式をチェックできません)。したがって、posts_controllerのすべての検証を次のように適用します。
class PostsController < ApplicationController
def create
@post = Post.new(params[:post])
if @post.link.empty?
@post.link = nil
@post.save
else
if looks_like_link(@post.link)
if is_new_link(@post.link)
if is_valid_link (@post.link)
@post.save
else # url is not available
flash['error'] = 'link is not available'
end
else # link is already in db
flash['error'] = 'link is already added'
end
else
flash['error'] = 'doesnt look like a link'
end
end
redirect_to(root_path)
end
private
def looks_like_link(link)
link.match(/^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix)? true : false
end
def is_new_link(link)
Post.find_by_link(link) ? false : true
end
def is_valid_link(link)
require "net/http"
url = URI.parse(link)
req = Net::HTTP.new(url.host, url.port)
res = req.request_head(url.path)
flash[:error] = 'res code is ' + res.code
return res.code == '200' || res.code == '301' ? true : false
end
end
これを正しい方法にする方法は?これに STI を使用するという提案がありましたが、それを正しい方法で行う方法と検証を適用する方法がよくわかりません。STI と検証の使用に関する適切なリソースを知っている場合は、リンクを教えてください。