开发者

Posts Model & Controller Architecture

开发者 https://www.devze.com 2023-03-30 15:03 出处:网络
I am trying to develop a simple site that lets users add posts and view them all in one aggregated stream.

I am trying to develop a simple site that lets users add posts and view them all in one aggregated stream.

The problem is that I have posts of 2 "types", the "message" post and the "link" post.

All post must have a message and post can have a link.

If post has a link it must be unique so you cant add a post with link that already was submitted (by you or some other user).

So, in case if user adds the Post with provided link URL I need validations for link like:

  • is this a link?
  • is this link new (not already in db)?
  • is this a valid link (like the domain exists and the server response is adequate (400,301,...)

Now I am stuck with just one model for开发者_如何转开发 all the posts (with links and without them) that looks like this:

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

The problem as I see it is that I cant apply model validation to link (cant check uniqueness or format) because it can be NULL, so I apply all the validations in posts_controller like this:

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

How to make this the right way? I got a suggestion to use STI for this, but I don't really know how to do it the right way and how to apply validation. If you know of good resource about using STI and validations please give me a link.


In rails, whenever you find yourself doing something that is unusual, it is probably wrong. Or if not wrong, it will probably mean a lot of work trying to achieve what you want to achieve. Validation is usually done on the model, and there should never be code in the controller that is not to do with simple routing. So the right way to address this is to put the validation code in the model. In rails 3, I would have a validator something like this - I've not put in the detail of your controller code, but hopefully you get the idea ...

 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

Then in the Post model you call the validator:

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

As to using validation in STI - take a look at this post

0

精彩评论

暂无评论...
验证码 换一张
取 消