2011-08-23 43 views
0

我想開發一個簡單的網站,讓用戶添加帖子並在一個聚合流中查看它們。發佈模型和控制器體系結構

問題是我有2個「類型」,「消息」帖子和「鏈接」帖子的帖子。

所有帖子都必須有留言,帖子可以有鏈接。

如果帖子有一個鏈接,它必須是唯一的,所以你不能添加一個鏈接已經提交(由你或一些其他用戶)的帖子。

所以,在情況下,如果用戶增加所提供的鏈接網址,我需要驗證像鏈接早報:

  • 這是一個鏈接?
  • 這是新的鏈接(尚未在db中)?
  • 這是一個有效的鏈接(如域存在,並且服務器響應是適當的(400301,...)

現在我堅持只是一個模型,所有的職位(有聯繫,並沒有他們),看起來像這樣:

# 
# 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 

的問題,因爲我看到的是,我不能適用模型驗證鏈接(廣東話檢查獨特或格式),因爲它可以爲空,所以我申請的所有驗證在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和驗證的好資源,請給我一個鏈接。

回答

0

在rails中,每當你發現自己在做某些不常見的事情時,可能是錯誤的。或者,如果沒有錯,這可能意味着很多努力實現你想要達到的目標。驗證通常在模型上完成,並且控制器中永遠不應該有與簡單路由無關的代碼。所以解決這個問題的正確方法是將驗證代碼放入模型中。在軌道3,我想有一個驗證器是這樣的 - 我不能把已經在你的控制器代碼的細節,但希望你的想法...

class LinkValidator < ActiveModel::EachValidator 
    def validate_each(record, attribute, value) 
    if record.empty? 
return true 
    else 
     Post.find_by_link(record) ? false : true 
    end 
    end 
end 

然後在調用Post模型驗證:

validates :link, :link=>true, :allow_nil => true 

至於在STI使用驗證 - 看看this post