Модель сообщений и архитектура контроллера - PullRequest
0 голосов
/ 23 августа 2011

Я пытаюсь разработать простой сайт, который позволяет пользователям добавлять сообщения и просматривать их все в одном объединенном потоке.

Проблема в том, что у меня есть сообщения 2 "типов", сообщение "сообщение" исообщение "link".

Все сообщения должны иметь сообщение, а сообщение может содержать ссылку.

Если сообщение имеет ссылку, оно должно быть уникальным, поэтому вы не можете добавить сообщение со ссылкой, которая уже была отправлена ​​(вами или другим пользователем).

Таким образом, в случае, если пользователь добавляетПубликация с предоставленной ссылкой URL Мне нужны проверки для ссылки, например:

  • это ссылка?
  • эта ссылка новая (еще не в БД)?
  • естьэто действительная ссылка (например, домен существует, и ответ сервера адекватен (400,301, ...)

Теперь я застрял только с одной моделью для всех сообщений (со ссылками и без них)это выглядит так:

#
# 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 для этого, но я действительно не знаю, как сделать это правильно и как применить валидацию.Если вы знаете хороший ресурс об использовании ИППП и проверок pаренды дай ссылку.

1 Ответ

0 голосов
/ 23 августа 2011

В рельсах, когда вы обнаруживаете, что делаете что-то необычное, это, вероятно, неправильно.Или, если не ошибаюсь, это, вероятно, будет означать большую работу, пытаясь достичь того, чего вы хотите достичь.Проверка обычно выполняется на модели, и в контроллере никогда не должно быть кода, который не связан с простой маршрутизацией.Таким образом, правильный способ решения этой проблемы - поместить код проверки в модель.В рельсах 3 у меня был бы такой валидатор - я не включил детали вашего кода контроллера, но, надеюсь, вы поняли ...позвоните валидатору:

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

Что касается использования валидации в STI - взгляните на этот пост

...