Статьи

Создать RSS-ридер в Rails легко

RSS Красный шестиугольник 3D значок современного дизайна на белом фоне

Эта статья была рецензирована Томом Паркином . Спасибо всем рецензентам SitePoint за то, что сделали контент SitePoint как можно лучше!

Канал RSS — это формат данных, используемый веб-сайтами (в основном, блогами) для доставки контента пользователям. Большинство веб-сайтов, включая SitePoint, публикуют фид в качестве другого средства распространения контента. Фид — это поток, в котором обновленный контент публикуется в одном из стандартизированных форматов и может использоваться читателями, например, RSS-клиентами.

Использование RSS-канала позволяет вам следить за многими из ваших любимых веб-сайтов и собирать обновленную информацию в одном месте. Существуют социальные сети и электронные рассылки, которые служат этой цели, но гибкость — это то, что отличает каналы. Существует множество программ чтения каналов, которые позволяют вам вводить все URL-адреса каналов, по которым вы хотите подписаться, и читать их в одном месте. Сегодня мы собираемся создать один такой читатель, чтобы доставить вам удовольствие от чтения. Мы также будем кэшировать содержимое для чтения в автономном режиме.

Давайте начнем.

Начальная загрузка приложения

Мы собираемся построить приложение в Rails 4. Хотя оно может работать со старыми версиями, рекомендуется не отставать от последней версии, чтобы избежать проблем с зависимостями. Давайте создадим наше приложение Rails, выполнив следующую команду:

rails new feedreader -d postgresql

Примечание. Предполагается, что PostgreSQL работает на локальном хосте. Если нет, не стесняйтесь опускать флаг -d

Когда генераторы Rails будут готовы, cd

 rake db:create

Давайте также добавим гемные зависимости, которые мы будем использовать в этом приложении. Поскольку это довольно минимальное приложение, нам понадобится всего два гема , feedjira для обработки каналов и twitter-bootstrap-rails для небольшого стилевого оформления. Часть начальной загрузки полностью необязательна, и вы можете игнорировать ее, если хотите использовать свой собственный дизайн.

Добавьте следующие драгоценные камни в Gemfile:

 gem 'feedjira'
gem 'twitter-bootstrap-rails'

и запустите bundle install

После завершения установки запустите генератор начальной загрузки:

 rails generate bootstrap:install static

Это добавит необходимые файлы начальной загрузки и добавит требуемые require На этом наша начальная загрузка завершена. Если вы используете контроль версий, что рекомендуется, сейчас самое время для фиксации изменений.

Создание моделей

Пришло время создавать модели для нашего приложения. Структура проста, так как у нас есть только две модели: FeedEntry FeedEntry Это будет схема для нашего приложения:

qiPd9cv
Давайте сначала создадим модель Feed. Это достаточно просто, чтобы просто помост. Выполните следующие команды, чтобы восстановить и перенести:

 rails g scaffold feed name url description:text
rake db:migrate

Это создает необходимую модель, контроллер и просмотр файлов, связанных с каналами. Нам не нужно вносить никаких изменений ни в один из файлов, просто добавьте rootconfig / rout.rb :

 root 'feeds#index'

Вот и все. Запустите сервер и добавьте ваши любимые каналы. Вероятно, это хорошая идея, чтобы зафиксировать ваши изменения в git:

 git add -A
git commit -m "Add Feed scaffold"

Далее, давайте создадим модель Entry Так как мы собираемся хранить записи с помощью граблей, нет необходимости в полноценных компонентах. Мы можем создать модель Entry напрямую, выполнив следующую команду:

 rails g model entry title published:datetime content:text url author feed_id:integer
rake db:migrate

После завершения миграции добавьте отношение к обеим моделям:

 ## models/feed.rb
class Feed < ActiveRecord::Base
    has_many :entries, dependent: :destroy
end

## models/entry.rb
class Entry < ActiveRecord::Base
    belongs_to :feed
end

С этим мы полностью уладили модели. Теперь пришло время создать грабли для заполнения модели Entry из добавленных каналов:

Обновление фида

Как я упоминал ранее, у нас будет грабельная задача в качестве точки входа для всех данных в таблице Entries. Эту задачу можно запланировать на выполнение через определенные промежутки времени для синхронизации содержимого канала с нашей базой данных. Начните с создания грабли в lib / tasks с именем sync.rake . После создания файла добавьте в него следующее содержимое:

 namespace :sync do
  task feeds: [:environment] do
    Feed.all.each do |feed|
      content = Feedjira::Feed.fetch_and_parse feed.url
      content.entries.each do |entry|
        local_entry = feed.entries.where(title: entry.title).first_or_initialize
        local_entry.update_attributes(content: entry.content, author: entry.author, url: entry.url, published: entry.published)
        p "Synced Entry - #{entry.title}"
      end
      p "Synced Feed - #{feed.name}"
    end
  end
end

Задача rake проходит по всем каналам, хранящимся в базе данных, и извлекает новейшее содержимое для каждого из них. Начиная с этого, просматривайте новые записи, создавая или обновляя их в базе данных. Мы обновляем каждый раз, чтобы не отставать от любых изменений в исходном контенте.

После того, как вы добавили это, попробуйте запустить задачу rake:

 bundle exec rake sync:feeds

Вы можете видеть, что содержимое было добавлено в таблицу Entry. Это легко проверить, войдя в консоль Rails:

 $ rails console
> Entry.count

Хорошо, теперь для последнего шага. Давайте создадим контроллер для записей.

Отображение канала

Начнем с создания контроллера для нашей модели Entries. Нам нужно только два действия: indexshow

 rails g controller entries index show

После выполнения вышеуказанной команды будут созданы файлы контроллера и представления. Перейдите на route.rb, измените следующие строки и добавьте их в ресурсы каналов:

 get 'entries/index'
get 'entries/show'

в

 resources :feeds do
  member do
   resources :entries, only: [:index, :show]
  end
end

У нас есть вложенные записи под конкретным потоком здесь. Перейдите к контроллеру Entries и добавьте следующее:

 # app/controllers/entries_controller.rb
class EntriesController < ApplicationController
  before_action :set_feed, only: :index

  def index
    @entries = @feed.entries.order('published desc')
  end

  def show
    @entry = Entry.find(params[:id])
  end

  private
  def set_feed
    @feed = Feed.find(params[:id])
  end
end

Мы выбираем соответствующий канал по идентификатору для страницы index Давайте также внесем необходимые изменения в представления:

 # app/views/entries/index.html.erb
<div class="container">
  <% @entries.each do |entry| %>
    <div class="panel panel-default">
      <div class="panel-body">
        <%= link_to entry.title, entry %> - <i> published <%= time_ago_in_words(entry.published) %> ago.</i>
      </div>
    </div>
  <% end %>
</div>

# app/views/entries/show.html.erb
<div class="container">
  <h3><%= link_to @entry.title, @entry.url %></h3>
  <i>published on <%= @entry.published %> by <%= @entry.author %></i>
  <p>
    <%= @entry.content.html_safe %>
  </p>
</div>

Код выше тривиален. Мы отображаем запись, настроенную в соответствии с нашими потребностями. Следует отметить, что мы использовали html_safeshow Это позволяет нам рендерить HTML в Entry. С этим изменением мы закончили наш крошечный читатель, который просто работает. Сохраните изменения и запустите сервер.

Наше завершенное приложение выглядит примерно так после добавления URL и запуска задачи rake:

gVMou

gVMot

Я знаю, что это не самый лучший читатель фидов, но он позволяет вам его создать. У нас есть функциональность, теперь используйте ваше воображение для дизайна.

Вывод

Весь пример кода, используемый в этом уроке, доступен на Github, не стесняйтесь разбирать и тыкать.

Спасибо, что нашли время прочитать этот учебник, и я надеюсь, что он послужил вашим целям До скорого.