在Rails中保存数据库中的外部推文

时间:2014-02-14 23:27:39

标签: ruby-on-rails twitter rails-activerecord

我是rails developpement和MVC架构的新手。我有一个小应用程序,我可以在Dailymotion或Youtube中添加视频的URL,并使用Ruby on Rails中的twitter gem获取与该URL相关的推文。

现在我可以像这样存储推文:(这是视频控制器)

 def show
  @video = Video.find(params[:id])

  # Creating a URL variable 
  url = @video.url

  # Search tweets for the given video/url
  @search = get_client.search("#{@video.url} -rt")

  # Save tweets in database
  @search.collect do |t|
    tweet = Tweet.create do |u|
    u.from_user =  t.user.screen_name.to_s
    u.from_user_id_str = t.id.to_s
    u.profile_image_url = t.user.profile_image_url.to_s
    u.text = t.text.to_s
    u.twitter_created_at = t.created_at.to_s
  end
end

我不确定这是否是正确的方法(在控制器中执行此操作?),我现在要做的是指定刚刚存储的那些推文属于当前视频。此外,我希望进行某种验证,使控制器在执行此操作之前查看数据库,以便仅保存新推文。有人可以帮我吗?

我的模特:

class Video < ActiveRecord::Base
   attr_accessible :url
   has_many :tweets
end

class Tweet < ActiveRecord::Base
belongs_to :video
end

我的routes.rb

 resources :videos do
  resources :tweets
end

1 个答案:

答案 0 :(得分:1)

这是“胖控制器”的一个例子,它是任何MVC架构中的反模式(here's a good read on the topic)。

您是否考虑过引入一些新对象来封装此行为?例如,我可能会这样做:

# app/models/twitter_search.rb
class TwitterSearch
  def initialize(url)
    @url = url
  end

  def results
    get_client.search("#{@url} -rt")
  end
end

# app/models/twitter_persistence.rb
class TwitterPersistence
  def self.persist(results)
    results.map do |result|
      self.new(result).persist
    end
  end

  def initialize(result)
    @result = result
  end

  def persist
    Tweet.find_or_create_by(remote_id: id) do |tweet|
      tweet.from_user =  screen_name
      tweet.from_user_id_str = from_user_id
      tweet.profile_image_url = profile_image_url
      tweet.text = text
      tweet.twitter_created_at = created_at
    end
  end

  private

  attr_reader :result

  delegate :screen_name, :profile_image_url, to: :user
  delegate :id, :user, :from_user_id, :text, :created_at, to: :result
end

请注意使用find_or_create_by ... Twitter结果应该有一个唯一的标识符,您可以使用它来保证不创建重复项。这意味着您在推文表上需要remote_id或其他内容,当然我只是猜测您正在使用的服务将返回的属性名称(id)。

然后,在你的控制器中:

# app/controllers/videos_controller.rb
class VideosController < ApplicationController
  def show
    @tweets = TwitterPersistence.persist(search.results)
  end

  private

  def search
    @search ||= TwitterSearch.new(video.url)
  end

  def video
    @video ||= Video.find(params[:id])
  end
end

另请注意,我已删除对to_s的调用... ActiveRecord应在将属性保存到数据库之前自动将属性转换为正确的类型。

希望这有帮助!