2011-08-23 45 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