我尝试创建一个用户可以提交网址链接,标题和说明的应用,然后创建一个包含标题,说明和图片的帖子。我希望能够直接从用户提交的URL路径中抓取最佳或主要图像,并使用MetaInspector在显示页面上显示它。 (我没有使用Nokogiri或Mechanize的原因是因为我并没有完全理解这一点,并且MetaInspector似乎不那么令人生畏)
问题是我对rails非常陌生,而且我很难完成大多数教程。
是否有人能够一步一步向我解释如何做到这一点或向我展示一个非常详细且非常友好的来源?
我有一个包含该链接的Post
模型,还应该将抓取的图片保存为Paperclip
附件:
class Post < ActiveRecord::Base
belongs_to :user
has_attached_file :image
end
# == Schema Information
#
# Table name: posts
#
# id :integer not null, primary key
# title :string
# link :string
# description :text
# created_at :datetime
# updated_at :datetime
# user_id :integer
# image_file_name :string
# image_content_type :string
# image_file_size :integer
# image_updated_at :datetime
我的应用的完整代码可在github.com/johnnyji/wanderful处找到。
我非常感谢任何帮助!谢谢
答案 0 :(得分:0)
让我们一步一步地完成这一过程。
首先,将MetaInspector gem添加到Gemfile
gem 'metainspector'
并运行bundle
命令。
我们需要另外一些代码:open-uri
。有了它,我们可以从URL读取远程文件,就像它们是本地文件一样。它是Rubys标准库的一部分,因此它已经内置,但我们仍然需要{post}顶部的require
.rb:
require 'open-uri'
class Post < ActiveRecord::Base
belongs_to :user
has_attached_file :image
end
我们希望每当帖子link
发生变化时都会抓取图片,因此我们会在发生这种情况时进行before_save
回调:
class Post < ActiveRecord::Base
belongs_to :user
has_attached_file :image
before_save :get_image_from_link,
if: ->(post) { post.link_changed? }
end
before_save
和其他回调的更多信息。link_changed?
方法是&#34;脏跟踪&#34;的一部分功能ActiveModel::Dirty提供if: ->(post)
被称为&#34; stabby lambda&#34; - 它基本上只是一个以当前post
作为参数调用的Ruby函数。如果它返回true
,则运行before_action
。它也可以写成if: Proc.new { |post| post.link_changed? }
现在我们需要get_image_from_link
方法。由于它只应该从Post
模型本身而不是从外部(例如Post.find(5).get_image_from_link
)调用,因此我们将其设为私有方法:
class Post < ActiveRecord::Base
belongs_to :user
has_attached_file :image
before_save :get_image_from_link,
if: ->(post) { post.link_changed? }
private
def get_image_from_link
end
end
阅读MetaInspectors自述文件时,它有一个名为page.images.best
的酷方法,可以帮助我们从该页面选择正确的图像。所以我们要去
open-uri
作为File
对象File
- 类似对象提供给Paperclip
以保存为附件所以:
def get_image_from_link
# `link` here is `self.link` = the current post.
# At least when reading attributes, `self` is implicit
# in Ruby
page = MetaInspector.new(link)
# maybe the page didn't have images?
return unless page.images.best.present?
# when you use IO resources such as files, you need
# to take care that you `.close` everything you open.
# Using the block form takes care of that automatically.
open(page.images.best) do |file|
# when writing/assigning a value, `self` is not
# implicit, because when you write `something = 5`,
# Ruby cannot know whether you want to assign to
# `self.something` or create a new local variable
# called `something`
self.image = file
end
end
这远非完美,因为它缺少一些错误处理(如果MetaInspector无法打开页面怎么办?或者open-uri无法读取图像URL?)。此外,这具有以下缺点:所有解析,下载等都在用户提交或更新其帖子时发生,因此当她点击保存按钮时,她必须等待所有这些完成。
对于下一次迭代,请考虑异步执行这些操作,例如使用作业队列。轨道&#39;新的Active Job系统可能是一个很好的起点。