Module: News
- Defined in:
- lib/newscast.rb
Defined Under Namespace
Classes: Configuration, Connection, Template
Class Method Summary collapse
-
.autogen_feed_key(feed_url) ⇒ Object
helpers.
-
.between(start_date, end_date) ⇒ Object
helper for week, q1, q2, etc.
-
.channels ⇒ Object
convenience alias for feeds.
- .config ⇒ Object
-
.configure {|config| ... } ⇒ Object
class Configuration.
-
.connection ⇒ Object
class Connection.
- .feeds ⇒ Object
- .items ⇒ Object
-
.latest ⇒ Object
note: “default” scope orders (sorts) by latest / time.
- .month(month = Date.today.month, year = Date.today.year) ⇒ Object
-
.norm_feed_hash(old_h) ⇒ Object
todo/check: rename to normalize/unify_feeds or resolve_feedlist or something?.
- .q(quarter = Date.today.quarter, year = Date.today.year) ⇒ Object
- .q1(year = Date.today.year) ⇒ Object
- .q2(year = Date.today.year) ⇒ Object
- .q3(year = Date.today.year) ⇒ Object
- .q4(year = Date.today.year) ⇒ Object
- .quarter(quarter = Date.today.quarter, year = Date.today.year) ⇒ Object
- .quarter1(year = Date.today.year) ⇒ Object
- .quarter2(year = Date.today.year) ⇒ Object
- .quarter3(year = Date.today.year) ⇒ Object
- .quarter4(year = Date.today.year) ⇒ Object
-
.refresh ⇒ Object
convenience alias for update.
-
.render(text, **kwargs) ⇒ Object
class Template.
-
.site ⇒ Object
note: defaults to news.
-
.site=(value) ⇒ Object
todo/check: allow (add) site = nil for no site “filter” (all items / feeds) - why? why not?.
- .subscribe(*feeds) ⇒ Object
- .this_month ⇒ Object
- .this_quarter ⇒ Object
-
.this_week ⇒ Object
convenience alias - keep - why? why not?.
- .this_year ⇒ Object
- .today ⇒ Object
- .update ⇒ Object
- .week(week = Date.today.cweek, year = Date.today.year) ⇒ Object
- .year(year = Date.today.year) ⇒ Object
Class Method Details
.autogen_feed_key(feed_url) ⇒ Object
helpers
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/newscast.rb', line 68 def self.autogen_feed_key( feed_url ) ## note: ## use a "fingerprint" hash digest as key ## do NOT include scheme (e.g. https or http) ## do NOT include port ## so you can change it without "breaking" the key - why? why not? ## ## e.g. u = URI( 'https://example.com:333/a/b?f=xml' ## u.host+u.request_uri ## #=> example.com/a/b?f=xml uri = URI( feed_url ) ## note: add host in "plain" text - making errors and the key more readable ## note: cut-off www. if leading e.g. www.ruby-lang.org => ruby-lang.org host = uri.host.downcase.sub( /^www\./, '' ) # use a differt separator e.g _ or ~ and NOT $ - why? why not? key = "#{host}$#{Digest::MD5.hexdigest( uri.request_uri )}" key end |
.between(start_date, end_date) ⇒ Object
helper for week, q1, q2, etc.
220 221 222 223 224 225 226 227 228 |
# File 'lib/newscast.rb', line 220 def self.between( start_date, end_date ) ## helper for week, q1, q2, etc. q_start = start_date.strftime('%Y-%m-%d') q_end = end_date.strftime('%Y-%m-%d') items. where( Arel.sql( "date(coalesce(items.updated,items.published,'1970-01-01')) BETWEEN '#{q_start}' AND '#{q_end}'" ) ) end |
.channels ⇒ Object
convenience alias for feeds
189 |
# File 'lib/newscast.rb', line 189 def self.channels() feeds; end |
.config ⇒ Object
329 330 331 |
# File 'lib/newscast.rb', line 329 def self.config @config ||= Configuration.new end |
.configure {|config| ... } ⇒ Object
class Configuration
325 326 327 |
# File 'lib/newscast.rb', line 325 def self.configure yield( config ) end |
.connection ⇒ Object
class Connection
347 348 349 350 351 |
# File 'lib/newscast.rb', line 347 def self.connection ## use for "auto-magic" connection w/ automigrate ## todo/fix: check - "just simply" return ActiveRecord connection - possible - why? why not? ## do NOT use our own Connection class @connection ||= Connection.new end |
.feeds ⇒ Object
176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/newscast.rb', line 176 def self.feeds connection ## note: always use "multi-site" setup; defaults to 'news' site key ## note: add "default" scope - orders (sorts) by latest / time rec = Pluto::Model::Site.where(key: site).first if rec.nil? Pluto::Model::Feed.none ## use null (relation) pattern to avoid crash on nil - why? why not? else rec.feeds.order( Arel.sql( "coalesce(feeds.updated,feeds.published,'1970-01-01') desc" ) ) end end |
.items ⇒ Object
192 193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/newscast.rb', line 192 def self.items connection ## make sure we have a database connection (and setup) up-and-running ## note: always use "multi-site" setup; defaults to 'news' site key ## note: add "default" scope - orders (sorts) by latest / time rec = Pluto::Model::Site.where(key: site).first if rec.nil? Pluto::Model::Item.none ## use null (relation) pattern to avoid crash on nil - why? why not? else rec.items.order( Arel.sql( "coalesce(items.updated,items.published,'1970-01-01') desc" ) ) end end |
.latest ⇒ Object
note: “default” scope orders (sorts) by latest / time
205 |
# File 'lib/newscast.rb', line 205 def self.latest() items; end |
.month(month = Date.today.month, year = Date.today.year) ⇒ Object
241 242 243 244 245 246 247 |
# File 'lib/newscast.rb', line 241 def self.month( month=Date.today.month, year=Date.today.year ) q = "%4d-%02d" % [year,month] # e.g. 2020-01 etc. items. where( Arel.sql( "strftime('%Y-%m', coalesce(items.updated,items.published,'1970-01-01')) = '#{q}'" ) ) end |
.norm_feed_hash(old_h) ⇒ Object
todo/check: rename to normalize/unify_feeds or resolve_feedlist or something?
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/newscast.rb', line 87 def self.norm_feed_hash( old_h ) ## todo/check: rename to normalize/unify_feeds or resolve_feedlist or something? ## unify feed list entries ## case 1) if section name is some thing like [Andrew Kane] ## and NO title/name key than assume it's the title/name ## and auto-generated key/id ## move all "global" settings to [planet] section - why? why not? ## e.g. ## title = Planet Open Data News ## becomes ## [planet] ## title = Planet Open Data News h = {} old_h.each do |k,v| if v.is_a?( String ) h[ k ] = v ## pass along as-is (assume "top-level" / global setting) elsif v.is_a?( Hash ) ## puts "#{k}:" ## pp v ## todo/fix: use "proper" ident e.g. allow 0-9 and .-_ too? why? why not? if k =~ /^[a-z_][a-z0-9$_.]*$/ ## all lower case; assume id - add 0-9 and .-_ - why? why not? h[ k ] = v else ## puts "bingo! section name shortcut - #{k}" if k.start_with?( 'http' ) if v.has_key?( 'feed' ) then raise ArgumentError.new( "duplicate >feed< hash table entry in section >#{k}<; cannot autogen key" ); end new_k = autogen_feed_key( k ) # note: use merge - why? why not? to NOT overwrite existing entry - why? why not? h[ new_k ] = { 'feed' => k }.merge( v ) else ## transform key to title and auto-generate id (new key) if v.has_key?( 'title' ) || v.has_key?( 'name' ) then raise ArgumentError.new( "duplicate >name< or >title< hash table entry in section >#{k}<; cannot autogen key" ); end if v.has_key?( 'feed' ) == false then raise ArgumentError.new( "expected / required >feed< hash table entry missing for section >#{k}<"); end new_k = autogen_feed_key( v['feed'] ) # note: use merge - why? why not? to NOT overwrite existing entry - why? why not? h[ new_k ] = { 'title' => k }.merge( v ) end end else raise ArgumentError.new( "expected String or Hash for value (in hash table) but got >#{v.class.name}< for key >#{k}<" ) end end ## todo/check - auto-add required (?) missing title if missing - why? why not? h['title'] = 'Untitled' if h.has_key?( 'title' ) == false h end |
.q(quarter = Date.today.quarter, year = Date.today.year) ⇒ Object
264 |
# File 'lib/newscast.rb', line 264 def self.q( quarter=Date.today.quarter, year=Date.today.year ) quarter( quarter, year ); end |
.q1(year = Date.today.year) ⇒ Object
265 |
# File 'lib/newscast.rb', line 265 def self.q1( year=Date.today.year ) quarter1( year ); end |
.q2(year = Date.today.year) ⇒ Object
266 |
# File 'lib/newscast.rb', line 266 def self.q2( year=Date.today.year ) quarter2( year ); end |
.q3(year = Date.today.year) ⇒ Object
267 |
# File 'lib/newscast.rb', line 267 def self.q3( year=Date.today.year ) quarter3( year ); end |
.q4(year = Date.today.year) ⇒ Object
268 |
# File 'lib/newscast.rb', line 268 def self.q4( year=Date.today.year ) quarter4( year ); end |
.quarter(quarter = Date.today.quarter, year = Date.today.year) ⇒ Object
249 250 251 252 253 254 255 256 257 |
# File 'lib/newscast.rb', line 249 def self.quarter( quarter=Date.today.quarter, year=Date.today.year ) case quarter when 1 then between( Date.new( year, 1, 1), Date.new( year, 3, 31) ); when 2 then between( Date.new( year, 4, 1), Date.new( year, 6, 30) ); when 3 then between( Date.new( year, 7, 1), Date.new( year, 9, 30) ); when 4 then between( Date.new( year, 10, 1), Date.new( year,12, 31) ); else raise ArgumentError end end |
.quarter1(year = Date.today.year) ⇒ Object
259 |
# File 'lib/newscast.rb', line 259 def self.quarter1( year=Date.today.year ) quarter(1, year); end |
.quarter2(year = Date.today.year) ⇒ Object
260 |
# File 'lib/newscast.rb', line 260 def self.quarter2( year=Date.today.year ) quarter(2, year); end |
.quarter3(year = Date.today.year) ⇒ Object
261 |
# File 'lib/newscast.rb', line 261 def self.quarter3( year=Date.today.year ) quarter(3, year); end |
.quarter4(year = Date.today.year) ⇒ Object
262 |
# File 'lib/newscast.rb', line 262 def self.quarter4( year=Date.today.year ) quarter(4, year); end |
.refresh ⇒ Object
convenience alias for update
172 |
# File 'lib/newscast.rb', line 172 def self.refresh() update; end |
.render(text, **kwargs) ⇒ Object
class Template
312 313 314 315 |
# File 'lib/newscast.rb', line 312 def self.render( text, **kwargs ) template = Template.new( text ) template.render( **kwargs ) end |
.site ⇒ Object
note: defaults to news
62 |
# File 'lib/newscast.rb', line 62 def self.site() @site ||= 'news'; end |
.site=(value) ⇒ Object
todo/check: allow (add) site = nil for no site “filter” (all items / feeds) - why? why not?
61 |
# File 'lib/newscast.rb', line 61 def self.site=(value) @site = value; end |
.subscribe(*feeds) ⇒ Object
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/newscast.rb', line 140 def self.subscribe( *feeds ) site_hash = if feeds.size == 1 && feeds[0].is_a?( Hash ) ## puts "bingo! it's a hash" norm_feed_hash( feeds[0] ) elsif feeds.size == 1 && feeds[0].is_a?( String ) && feeds[0] =~ /\n/ ## string includes newline (e.g. more than a single line?) ## if yes, parse and assume ini (config) format norm_feed_hash( INI.load( feeds[0] )) else ## assume list / array of strings (feed_urls) ## puts "bingo! it's a string list" ## auto-build a (simple) site hash feeds.reduce( { ## note: keys are strings (NOT symbols) for now 'title' => 'Untitled' ## todo/check: remove title? required? check in model update if missing? } ) do |h, feed| key = autogen_feed_key( feed ) h[ key ] = { 'feed' => feed } h end end connection ## make sure we have a database connection (and setup) up-and-running ## note: always use "multi-site" setup; defaults to 'news' site key Pluto::Model::Site.deep_create_or_update_from_hash!( site, site_hash ) end |
.this_month ⇒ Object
283 |
# File 'lib/newscast.rb', line 283 def self.this_month() month; end |
.this_quarter ⇒ Object
284 |
# File 'lib/newscast.rb', line 284 def self.this_quarter() quarter; end |
.this_week ⇒ Object
convenience alias - keep - why? why not?
282 |
# File 'lib/newscast.rb', line 282 def self.this_week() week; end |
.this_year ⇒ Object
285 |
# File 'lib/newscast.rb', line 285 def self.this_year() year; end |
.today ⇒ Object
208 209 210 211 212 213 214 215 216 217 |
# File 'lib/newscast.rb', line 208 def self.today ## todo: order by time!! - possible - why? why not? ## note: use date() to cut-off hours etc. if present? q = Date.today.strftime('%Y-%m-%d') # e.g. 2020-02-20 items. where( Arel.sql( "date(coalesce(items.updated,items.published)) = '#{q}'" ) ) end |
.update ⇒ Object
168 169 170 171 |
# File 'lib/newscast.rb', line 168 def self.update connection ## make sure we have a database connection (and setup) up-and-running Pluto.update_feeds end |
.week(week = Date.today.cweek, year = Date.today.year) ⇒ Object
230 231 232 233 234 235 236 237 238 239 |
# File 'lib/newscast.rb', line 230 def self.week( week=Date.today.cweek, year=Date.today.year ) ## note: SQLite only supports "classic" week of year (not ISO "commercial week" starting on monday - and not on sunday) ## %W - week of year: 00-53 ## thus, needs to calculate start and end date!!! start_date = Date.commercial(year, week, 1) end_date = Date.commercial(year, week, 7) between( start_date, end_date ) end |
.year(year = Date.today.year) ⇒ Object
271 272 273 274 275 276 277 |
# File 'lib/newscast.rb', line 271 def self.year( year=Date.today.year ) q = year items. where( Arel.sql( "strftime('%Y', coalesce(items.updated,items.published,'1970-01-01')) = '#{q}'" ) ) end |