Skip to content

Instantly share code, notes, and snippets.

@Inviz
Created February 11, 2009 10:34
Show Gist options
  • Save Inviz/61952 to your computer and use it in GitHub Desktop.
Save Inviz/61952 to your computer and use it in GitHub Desktop.
module Templating
class Buffer
attr_accessor :buffer
def initialize(controller, language = :html)
@controller = controller
@hooks = {}
@counter = 0
self.extend language == "wml" ? WML : HTML
self.extend Abstract
self.buffer = []
end
def counter
@counter += 1
@counter - 1
end
def before(&block)
@hooks[:before] = block
end
def after(&block)
@hooks[:after] = block
end
def output(&block) #good thing, but unused
if block
instance_eval &block
else
to_s
end
end
def to_s
page_open + call_hook(:before) + (buffer * " ") + call_hook(:after) + page_close
end
def each
#this is a hack. Merb calls `each` on the object, if action returns it.
#I tie render here, so i dont need to specify it in each action of controller
yield(to_s)
end
private
def call_hook(which = :before)
return '' unless @hooks[which]
buff = @buffer
@buffer = []
@hooks[which].call(self)
ret = @buffer * " "
@buffer = buff
ret
end
end
module Abstract #are the tags to be used
def link_to(text, url, key = false)
puts link(text, url, key)
end
def heading(text, url = nil)
puts header(url ? link(text, url) : text)
end
def message(text = "")
puts paragraph(text)
end
def separator
puts hr
end
def paginator(items)
formatted_paginator items
end
def list(items, empty_message = "Список пуст")
sub = []
unless items.empty?
sub << list_open
items.each do |i|
sub << list_item_open
sub << (i.respond_to?(:to_item) ? link(*i.to_item) : i.to_s)
sub << list_item_close
end
sub << list_close
else
sub << empty_message
end
puts sub
paginator(items) if (!items.empty? && items.respond_to?(:next_page))
self
end
def quickform(*args)
puts form(*args)
end
def puts(*args)
buffer << (args * " ")
self
end
end
module WML
def page_open
['<?xml version="1.0" encoding="UTF-8"?>',
'<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">',
'<wml>',
'<meta http-equiv="Cache-Control" content="no-cache" forua="true"/>',
'<card id="index" title="',
@controller.page_title,
'">', back].join
end
def page_close
'</card>' + 'back' + '</wml>'
end
def paragraph(text)
"#{text}<br /><br />"
end
def header(text, big = false)
"<big>#{text}</big><br />"
end
def list_open
""
end
def list_close
"<br />"
end
def list_item_open
"- "
end
def list_item_close
"<br />"
end
def link(text, url = "#", key = false)
"<a href='#{@controller.sessioned(url)}' accesskey='#{key || counter}'>#{text}</a>"
end
def hr
"<br /><br />"
end
def accept(label = "Ещё", url = false) # phone buttons remapper
"<do type='accept' name='a' label='#{label}'><go href='#{url}'/></do>"
end
def back(label = "Назад")
"<do type='back' label='#{label}'><prev /></do>"
end
def formatted_paginator(items)
#nator = Paginator.new(items, self, :outer_window => -1, :inner_window => -1, :prev_label => "Назад", :next_label => "Ещё")
#nator.to_s
if items.next_page && (items.next_page <= items.total_pages)
puts accept("Ещё", @controller.sessioned("?page=#{items.next_page}"))
end
end
def form(label = "Найти", label2 = "Искать", url = "/", param = "id")
"#{label}<br /><input name='ss'/><anchor><go href='#{@controller.sessioned(url + '$ss', 'q')}'/>#{label2}</anchor>"
end
end
module HTML
def page_open
['<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
'<html>',
'<head>',
'<meta http-equiv="Content-Type" content="text/html; charset=utf-8">',
'<title>',
@controller.page_title,
'</title>',
'</head>'].join
end
def page_close
'</html></body>'
end
def link(text, url = "#", key = false)
"<a href='#{@controller.sessioned(url)}' accesskey='#{key || counter}'>#{text}</a>"
end
def header(text, big = false)
tag = big ? "h2" : "h1"
"<#{tag}>#{text}</#{tag}>"
end
def list_open
"<ul>"
end
def list_close
"</ul>"
end
def list_item_open
"<li>"
end
def list_item_close
"</li>"
end
def paragraph(text)
"<p>#{text}</p>"
end
def hr
"<hr />"
end
def formatted_paginator(items)
Paginator.new(items, self).to_s
end
def form(label = "Найти", label2 = "Искать", url = "/", param = "id")
"#{label}:<br /><form action='#{@controller.sessioned(url, 'q')}'><input name='#{param}' /> <input type='submit' value='#{label2}' /></form>"
end
end
# This is extracted from another app
# Atleast it's 267 times cleaner than WP
class Paginator
attr_accessor :r
def initialize(collection, r, opts = {})
@options = {
:prev_label => opts.delete(:prev_label) || "&lt;",
:next_label => opts.delete(:next_label) || "&gt;",
:inner_window => opts.delete(:inner_window) || 3,
:outer_window => opts.delete(:outer_window) || 2
}
@collection = collection
@r = r
@url = "?#{opts.delete(:param_name) || 'page'}=%s"
end
def visible_pages
outer = @options[:outer_window]
inner = @options[:inner_window]
current = @collection.current_page
count = @collection.total_pages
#following is ruby cuteness
((1..(inner + 1)).entries | #left
((current - inner)..(current + inner)).entries | #middle
((count - outer)..count).entries) & #right
(1..count).entries #now intersect
end
def url_for_page(page = nil)
@url % page if page
end
def item(text, page)
if !page || page.zero? || (page == @collection.current_page)
r.puts text
else
r.link_to text, url_for_page(page)
end
end
def show?
@collection.total_pages > 1
end
def to_s
return "" unless show?
item @options[:prev_label], @collection.previous_page
visible_pages.each do |page|
item page, page
end
item @options[:next_label], @collection.next_page
end
end
end
#used like that:
module Search
def random(model)
r.heading "Случайные результаты:"
r.list model.find(:all, :limit => 3, :order => "random()")
end
def filter(q, model, label = "Искать")
r.quickform label, "Найти", "?q="
r.separator
if q.blank?
random(model)
else
contents = model.paginate(:page => current_page, :conditions => ["lower(name) like ?", "%#{q.downcase}%"])
if contents.blank?
r.message "Ничего не найдено."
random(model)
else
r.list contents
end
end
end
end
def fetch_news
Yandex::News::List.new("Ulan-Ude").each do |item|
New.create_from_item(item)
end
end
$kcode = 'u'
require 'rss/1.0'
require 'rss/2.0'
require 'open-uri'
require 'iconv'
module Yandex
module News
class List
attr_reader :url, :items
include Enumerable
def initialize(category = nil)
@rss = ["http://news.yandex.ru", category, "index.rss"].compact * "/"
end
def each(&block)
fetch.each(&block)
end
private
def fetch
items.map { |item| Item.new(item) }
end
def items
content = ""
open(@rss) { |s| content = s.read }
@items = ::RSS::Parser.parse(content, false).items or raise "Unable to parse #{@rss}"
end
end
class Item
attr_reader :date, :link
def initialize(item)
@date = item.pubDate
@link = item.link
end
def title
data[:title]
end
def summaries
data[:summaries]
end
def category
data[:category]
end
def quote
data[:quote]
end
private
def data
@data ||= Item.parse_url(@link)
end
class << self
TITLE_RE = /<H2>([^<]*)/m.freeze
SUMMARIES_RE = /<dl class="lefts">(.*)<\/dl>/m.freeze
SUMMARY_RE = /<dd>(.*?)\s*<span class=source>&nbsp;<!--&#8594;&nbsp;--><a href="(.*?)"[^>]*>(.*?)</m.freeze
CATEGORY_RE = /<p class="toplinks">[^>]*>(.*?)</m.freeze
def parse_url(url)
content = ""
open(url) { |s| content = s.read }
content = converter.iconv content
data = {}
begin
data[:title] = content.match(TITLE_RE)[1]
data[:category] = content.match(CATEGORY_RE)[1]
data[:category] = nil if data[:category].blank?
data[:summaries] = content.match(SUMMARIES_RE)[1].scan(SUMMARY_RE).map do |summary|
{:body => summary[0], :link => summary[1], :source => summary[2]}
end
rescue
raise "Unable to parse #{url}. Has layout changed there?"
end
data
end
def converter
@converter ||= Iconv.new('UTF-8','WINDOWS-1251')
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment