我是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
答案 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应在将属性保存到数据库之前自动将属性转换为正确的类型。
希望这有帮助!