Get Feeds source with Feedjira Gem - ruby-on-rails

I use Feedjira Gem (Rails) to fetch/grab the rss-feeds from several websites. Everything works fine, but the only that has bugged me long time is the source-feed (the website I grab the rss from).
I want to show users which website the rss comes from. Right now, I grab the whole url, but I want to only grab what is after www and before .com. Anyway I can get it work or I can grab the feed source from the rss file.
I see this in rss file, but can't grab it.
<channel>
<link>http://www.domain.com/</link>
And here is my whole model.
class FeedEntry < ActiveRecord::Base
acts_as_punchable
def self.update_from_feed(feed_url)
feed = Feedjira::Feed.fetch_and_parse(feed_url)
add_entries(feed.entries)
end
private
def self.add_entries(entries)
entries.each do |entry|
unless exists? :guid => entry.id
create!(
:name => entry.title,
:url => entry.url,
:guid => entry.id,
:source => entry.url,
:summary => entry.summary,
:published_at => entry.published,
)
end
end
end
end
Thanks in advance!

You can grab the source by
feed = Feedjira::Feed.fetch_and_parse(feed_url)
source = feed.url # -> http://www.domain.com/
To grab what is after www and before .com, you can do something like this
source = URI.parse(feed.url).host.split('.')[-2] # -> domain
Now, here we go
def self.update_from_feed(feed_url)
feed = Feedjira::Feed.fetch_and_parse(feed_url)
source = URI.parse(feed.url).host.split('.')[-2]
add_entries(feed.entries, source)
end
private
def self.add_entries(entries, source)
entries.each do |entry|
unless exists? :guid => entry.id
create!(
:name => entry.title,
:url => entry.url,
:guid => entry.id,
:source => source,
:summary => entry.summary,
:published_at => entry.published,
)
end
end
end
It would work!

Related

How to generate sitemap for videos on rails app?

I am using sitemap_generator for my rails app. I was able to generate sitemap for everything except for video links on the website. Following is my
sitemap.rb
Equipment.find_each do |e|
add search_equipments_path(e), :changefreq => 'weekly'
end
Equipment.find_each do |more|
add equipment_details_path(more), :changefreq => 'weekly'
end
Category.find_each do |c|
add search_equipments_path(:category_id=>c.id), :changefreq => 'weekly'
end
Category.find_each do |sub|
add search_equipments_path(:sub_category=>sub.id), :changefreq => 'weekly'
end
Service.find_each do |s|
add service_details_path(s), :changefreq => 'weekly'
end
WantedEquipment.find_each do |f|
add wanted_equipments_path(f), :changefreq => 'weekly'
end
StaticPage.find_each do |t|
add benefits_for_buyers_path(t), :changefreq => 'weekly'
end
StaticPage.find_each do |sel|
add benefits_for_sellers_path(sel), :changefreq=> 'weekly'
end
StaticPage.find_each do |ser|
add benefits_for_service_providers_path(ser), :changefreq=> 'weekly'
end
add '/about-us'
add '/terms-and-conditions'
add '/pricing-plans'
add '/how-it-work'
This what is given on the documentation on the gem page for generating video sitemap:
SitemapGenerator::Sitemap.create do
add('/index.html', :video => {
:thumbnail_loc => 'http://www.example.com/video1_thumbnail.png',
:title => 'Title',
:description => 'Description',
:content_loc => 'http://www.example.com/cool_video.mpg',
:tags => %w[one two three],
:category => 'Category'
})
end
I am not able to understand how to pass these values dynamically.
If you want to generate video contents on basis of dynamic data, try this:
Model.all.each do |e|
video = VideoInfo.new(e.video_url)
add("https://example.com/views/#{e.slug}", :video => {
:thumbnail_loc => "#{video.thumbnail_medium}",
:title => "#{video.title}",
:description => "#{video.description}",
:content_loc => "#{e.video_url}",
:tags => e.slug.split('-'),
:player_loc => video.embed_url
})
end
Here VideoInfo is gem used for getting video meta info.
Can you use this sample but change it to your model name:
SitemapGenerator::Sitemap.create do
add '/contact_us', 'changefreq': 'weekly'
Article.find_each do |article|
add article_path(article), lastmod: article.updated_at
end
end
As you can see he makes find_each on articles model. So you can do the same on your video model.

Highcharts gem not working

I'm trying to create a line graph of weights for a user off of the lazy high charts gem.
I currently have in my users_controller
def show
#user = User.find(params[:id])
#weights = Weight.where(user_id: #user.id)
#weight_hash = #weights.to_json
#chart = LazyHighCharts::HighChart.new('graph') do |f|
f.title(:text => "Historical Weights")
f.xAxis(:type => 'datetime', :title => {:text =>'Date'})
f.yAxis(:title => {:text => "pounds"})
f.series(:name => 'Weight', :data => #weight_hash)
f.chart({defaultSeriesType => 'line'})
end
end
Within my weight model I have:
class Weight < ActiveRecord::Base
belongs_to :user
def as_json(*args)
{
:weight => self.weight,
:date => self.date
}
end
end
Then in my users/show.html.erb I have
<%= high_chart("Weight", #chart) %>
but i'm getting the error
undefined local variable or method `defaultSeriesType' for
#
I'm not sure how this method should be declared as it is part of the gem. Could anyone please explain what is going on?
In this line:
f.chart({defaultSeriesType => 'line'})
It looks like you forgot to add a colon to defaultSeriesType to make it a symbol, so Ruby thinks it's a variable/method. Try changing it to:
f.chart({:defaultSeriesType => 'line'})
...like the other hashes.

uninitialized constant CustomersController::CSV

I'm following the tutorial http://www.funonrails.com/2012/01/csv-file-importexport-in-rails-3.html]for upload files in rails 3, because I need that my app's user could upload csv files but when I tried to save the file I get: uninitialized constant CustomersController::CSV message, before change my routes to get "customers/import" to post "customers/import" I had other error No route matches [POST] "/customers/import" what Im doing wrong? thanks in advance.
MY CONTROLLER:
class CustomersController < ApplicationController
def import
if request.post? && params[:file].present?
infile = params[:file].read
n, errs = 0, []
CSV.parse(infile) do |row|
n += 1
# SKIP: header i.e. first row OR blank row
next if n == 1 or row.join.blank?
# build_from_csv method will map customer attributes &
# build new customer record
customer = Customer.build_from_csv(row)
# Save upon valid
# otherwise collect error records to export
if customer.valid?
customer.save
else
errs << row
end
end
# Export Error file for later upload upon correction
if errs.any?
errFile ="errors_#{Date.today.strftime('%d%b%y')}.csv"
errs.insert(0, Customer.csv_header)
errCSV = CSV.generate do |csv|
errs.each {|row| csv << row}
end
send_data errCSV,
:type => 'text/csv; charset=iso-8859-1; header=present',
:disposition => "attachment; filename=#{errFile}.csv"
else
flash[:notice] = I18n.t('customer.import.success')
redirect_to import_url #GET
end
end
end
end
MY MODEL:
class Customer < ActiveRecord::Base
scope :active, where(:active => true)
scope :latest, order('created_at desc')
def self.csv_header
"First Name,Last Name,Email,Phone,Mobile, Address, FAX, City".split(',')
end
def self.build_from_csv(row)
# find existing customer from email or create new
cust = find_or_initialize_by_email(row[2])
cust.attributes ={:first_name => row[0],
:last_name => row[1],
:email => row[3],
:phone => row[4],
:mobile => row[5],
:address => row[6],
:fax => row[7],
:city => row[8]}
return cust
end
def to_csv
[first_name, last_name, email, phone, mobile, address, fax, city]
end
end
*MY VIEW:
<h1>Subir Archivos</h1>
<%= form_tag('import', :multipart => true) do %>
<p>
File:<br />
<%= file_field_tag 'file' %><br />
</p>
<p>
<%= submit_tag "subir" %>
</p>
<% end %>
MY ROUTES:
Pruebaupcsv::Application.routes.draw do
post "customers/import"
You need to add a require 'csv' before you use it, either in an initializer, or at the top of your controller.

Nested Resource Not Properly Destroyed on Dependent Destroy

I'm having issue with a youtube video being destroyed properly in a nested belongs_to has_one relationship between a sermon and its sermon video when using :dependent => :destroy.
I'm using the youtube_it gem and have a fairly vanilla setup.
The relevant bits below:
the video controller --
def destroy
#sermon = Sermon.find(params[:sermon_id])
#sermon_video = #sermon.sermon_video
if SermonVideo.delete_video(#sermon_video)
flash[:notice] = "video successfully deleted"
else
flash[:error] = "video unsuccessfully deleted"
end
redirect_to dashboard_path
end
the video model --
belongs_to :sermon
def self.yt_session
#yt_session ||= YouTubeIt::Client.new(:username => YouTubeITConfig.username , :password => YouTubeITConfig.password , :dev_key => YouTubeITConfig.dev_key)
end
def self.delete_video(video)
yt_session.video_delete(video.yt_video_id)
video.destroy
rescue
video.destroy
end
the sermon model --
has_one :sermon_video, :dependent => :destroy
accepts_nested_attributes_for :sermon_video, :allow_destroy => true
In the above setup, all local data is removed successfully; however, the video on youtube is not.
I have tried to override the destroy action with a method in the model, but probably due a failing of my understanding, can only get either the video deleted from youtube, or the record deleted locally, never both at the same time (I posted the two variants below and their results).
This only serves to destroy the local record --
def self.destroy
#yt_session ||= YouTubeIt::Client.new(:username => YouTubeITConfig.username , :password => YouTubeITConfig.password , :dev_key => YouTubeITConfig.dev_key)
#yt_session.video_delete(self.yt_video_id)
#sermon_video.destory
end
This only serves to destroy the video on youtube, but not the local resource --
def self.destroy
#yt_session ||= YouTubeIt::Client.new(:username => YouTubeITConfig.username , :password => YouTubeITConfig.password , :dev_key => YouTubeITConfig.dev_key)
#yt_session.video_delete(self.yt_video_id)
end
Lastly, the link I'm using to destroy the sermon, in case it helps --
<%= link_to "Delete", [#sermon.church, #sermon], :method => :delete %>
Thanks for your help, very much appreciated!
It looks as though I have just solved the issue; however, I'll leave it open for a bit in case someone has a more elegant / appropriate solution.
In the sermon video model I added --
before_destroy :kill_everything
def kill_everything
#yt_session ||= YouTubeIt::Client.new(:username => YouTubeITConfig.username , :password => YouTubeITConfig.password , :dev_key => YouTubeITConfig.dev_key)
#yt_session.video_delete(self.yt_video_id)
end
And the key thing, I believe, to have added in the sermon model was this --
accepts_nested_attributes_for :sermon_video, :allow_destroy => true

Nested resource with Atom Feed Helper

I'm trying to use the Rails Atom Feed Helper to generate a feed for a nested resource. My view template (index.atom.builder) is:
atom_feed(:schema_date => #favourites.first.created_at) do |feed|
feed.title("Favourites for #{#user.login}")
feed.updated(#favourites.first.created_at)
#favourites.each do |favourite|
feed.entry(favourite, :url => favourite.asset.external_ref) do |entry|
entry.title(favourite.asset.external_ref)
entry.content(image_tag(favourite.asset.location), :type => 'html')
entry.author do |author|
author.name(#user.login)
end
end
end
end
And I have the following routes:
map.namespace :public do |pub|
pub.resources :users, :has_many => [ :favourites ]
pub.resources :favourites
pub.resources :assets, :only => [ :show ]
end
Unfortunately the url is failing to generate for the feed.entry line:
feed.entry(favourite, :url => favourite.asset.external_ref) do |entry|
The error is "undefined method `favourite_url' for ActionView::Base".
I've tried changing the feed.entry line to:
feed.entry([:public, favourite], :url => favourite.asset.external_ref) do |entry|
But this then returns the entry for an Array rather than a favourite! Someone had a similar problem here also.
I know that adding the line:
map.resource :favourites
to my routes.rb would 'fix' this problem but this resource is only available nested beneath the /public namespace.
Has anyone had this problem before?
Cheers
Arfon
Just to follow up. Based upon Michael's suggestion I'm passing the full url param and this seems to generate the correct url for the feed.entry line.
#favourites.each do |favourite|
feed.entry(favourite, :url => public_user_favourite_url(:id => favourite, :user_id => #user)) do |entry|
entry.title(favourite.asset.external_ref)
entry.content(image_tag(favourite.asset.location), :type => 'html')
entry.author do |author|
author.name(#user.zooniverse_user_id)
end
end
end
You are using favourite.asset.external_ref as the title of the entry, which leaves me to believe the URL for that entry should probably be defined as:
public_user_favourite_url(:id => favourite, :user_id => #user)
Which, if favorite.id = 9 and #user.id = 1, would generate:
http://localhost:3000/public/users/1/favourites/9
Is this what you are looking for?

Resources