feedzirra 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/lib/feedzirra/feed.rb +37 -23
- data/lib/feedzirra/feed_utilities.rb +1 -1
- data/lib/feedzirra/parser/atom.rb +1 -0
- data/lib/feedzirra/parser/atom_feed_burner.rb +1 -0
- data/lib/feedzirra/parser/itunes_rss_item.rb +1 -0
- data/lib/feedzirra/parser/rss.rb +1 -0
- data/lib/feedzirra/parser/rss_feed_burner.rb +1 -0
- data/lib/feedzirra/version.rb +1 -1
- data/spec/feedzirra/feed_spec.rb +60 -8
- data/spec/feedzirra/parser/atom_feed_burner_spec.rb +9 -0
- data/spec/feedzirra/parser/atom_spec.rb +10 -0
- data/spec/feedzirra/parser/itunes_rss_item_spec.rb +3 -0
- data/spec/feedzirra/parser/rss_feed_burner_spec.rb +5 -0
- data/spec/feedzirra/parser/rss_spec.rb +4 -0
- data/spec/sample_feeds/SamRuby.xml +582 -0
- data/spec/sample_feeds/TypePadNews.xml +367 -0
- data/spec/sample_feeds/itunes.xml +4 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95a08649fedde92fbdc49bf3df509bb0c2e95344
|
4
|
+
data.tar.gz: bed6f361c5d49a5ab122ecceabd8730b08111fe8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a84e2ffebe7036193224bc88b12a577c978f7fe04490f8547fdd32659ce7685a008f44e39d40eeb5dc4615a1fd77f59ab92d2f98e68fe3efc26e475c0ef6ea13
|
7
|
+
data.tar.gz: 385e01cbe1825b3a9421a06c15d75095be655602d201a9b9d5787b3a042e5c6dcac33d243786d7ab090181e0fd06a2b81f26167cbfaaf9d8ff9d3b85331856e0
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Feedzirra Changelog
|
2
2
|
|
3
|
+
## 0.4.0
|
4
|
+
|
5
|
+
* Enhancements
|
6
|
+
* Raise when parser invokes its failure callback [[#159](https://github.com/pauldix/feedzirra/issues/159)]
|
7
|
+
* Add PubSubHubbub hub urls as feed element [[#138](https://github.com/pauldix/feedzirra/pull/138)]
|
8
|
+
* Add support for iTunes image in iTunes RSS item [[#164](https://github.com/pauldix/feedzirra/pull/164)]
|
9
|
+
|
10
|
+
* Bug fixes
|
11
|
+
* Use curb callbacks rather than response codes [[#161](https://github.com/pauldix/feedzirra/pull/161)]
|
12
|
+
|
3
13
|
## 0.3.0
|
4
14
|
|
5
15
|
* General
|
data/lib/feedzirra/feed.rb
CHANGED
@@ -171,8 +171,9 @@ module Feedzirra
|
|
171
171
|
curl.on_success do |c|
|
172
172
|
responses[url] = decode_content(c)
|
173
173
|
end
|
174
|
-
|
175
|
-
|
174
|
+
|
175
|
+
curl.on_complete do |c, err|
|
176
|
+
responses[url] = c.response_code unless responses.has_key?(url)
|
176
177
|
end
|
177
178
|
end
|
178
179
|
multi.add(easy)
|
@@ -282,13 +283,13 @@ module Feedzirra
|
|
282
283
|
curl.headers["If-None-Match"] = options[:if_none_match] if options.has_key?(:if_none_match)
|
283
284
|
|
284
285
|
curl.on_success do |c|
|
285
|
-
add_url_to_multi(multi, url_queue.shift, url_queue, responses, options) unless url_queue.empty?
|
286
286
|
xml = decode_content(c)
|
287
287
|
klass = determine_feed_parser_for_xml(xml)
|
288
288
|
|
289
289
|
if klass
|
290
290
|
begin
|
291
|
-
feed = klass.parse
|
291
|
+
feed = klass.parse xml, on_parser_failure(url)
|
292
|
+
|
292
293
|
feed.feed_url = c.last_effective_url
|
293
294
|
feed.etag = etag_from_header(c.header_str)
|
294
295
|
feed.last_modified = last_modified_from_header(c.header_str)
|
@@ -298,8 +299,6 @@ module Feedzirra
|
|
298
299
|
options[:on_failure].call(url, c.response_code, c.header_str, c.body_str) if options.has_key?(:on_failure)
|
299
300
|
end
|
300
301
|
else
|
301
|
-
# puts "Error determining parser for #{url} - #{c.last_effective_url}"
|
302
|
-
# raise NoParserAvailable.new("no valid parser for content.") (this would unfortunately fail the whole 'multi', so it's not really usable)
|
303
302
|
options[:on_failure].call(url, c.response_code, c.header_str, c.body_str) if options.has_key?(:on_failure)
|
304
303
|
end
|
305
304
|
end
|
@@ -309,21 +308,24 @@ module Feedzirra
|
|
309
308
|
#
|
310
309
|
curl.on_complete do |c|
|
311
310
|
add_url_to_multi(multi, url_queue.shift, url_queue, responses, options) unless url_queue.empty?
|
312
|
-
responses[url] = c.response_code
|
311
|
+
responses[url] = c.response_code unless responses.has_key?(url)
|
312
|
+
end
|
313
|
+
|
314
|
+
curl.on_redirect do |c|
|
315
|
+
if c.response_code == 304 # it's not modified. this isn't an error condition
|
316
|
+
options[:on_success].call(url, nil) if options.has_key?(:on_success)
|
317
|
+
end
|
318
|
+
end
|
313
319
|
|
320
|
+
curl.on_missing do |c|
|
314
321
|
if c.response_code == 404 && options.has_key?(:on_failure)
|
315
322
|
options[:on_failure].call(url, c.response_code, c.header_str, c.body_str)
|
316
323
|
end
|
317
324
|
end
|
318
325
|
|
319
326
|
curl.on_failure do |c, err|
|
320
|
-
add_url_to_multi(multi, url_queue.shift, url_queue, responses, options) unless url_queue.empty?
|
321
327
|
responses[url] = c.response_code
|
322
|
-
|
323
|
-
options[:on_success].call(url, nil) if options.has_key?(:on_success)
|
324
|
-
else
|
325
|
-
options[:on_failure].call(url, c.response_code, c.header_str, c.body_str) if options.has_key?(:on_failure)
|
326
|
-
end
|
328
|
+
options[:on_failure].call(url, c.response_code, c.header_str, c.body_str) if options.has_key?(:on_failure)
|
327
329
|
end
|
328
330
|
end
|
329
331
|
multi.add(easy)
|
@@ -352,8 +354,8 @@ module Feedzirra
|
|
352
354
|
|
353
355
|
curl.on_success do |c|
|
354
356
|
begin
|
355
|
-
|
356
|
-
|
357
|
+
updated_feed = Feed.parse c.body_str, &on_parser_failure(feed.feed_url)
|
358
|
+
|
357
359
|
updated_feed.feed_url = c.last_effective_url
|
358
360
|
updated_feed.etag = etag_from_header(c.header_str)
|
359
361
|
updated_feed.last_modified = last_modified_from_header(c.header_str)
|
@@ -365,17 +367,21 @@ module Feedzirra
|
|
365
367
|
end
|
366
368
|
end
|
367
369
|
|
368
|
-
curl.on_failure do |c, err|
|
369
|
-
|
370
|
-
response_code
|
371
|
-
|
372
|
-
|
370
|
+
curl.on_failure do |c, err| # response code 50X
|
371
|
+
responses[feed.url] = c.response_code
|
372
|
+
options[:on_failure].call(feed, c.response_code, c.header_str, c.body_str) if options.has_key?(:on_failure)
|
373
|
+
end
|
374
|
+
|
375
|
+
curl.on_redirect do |c, err| # response code 30X
|
376
|
+
if c.response_code == 304
|
373
377
|
options[:on_success].call(feed) if options.has_key?(:on_success)
|
374
|
-
else
|
375
|
-
responses[feed.url] = c.response_code
|
376
|
-
options[:on_failure].call(feed, c.response_code, c.header_str, c.body_str) if options.has_key?(:on_failure)
|
377
378
|
end
|
378
379
|
end
|
380
|
+
|
381
|
+
curl.on_complete do |c|
|
382
|
+
add_feed_to_multi(multi, feed_queue.shift, feed_queue, responses, options) unless feed_queue.empty?
|
383
|
+
responses[feed.feed_url] = feed unless responses.has_key?(feed.feed_url)
|
384
|
+
end
|
379
385
|
end
|
380
386
|
multi.add(easy)
|
381
387
|
end
|
@@ -401,5 +407,13 @@ module Feedzirra
|
|
401
407
|
header =~ /.*Last-Modified:\s(.*)\r/
|
402
408
|
Time.parse_safely($1) if $1
|
403
409
|
end
|
410
|
+
|
411
|
+
class << self
|
412
|
+
private
|
413
|
+
|
414
|
+
def on_parser_failure(url)
|
415
|
+
Proc.new { |message| raise "Error while parsing [#{url}] #{message}" }
|
416
|
+
end
|
417
|
+
end
|
404
418
|
end
|
405
419
|
end
|
@@ -10,6 +10,7 @@ module Feedzirra
|
|
10
10
|
element :link, :as => :url, :value => :href, :with => {:type => "text/html"}
|
11
11
|
element :link, :as => :feed_url, :value => :href, :with => {:type => "application/atom+xml"}
|
12
12
|
elements :link, :as => :links, :value => :href
|
13
|
+
elements :link, :as => :hubs, :value => :href, :with => {:rel => "hub"}
|
13
14
|
elements :entry, :as => :entries, :class => AtomEntry
|
14
15
|
|
15
16
|
def self.able_to_parse?(xml) #:nodoc:
|
@@ -9,6 +9,7 @@ module Feedzirra
|
|
9
9
|
element :subtitle, :as => :description
|
10
10
|
element :link, :as => :url, :value => :href, :with => {:type => "text/html"}
|
11
11
|
element :link, :as => :feed_url, :value => :href, :with => {:type => "application/atom+xml"}
|
12
|
+
elements :"atom10:link", :as => :hubs, :value => :href, :with => {:rel => "hub"}
|
12
13
|
elements :entry, :as => :entries, :class => AtomFeedBurnerEntry
|
13
14
|
|
14
15
|
def self.able_to_parse?(xml) #:nodoc:
|
@@ -21,6 +21,7 @@ module Feedzirra
|
|
21
21
|
element :"itunes:explicit", :as => :itunes_explicit
|
22
22
|
element :"itunes:keywords", :as => :itunes_keywords
|
23
23
|
element :"itunes:subtitle", :as => :itunes_subtitle
|
24
|
+
element :"itunes:image", :value => :href, :as => :itunes_image
|
24
25
|
# If summary is not present, use the description tag
|
25
26
|
element :"itunes:summary", :as => :itunes_summary
|
26
27
|
element :enclosure, :value => :length, :as => :enclosure_length
|
data/lib/feedzirra/parser/rss.rb
CHANGED
data/lib/feedzirra/version.rb
CHANGED
data/spec/feedzirra/feed_spec.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper'
|
2
2
|
|
3
|
+
class FailParser
|
4
|
+
def self.parse(_, on_failure)
|
5
|
+
on_failure.call
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
3
9
|
describe Feedzirra::Feed do
|
4
10
|
|
5
11
|
describe "#add_common_feed_element" do
|
@@ -247,7 +253,7 @@ describe Feedzirra::Feed do
|
|
247
253
|
@cmock = double('cmock', :header_str => '', :body_str => @paul_feed[:xml] )
|
248
254
|
@multi = double('curl_multi', :add => true, :perform => true)
|
249
255
|
@curl_easy = double('curl_easy')
|
250
|
-
@curl = double('curl', :headers => {}, :follow_location= => true, :on_failure => true)
|
256
|
+
@curl = double('curl', :headers => {}, :follow_location= => true, :on_failure => true, :on_complete => true)
|
251
257
|
@curl.stub(:on_success).and_yield(@cmock)
|
252
258
|
|
253
259
|
Curl::Multi.stub(:new).and_return(@multi)
|
@@ -295,10 +301,10 @@ describe Feedzirra::Feed do
|
|
295
301
|
paul_response = double('paul_response', :header_str => '', :body_str => @paul_feed[:xml] )
|
296
302
|
trotter_response = double('trotter_response', :header_str => '', :body_str => @trotter_feed[:xml] )
|
297
303
|
|
298
|
-
paul_curl = double('paul_curl', :headers => {}, :follow_location= => true, :on_failure => true)
|
304
|
+
paul_curl = double('paul_curl', :headers => {}, :follow_location= => true, :on_failure => true, :on_complete => true)
|
299
305
|
paul_curl.stub(:on_success).and_yield(paul_response)
|
300
306
|
|
301
|
-
trotter_curl = double('trotter_curl', :headers => {}, :follow_location= => true, :on_failure => true)
|
307
|
+
trotter_curl = double('trotter_curl', :headers => {}, :follow_location= => true, :on_failure => true, :on_complete => true)
|
302
308
|
trotter_curl.stub(:on_success).and_yield(trotter_response)
|
303
309
|
|
304
310
|
Curl::Easy.should_receive(:new).with(@paul_feed[:url]).ordered.and_yield(paul_curl)
|
@@ -425,10 +431,44 @@ describe Feedzirra::Feed do
|
|
425
431
|
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, { :on_success => success })
|
426
432
|
@easy_curl.on_success.call(@easy_curl)
|
427
433
|
end
|
434
|
+
|
435
|
+
describe 'when the parser raises an exception' do
|
436
|
+
it 'invokes the on_failure callback' do
|
437
|
+
failure = lambda { |url, feed| }
|
438
|
+
failure.should_receive(:call).with(@paul_feed[:url], 0, nil, nil)
|
439
|
+
|
440
|
+
Feedzirra::Parser::AtomFeedBurner.should_receive(:parse).and_raise Exception
|
441
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, { on_failure: failure })
|
442
|
+
|
443
|
+
@easy_curl.on_success.call(@easy_curl)
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
describe 'when the parser invokes its on_failure callback' do
|
448
|
+
before(:each) do
|
449
|
+
Feedzirra::Feed.stub(:determine_feed_parser_for_xml).and_return FailParser
|
450
|
+
end
|
451
|
+
|
452
|
+
it 'invokes the on_failure callback' do
|
453
|
+
failure = lambda { |url, feed| }
|
454
|
+
failure.should_receive(:call).with(@paul_feed[:url], 0, nil, nil)
|
455
|
+
|
456
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, { on_failure: failure })
|
457
|
+
@easy_curl.on_success.call(@easy_curl)
|
458
|
+
end
|
459
|
+
end
|
428
460
|
end
|
429
461
|
|
430
462
|
describe 'when no compatible xml parser class is found' do
|
431
|
-
it '
|
463
|
+
it 'invokes the on_failure callback' do
|
464
|
+
failure = lambda { |url, feed| }
|
465
|
+
failure.should_receive(:call).with(@paul_feed[:url], 0, nil, nil)
|
466
|
+
|
467
|
+
Feedzirra::Feed.should_receive(:determine_feed_parser_for_xml).and_return nil
|
468
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, { on_failure: failure })
|
469
|
+
|
470
|
+
@easy_curl.on_success.call(@easy_curl)
|
471
|
+
end
|
432
472
|
end
|
433
473
|
end
|
434
474
|
|
@@ -473,7 +513,7 @@ describe Feedzirra::Feed do
|
|
473
513
|
complete = lambda { |url| }
|
474
514
|
complete.should_receive(:call).with(@paul_feed[:url], 404, @headers, @body)
|
475
515
|
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, { :on_failure => complete })
|
476
|
-
@easy_curl.
|
516
|
+
@easy_curl.on_missing.call(@easy_curl)
|
477
517
|
end
|
478
518
|
|
479
519
|
it 'should return the http code in the responses' do
|
@@ -543,8 +583,6 @@ describe Feedzirra::Feed do
|
|
543
583
|
Feedzirra::Feed.stub(:last_modified_from_header).and_return('Wed, 28 Jan 2009 04:10:32 GMT')
|
544
584
|
end
|
545
585
|
|
546
|
-
it 'should process the next feed in the queue'
|
547
|
-
|
548
586
|
it 'should parse the updated feed' do
|
549
587
|
Feedzirra::Parser::AtomFeedBurner.should_receive(:parse).and_return(@new_feed)
|
550
588
|
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
|
@@ -591,6 +629,20 @@ describe Feedzirra::Feed do
|
|
591
629
|
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
|
592
630
|
@easy_curl.on_success.call(@easy_curl)
|
593
631
|
end
|
632
|
+
|
633
|
+
describe 'when the parser invokes its on_failure callback' do
|
634
|
+
before(:each) do
|
635
|
+
Feedzirra::Feed.stub(:determine_feed_parser_for_xml).and_return FailParser
|
636
|
+
end
|
637
|
+
|
638
|
+
it 'invokes the on_failure callback' do
|
639
|
+
failure = lambda { |feed| }
|
640
|
+
failure.should_receive(:call)
|
641
|
+
|
642
|
+
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, { on_failure: failure })
|
643
|
+
@easy_curl.on_success.call(@easy_curl)
|
644
|
+
end
|
645
|
+
end
|
594
646
|
end
|
595
647
|
|
596
648
|
describe 'on failure' do
|
@@ -608,7 +660,7 @@ describe Feedzirra::Feed do
|
|
608
660
|
success.should_receive(:call).with(@feed)
|
609
661
|
@easy_curl.should_receive(:response_code).and_return(304)
|
610
662
|
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, { :on_success => success })
|
611
|
-
@easy_curl.
|
663
|
+
@easy_curl.on_redirect.call(@easy_curl)
|
612
664
|
end
|
613
665
|
|
614
666
|
it 'should return the http code in the responses' do
|
@@ -40,6 +40,15 @@ describe Feedzirra::Parser::AtomFeedBurner do
|
|
40
40
|
@feed.feed_url.should == "http://feeds.feedburner.com/PaulDixExplainsNothing"
|
41
41
|
end
|
42
42
|
|
43
|
+
it "should parse no hub urls" do
|
44
|
+
@feed.hubs.count.should == 0
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should parse hub urls" do
|
48
|
+
feed_with_hub = Feedzirra::Parser::AtomFeedBurner.parse(load_sample("TypePadNews.xml"))
|
49
|
+
feed_with_hub.hubs.count.should == 1
|
50
|
+
end
|
51
|
+
|
43
52
|
it "should parse entries" do
|
44
53
|
@feed.entries.size.should == 5
|
45
54
|
end
|
@@ -44,6 +44,16 @@ describe Feedzirra::Parser::Atom do
|
|
44
44
|
@feed.feed_url.should == "http://aws.typepad.com/aws/atom.xml"
|
45
45
|
end
|
46
46
|
|
47
|
+
it "should parse no hub urls" do
|
48
|
+
@feed.hubs.count.should == 0
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should parse the hub urls" do
|
52
|
+
feed_with_hub = Feedzirra::Parser::Atom.parse(load_sample("SamRuby.xml"))
|
53
|
+
feed_with_hub.hubs.count.should == 1
|
54
|
+
feed_with_hub.hubs.first.should == "http://pubsubhubbub.appspot.com/"
|
55
|
+
end
|
56
|
+
|
47
57
|
it "should parse entries" do
|
48
58
|
@feed.entries.size.should == 10
|
49
59
|
end
|
@@ -45,4 +45,7 @@ describe Feedzirra::Parser::ITunesRSSItem do
|
|
45
45
|
@item.itunes_keywords.should == "salt, pepper, shaker, exciting"
|
46
46
|
end
|
47
47
|
|
48
|
+
it "should parse the image" do
|
49
|
+
@item.itunes_image.should == "http://example.com/podcasts/everything/AllAboutEverything.jpg"
|
50
|
+
end
|
48
51
|
end
|
@@ -40,6 +40,11 @@ describe Feedzirra::Parser::RSSFeedBurner do
|
|
40
40
|
@feed.url.should == "http://techcrunch.com"
|
41
41
|
end
|
42
42
|
|
43
|
+
it "should parse the hub urls" do
|
44
|
+
@feed.hubs.count.should == 2
|
45
|
+
@feed.hubs.first.should == "http://pubsubhubbub.appspot.com/"
|
46
|
+
end
|
47
|
+
|
43
48
|
it "should provide an accessor for the feed_url" do
|
44
49
|
@feed.respond_to?(:feed_url).should == true
|
45
50
|
@feed.respond_to?(:feed_url=).should == true
|
@@ -37,6 +37,10 @@ describe Feedzirra::Parser::RSS do
|
|
37
37
|
@feed.url.should == "http://tenderlovemaking.com"
|
38
38
|
end
|
39
39
|
|
40
|
+
it "should not parse hub urls" do
|
41
|
+
@feed.hubs.should == nil
|
42
|
+
end
|
43
|
+
|
40
44
|
it "should provide an accessor for the feed_url" do
|
41
45
|
@feed.respond_to?(:feed_url).should == true
|
42
46
|
@feed.respond_to?(:feed_url=).should == true
|
@@ -0,0 +1,582 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<feed xmlns="http://www.w3.org/2005/Atom"
|
3
|
+
xmlns:thr="http://purl.org/syndication/thread/1.0">
|
4
|
+
<link rel="self" href="http://intertwingly.net/blog/index.atom"/>
|
5
|
+
<link rel="hub" href="http://pubsubhubbub.appspot.com/"/>
|
6
|
+
<id>http://intertwingly.net/blog/index.atom</id>
|
7
|
+
<icon>../favicon.ico</icon>
|
8
|
+
|
9
|
+
<title>Sam Ruby</title>
|
10
|
+
<subtitle>It’s just data</subtitle>
|
11
|
+
<author>
|
12
|
+
<name>Sam Ruby</name>
|
13
|
+
<email>rubys@intertwingly.net</email>
|
14
|
+
<uri>/blog/</uri>
|
15
|
+
</author>
|
16
|
+
<updated>2013-02-23T18:33:07-08:00</updated>
|
17
|
+
<link href="/blog/"/>
|
18
|
+
<link rel="license" href="http://creativecommons.org/licenses/BSD/"/>
|
19
|
+
|
20
|
+
<entry>
|
21
|
+
<id>tag:intertwingly.net,2004:3308</id>
|
22
|
+
<link href="/blog/2013/01/30/Plex"/>
|
23
|
+
<link rel="replies" href="3308.atom" thr:count="2" thr:updated="2013-01-30T13:58:47-08:00"/>
|
24
|
+
<title>Plex</title>
|
25
|
+
<summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p><a href="http://www.hanselman.com/blog/PlexIsTheMediaCenterSoftwareEcosystemIveBeenWaitingFor.aspx">Scott Hanselman</a>: <em>Plex is the media center software ecosystem I’ve been waiting for</em></p>
|
26
|
+
<p>Unhappy with <a href="http://intertwingly.net/blog/2012/12/05/Time-Warner-Cables-idea-of-service">Time Warner Cable</a>, I’ve been exploring <a href="http://movies.netflix.com/WiHome">netflix</a>, <a href="http://www.dish.com/">dish</a>, <a href="http://www.slingbox.com/">sling</a>, <a href="http://www.roku.com/">roku</a>, <a href="http://www.samsung.com/smarttv">samsung</a>, <a href="http://fmpeg.org/">ffmpeg</a>, <a href="http://handbrake.fr/">handbrake</a>, and <a href="http://cclive.sourceforge.net/">cclive</a>. Next up, some form of <a href="http://www.linuxtv.org/wiki/index.php/ATSC_USB_Devices">video capture device</a>... at the moment I’m leaning towards <a href="http://www.tigerdirect.com/applications/SearchTools/item-details.asp?EdpNo=4146195&CatId=4546">Hauppauge</a>.</p>
|
27
|
+
<p>I’m not quite prepared to declare Plex as the centerpiece of my home media center, but it certainly has become a key component.</p></div></summary>
|
28
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
29
|
+
<defs>
|
30
|
+
<radialGradient id="plex1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
|
31
|
+
<stop offset="0%" stop-color="#f8ce22" stop-opacity="0.9" ></stop>
|
32
|
+
<stop offset="100%" stop-color="rgb(0,0,0)" stop-opacity="0" ></stop>
|
33
|
+
</radialGradient>
|
34
|
+
</defs>
|
35
|
+
<rect width="100" height="100" rx="10"></rect>
|
36
|
+
<ellipse cx="54" cy="50" rx="38" ry="60" fill="url(#plex1)" ></ellipse>
|
37
|
+
<path d="M28,7h31l28,43l-28,43h-31l28-43Z" fill="#ff8e00" stroke="#f8ce22" stroke-width="2"></path>
|
38
|
+
</svg>
|
39
|
+
<p><a href="http://www.hanselman.com/blog/PlexIsTheMediaCenterSoftwareEcosystemIveBeenWaitingFor.aspx"><cite>Scott Hanselman</cite></a>: <em>Plex is the media center software ecosystem I’ve been waiting for</em></p>
|
40
|
+
<p>Unhappy with <a href="http://intertwingly.net/blog/2012/12/05/Time-Warner-Cables-idea-of-service">Time Warner Cable</a>, I’ve been exploring <a href="http://movies.netflix.com/WiHome">netflix</a>, <a href="http://www.dish.com/">dish</a>, <a href="http://www.slingbox.com/">sling</a>, <a href="http://www.roku.com/">roku</a>, <a href="http://www.samsung.com/smarttv">samsung</a>, <a href="http://fmpeg.org/">ffmpeg</a>, <a href="http://handbrake.fr/">handbrake</a>, and <a href="http://cclive.sourceforge.net/">cclive</a>. Next up, some form of <a href="http://www.linuxtv.org/wiki/index.php/ATSC_USB_Devices">video capture device</a>... at the moment I’m leaning towards <a href="http://www.tigerdirect.com/applications/SearchTools/item-details.asp?EdpNo=4146195&CatId=4546">Hauppauge</a>.</p>
|
41
|
+
<p>I’m not quite prepared to declare Plex as the centerpiece of my home media center, but it certainly has become a key component.</p>
|
42
|
+
<p>Unlike Scott, I didn’t go with a dedicated NAS box. Installation of a <a href="https://apps.ubuntu.com/cat/applications/precise/plexmediaserver/">Plex Media Server</a> on Ubuntu is a snap (though a <a href="https://bugs.launchpad.net/ubuntu/+source/software-center/+bug/647212">workaround</a> is needed if you happen to make use of an <a href="http://linuxexpresso.wordpress.com/2011/02/13/howto-apt-cacher-ng-on-ubuntu/">apt cacher</a>).</p>
|
43
|
+
<p>Obligatory <a href="http://i.imgur.com/VCTCAS7.png">Cable Guy</a> reference.</p></div></content>
|
44
|
+
<updated>2013-01-30T10:12:03-08:00</updated>
|
45
|
+
</entry>
|
46
|
+
|
47
|
+
<entry>
|
48
|
+
<id>tag:intertwingly.net,2004:3307</id>
|
49
|
+
<link href="/blog/2012/12/22/RESTful-Web-APIs"/>
|
50
|
+
<link rel="replies" href="3307.atom" thr:count="0"/>
|
51
|
+
<title>RESTful Web APIs</title>
|
52
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
53
|
+
<path d="M10,90.1v-2h80V90.1zM10,70.1v-2h80V70.1zM10,50.1v-2h80V50.1zM10,30.1v-2h80V30.1zM10,10.1v-2h80V10.1z"></path>
|
54
|
+
<path d="M44.4,20.8c1.5,1.6,13,15.7,13,15.7s-6.4,6.1-6.4,12.5c0,7.5,8.6,14.3,8.6,14.3l-0.9,1.1c-3.3-1.9-8.9-2.1-11.4,0.8c-3.1,3.6,3.9,9.1,3.9,9.1l-0.8,1.1c-2.4-1.8-12.6-11.4-8.3-16.1c2.6-2.9,5.8-3.8,10.3-1.4l-12.1-12.5c7-8.6,8.2-11.1,8.2-13.4c0-4.8-3.4-8.2-5.1-10.4c-0.6-0.9-1.7-1.6-1-2.2C43.1,18.9,43.5,19.7,44.4,20.8z" fill="#F33"></path>
|
55
|
+
</svg>
|
56
|
+
<p><a href="http://amundsen.com/blog/archives/1139"><cite>Mike Amundsen</cite></a>: <em>I have the even greater privilege of working with Leonard and Sam on a new book - “RESTful Web APIs”. It’s scheduled for completion by the end of Q1 2013 and should be available soon after.</em></p>
|
57
|
+
<p>While I’m formally on this project, I’m not planning on doing any writing beyond possibly an introduction. As Mike put it, this book isn’t merely a 2nd edition, but rather <em>more of a “follow-up” seven years on.</em> I’m very much looking forward to seeing where Mike can help Leonard take this work.</p></div></content>
|
58
|
+
<updated>2012-12-22T05:47:48-08:00</updated>
|
59
|
+
</entry>
|
60
|
+
|
61
|
+
<entry>
|
62
|
+
<id>tag:intertwingly.net,2004:3306</id>
|
63
|
+
<link href="/blog/2012/12/19/Feedvalidator-org-Hacked"/>
|
64
|
+
<link rel="replies" href="3306.atom" thr:count="5" thr:updated="2013-01-07T12:31:41-08:00"/>
|
65
|
+
<title>Feedvalidator.org Hacked?</title>
|
66
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" stroke="#000" width="100" height="100" viewBox="0 0 100 100">
|
67
|
+
<path d="M8,80s-5,8,5,9l78,0s9,0,5-9l-40-71s-4-6-8,0z" stroke-width="2" fill="#fff"></path>
|
68
|
+
<path d="M52,10 L10,85 L93,85z" stroke-width="2" stroke-linejoin="round" fill="#fc0"></path>
|
69
|
+
<path d="M52,32l0,26" stroke-width="9" stroke-linecap="round"></path>
|
70
|
+
<circle r="6" cx="52" cy="73"></circle>
|
71
|
+
</svg>
|
72
|
+
<p>Google has reported <a href="http://feedvalidator.org/">feedvalidator.org</a> as being <a href="http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=Firefox&hl=en-US&site=http://feedvalidator.org/">hacked</a>, and people are tweeting and emailing me.</p>
|
73
|
+
<p>I’ve looked at the markup being returned and it looks clean to me. The <a href="https://raw.github.com/rubys/feedvalidator/master/.htaccess">.htaccess</a> file looks fine. A <code>git status</code> command shows that none of the files on the server have been modified.</p>
|
74
|
+
<p>Can somebody identify what is causing Google to be concerned?</p></div></content>
|
75
|
+
<updated>2012-12-19T03:33:01-08:00</updated>
|
76
|
+
</entry>
|
77
|
+
|
78
|
+
<entry>
|
79
|
+
<id>tag:intertwingly.net,2004:3305</id>
|
80
|
+
<link href="/blog/2012/12/13/Changing-the-TAG"/>
|
81
|
+
<link rel="replies" href="3305.atom" thr:count="4" thr:updated="2012-12-14T09:16:37-08:00"/>
|
82
|
+
<title>Changing the TAG</title>
|
83
|
+
<summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p><a href="https://blog.linss.com/2012/12/12/changing-the-tag-an-unexpected-opportunity/">Peter Linss</a>: <em>I really want to see the TAG be more involved with the rest of the working groups at the W3C</em></p>
|
84
|
+
<p>I’ll come out and say it. I’m a skeptic. I’ll note that the three out of the four of the “TAG reformists” statements do NOT list getting involved with the rest of the working groups at the W3C as a goal. What am I missing?</p></div></summary>
|
85
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns='http://www.w3.org/2000/svg' width="131" height="76" viewBox="0 0 131 76">
|
86
|
+
<path d="M36,5l12,41l12-41h33v4l-13,21c30,10,2,69-21,28l7-2c15,27,33,-22,3,-19v-4l12-20h-15l-17,59h-1l-13-42l-12,42h-1l-20-67h9l12,41l8-28l-4-13h9" fill='#005A9C'></path>
|
87
|
+
<path d="M94,53c15,32,30,14,35,7l-1-7c-16,26-32,3-34,0M122,16c-10-21-34,0-21,30c-5-30 16,-38 23,-21l5-10l-2-9"></path>
|
88
|
+
</svg>
|
89
|
+
<p><a href="https://blog.linss.com/2012/12/12/changing-the-tag-an-unexpected-opportunity/"><cite>Peter Linss</cite></a>: <em>I really want to see the TAG be more involved with the rest of the working groups at the W3C</em></p>
|
90
|
+
<p>I’ll come out and say it. I’m a skeptic. Each of the <a href="http://www.w3.org/2012/12/03-tag-nominations">nominees</a> are good people.</p>
|
91
|
+
<p>I’ll note that the three out of the four of the “TAG reformists” statements do NOT list getting involved with the rest of the working groups at the W3C as a goal: <a href="http://infrequently.org/2012/12/reforming-the-w3c-tag/">Alex Russell</a>, <a href="http://marcosc.com/2012/12/w3c-tag-elections/">Marcos Cáceres</a>, <a href="http://annevankesteren.nl/2012/12/w3c-tag">Anne van Kesteren</a>, and <a href="http://yehudakatz.com/2012/12/07/im-running-to-reform-the-w3cs-tag/">Yehuda Katz</a>.</p>
|
92
|
+
<p>And outside of Anne, none of them have significantly been involved in the <a href="http://www.w3.org/html/wg/">HTML WG</a>. As to Anne, I don’t see being on the TAG as resolving his <a href="http://annevankesteren.nl/2012/11/copyright">concern</a>.</p>
|
93
|
+
<p>What am I missing?</p></div></content>
|
94
|
+
<updated>2012-12-13T07:54:49-08:00</updated>
|
95
|
+
</entry>
|
96
|
+
|
97
|
+
<entry>
|
98
|
+
<id>tag:intertwingly.net,2004:3304</id>
|
99
|
+
<link href="/blog/2012/12/05/Time-Warner-Cables-idea-of-service"/>
|
100
|
+
<link rel="replies" href="3304.atom" thr:count="15" thr:updated="2012-12-20T14:47:52-08:00"/>
|
101
|
+
<title>Time Warner Cable’s idea of “service”</title>
|
102
|
+
<summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>It started with two notifications we received via postal mail. First Time Warner was going to start charging us rent for an outdated cable modem. Second they were going to drop a number of cable channels, but if I acted now, I could request a digital adapter which would allow me to watch these channels on exactly one TV.</p>
|
103
|
+
<p>This process has turned a fairly complacent Time Warner customer into one that is actively seeking alternatives. In looking around, I see plenty of promo offers of more service than I have (basic cable and basic internet) for considerably less than I am currently paying. I am OK with waiting an hour or more for an answer, but I am not OK with having to be on hold for that entire time. And I’m definitely not OK with renting a separate box per device simply to get access.</p>
|
104
|
+
<p>This process has turned a fairly complacent Time Warner customer into one that is actively seeking alternatives. So I am beginning my research: starting with looking for alternatives to cable TV. What I want is a single plan that allows me to watch whatever I want wherever I want. I am OK with upgrading my devices as long as we are talking about a purchase not a lease.</p>
|
105
|
+
<p>Any pointers people might leave in comments would be appreciated.</p></div></summary>
|
106
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns='http://www.w3.org/2000/svg' width="108" height="93" viewBox="0 0 108 93">
|
107
|
+
<path d='M17,27c-3,3-5,6-10,11c-2,1-3,1-5,0c-4-4-2-7,8-17c11-11,24-19,36-20c13-2,30,1,43,11c7,6,15,14,19,21c-4,7-9,13-14,17c-5,5-11,8-16,10c-13,4-28,3-36-10c-2-4-2-8,0-12c2-5,8-9,13-9c4,0,9,2,11,7c1,2,1,6-1,8c-1,1-6,2-7-2c0-2-0-4-2-4c-4,0-7,3-6,8c1,3,4,6,11,7c3,0,7-1,11-6c3-4,3-11,0-15c-4-7-10-10-18-10c-9,0-17,5-21,14c-3,7-5,17,0,28c4,8,11,13,17,16c5,3,16,4,17,8c0,3-2,5-4,5c-17-3-31-11-37-25c-7-13-6-30,2-41c5-7,13-12,20-13c19-5,38,9,35,28c-1,3-2,6-4,8c0,1,0,1-1,1l2-1c7-4,13-10,17-17c-10-18-32-27-49-24c-14,2-23,10-31,18' fill='#0056a2'></path>
|
108
|
+
</svg>
|
109
|
+
<p>It started with two notifications we received via postal mail. First Time Warner was going to start charging us rent for an outdated cable modem. Second they were going to drop a number of cable channels, but if I acted now, I could request a digital adapter which would allow me to watch these channels on exactly one TV.</p>
|
110
|
+
<p>So I did some research and purchased a DOCSIS 3.0 compatible modem that can do IP V6, figuring that would future proof me for a while, and connected it up. I actually managed to get an IP address assigned, but everything I tried after that was redirected to a site saying that I needed to be “provisioned” and to call a number. Upon calling that number, I got connected with a person whose sole purpose seemed to be to upsell me to a higher plan. After I politely but firmly refused, I was transferred and placed on hold for about 30 minutes. The woman that tried to help me get connected couldn’t get it to work so she transferred me to level 3. Another 5 minutes later, a gentleman picked up and also had trouble. It took him about 30 minutes to get it to work — apparently they didn’t give him instructions on how to deal with DOCSIS 3.0 modems despite my picking one of the options on the list they provided to me. But he was pleasant and apologetic throughout, and eventually did manage to get it working.</p>
|
111
|
+
<p>The next day I drove 15 minutes to stand in a 20 minute line to do what amounted to a 60 second transaction: here’s a box, here’s a receipt. Thank you and goodbye.</p>
|
112
|
+
<p>As to the dropped channels... I dutifully filled out an online form requesting a digital adapter, and got first a confirmation and subsequently a notification that the order was “complete”... where the latter merely indicated that something would be shipping in 3-5 business days, giving me a confirmation number. That was 18 November.</p>
|
113
|
+
<p>The box never showed up.</p>
|
114
|
+
<p>Yesterday, the channels went dark, and I went online. After using Chrome to override my User Agent so that I could make use of their chat system, I waited over 20 minutes for a representative. After checking, he said that there was nothing he could do for me, and gave me a number I could call. I called that number and was told that the wait time would be more than 30 minutes. As the chat window was still open, I asked if there was anything else I could do. He said call back late in the evening when the wait times would be less. I was not happy and closed the chat window. I was then presented with a survey, in which I responded that the person was not able to solve my problem and that I was not happy.</p>
|
115
|
+
<p>I <a href="https://twitter.com/samruby">tweeted to TWCableHelp</a> and got <strike>no response</strike> a DM five hours later asking me for my phone number. Before I went to bed, I sent an email. When I woke up I got a response indicating that the email had been forwarded to “our regional contacts”, who would be contacting me. They have not.</p>
|
116
|
+
<p>I called again, and was told that there would be a 20 to 25 minute wait time. It was closer to 30. I was told that another digital adapter had been placed on order. I asked for a confirmation number, and was told that she didn’t have one. I asked for an email, and she said that one would be sent within 48 hours. I was given a case number. And that was all she could do for me.</p>
|
117
|
+
<p>At this point, I have nobody I can contact, no tracking number, and no confidence that this time will turn out any different. And a number of black channels.</p>
|
118
|
+
<p>This process has turned a fairly complacent Time Warner customer into one that is actively seeking alternatives. In looking around, I see plenty of promo offers of more service than I have (basic cable and basic internet) for considerably less than I am currently paying. I am OK with waiting an hour or more for an answer, but I am not OK with having to be on hold for that entire time. And I’m definitely not OK with renting a separate box per device simply to get access.</p>
|
119
|
+
<p>So I am beginning my research: starting with looking for alternatives to cable TV. What I want is a single plan that allows me to watch whatever I want wherever I want. I am OK with upgrading my devices as long as we are talking about a purchase not a lease.</p>
|
120
|
+
<p>Any pointers people might leave in comments would be appreciated.</p></div></content>
|
121
|
+
<updated>2012-12-05T08:54:58-08:00</updated>
|
122
|
+
</entry>
|
123
|
+
|
124
|
+
<entry>
|
125
|
+
<id>tag:intertwingly.net,2004:3303</id>
|
126
|
+
<link href="/blog/2012/11/09/In-defence-of-Polyglot"/>
|
127
|
+
<link rel="replies" href="3303.atom" thr:count="21" thr:updated="2012-12-10T20:19:45-08:00"/>
|
128
|
+
<title>In defence of Polyglot</title>
|
129
|
+
<summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I see that <a href="http://hsivonen.iki.fi/author/">Henri Sivonen</a> is once again <a href="https://twitter.com/hsivonen/status/266535784050458624">being snarky</a> without <a href="https://twitter.com/hsivonen/status/266565956585795585">backing his position</a>. I’ll state my position, namely that something like the <a href="http://dev.w3.org/html5/html-xhtml-author-guide/html-xhtml-authoring-guide.html">polyglot specification</a> needs to exist, and why I believe that to be the case.</p>
|
130
|
+
<p>It makes sense for authors who may produce a handful of pages to be processed by an uncountable number of imperfect tools to agree on restrictions that may go well behond the <a href="http://lists.w3.org/Archives/Public/public-html/2012Nov/0006.html">minimal logical consequences from normative text elsewhere</a> if those restrictions increase the odds of the document produced being correctly processed.</p>
|
131
|
+
<p>Such restrictions are not a bad thing. In fact, such restrictions are very much a good thing.</p></div></summary>
|
132
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns='http://www.w3.org/2000/svg' width="86" height="116" viewBox="0 0 86 116">
|
133
|
+
<path d='M70,70c0,20-15,37-34,37c-18,0-33-17-32-37c0-21,14-54,33-55c18,0,34,34,33,55' fill='#0C0'></path>
|
134
|
+
<path d='M27,48a1,2,170,1,1-12,0a1,2,170,1,1,12,0M30,48a1,2,10,1,1,12,1a1,2,10,1,1-12-1M46,66l-5,4c-2,2-5,3-9,4c-4,1-8,1-12,0h-1c0,2,1,3,2,5c-1,0,4,5,7,5c4,0,6,0,10-1c2,0,5,1,7-1c1-1,1-8,1-10v-6' fill='#fff' stroke="#0A0"></path>
|
135
|
+
<path d='M30,25l13,4l-1,3l-12-5zM24,25l-12,4l2,3l11-5zM26,52a2,3,170,1,1-7,0a2,3,170,1,1,7,0M37,52a2,3,10,1,1-7,0a2,3,10,1,1,7,0'></path>
|
136
|
+
<path d='M34,48a1,1,0,1,1-1,0M23,48a1,1,0,1,1-1,0' fill='#999'></path>
|
137
|
+
<path stroke='#000' d='M31,20c-1,0-2-2-3-3c-1-1,2-3,3-3c3-6-2-9-7-6' fill='none'></path>
|
138
|
+
</svg>
|
139
|
+
<p>I see that <a href="http://hsivonen.iki.fi/author/">Henri Sivonen</a> is once again <a href="https://twitter.com/hsivonen/status/266535784050458624">being snarky</a> without <a href="https://twitter.com/hsivonen/status/266565956585795585">backing his position</a>. I’ll state my position, namely that something like the <a href="http://dev.w3.org/html5/html-xhtml-author-guide/html-xhtml-authoring-guide.html">polyglot specification</a> needs to exist, and why I believe that to be the case.</p>
|
140
|
+
<p>The short version is that I have developed a <a href="https://github.com/rubys/wunderbar">library</a> that I believe to be polyglot compatible, and by that I mean that if there are differences between what this library does and what polyglot specifies that one or both should be corrected to bring them into compliance.</p>
|
141
|
+
<p>I didn’t write this library simply because I am loonie, but very much to solve a real problem.</p>
|
142
|
+
<p>The problem is that HTML source files <a href="http://svn.whatwg.org/webapps/complete.html">exist</a> that contain artifacts like consecutive <td> elements; people process such documents using tools such as <a href="http://anolis.gsnedders.com/">anolis</a>; and such libraries often depend on — for good reasons — libraries such as <a href="http://www.xmlsoft.org/">libxml2</a> which do an imperfect job of parsing HTML correctly. The output produced by such tools when combined with such libraries are incorrect.</p>
|
143
|
+
<p>Note that I stop well short of recommending that others serve their content as <a href="http://www.w3.org/TR/xhtml-media-types/">application/xhtml+xml</a>. Or that tools should <a href="http://docs.activestate.com/activepython/3.1/diveintopython3/html/xml.html#xml-custom-parser">halt and catch fire</a> if they are presented with incorrect input. In fact, I would even be willing to say that in general people <a href="http://www.ietf.org/rfc/rfc2119.txt">SHOULD NOT</a> do either of these things.</p>
|
144
|
+
<p>Now that I have provided instance proofs of the problem and the solution, I’ll proceed with the longer answer. I will start by noting that <a href="http://en.wikipedia.org/wiki/Robustness_principle">Postel’s law</a> has two halves, and while the HTML WG has focused heavily on the second half of that law, the story should not stop there.</p>
|
145
|
+
<p>To get HTML right involves a number of details that people often get wrong. Details such as encoding and escaping. Details that have consequences such as <a href="http://en.wikipedia.org/wiki/Cross-site_scripting">XSS vulnerabilities</a> when the scenario involves integrating content from untrusted sources. Scenarios which include comments on blogs or feed aggregators. Scenarios that lead people to write sanitizers and employ the use of imperfect HTML parsers.</p>
|
146
|
+
<p>It is well and good that Henri maintains — on a best effort basis only — a <a href="http://about.validator.nu/htmlparser/">superior parser</a> for exactly one programming language. <a href="https://twitter.com/hsivonen/status/263696331141431296">Advertising</a> this library more won’t solve the problem for people who code in languages such as C#, Perl, PHP, Python, or Ruby. Fundamentally, a <a href="http://www.xml.com/pub/a/2004/07/21/dive.html">tools will save us</a> response is not an adequate response when the problem is imperfect tools.</p>
|
147
|
+
<p>This problem that needs to be addressed is very much the flip side, and complement to, the parsing problem that HTML5 has competently solved. Given a handful of browser vendors and an uncountable number of imperfect documents, it very much make sense for the browser vendors to get together and agree on how to handle error recovery. By the very same token, it makes sense for authors who may produce a handful of pages to be processed by an uncountable number of imperfect tools to agree on restrictions that may go well beyond the <a href="http://lists.w3.org/Archives/Public/public-html/2012Nov/0006.html">minimal logical consequences from normative text elsewhere</a> if those restrictions increase the odds of the document produced being correctly processed.</p>
|
148
|
+
<p>Yes, it would be great if this weren’t necessary and all tools were perfect. Similarly, it would be great if browser vendors didn’t have to agree on error recovery as this makes the creation of streaming parsers more difficult. The point is that while both would be great, neither will happen, at least not any time soon.</p>
|
149
|
+
<p>These restrictions may indeed go beyond “always explicitly close all elements” and “always quote all attribute values”. It may include such statements as “always use UTF-8”.</p>
|
150
|
+
<p>Such restrictions are not a bad thing. In fact, such restrictions are very much a good thing.</p></div></content>
|
151
|
+
<updated>2012-11-09T03:58:21-08:00</updated>
|
152
|
+
</entry>
|
153
|
+
|
154
|
+
<entry>
|
155
|
+
<id>tag:intertwingly.net,2004:3302</id>
|
156
|
+
<link href="/blog/2012/10/09/Web-Platform-Docs"/>
|
157
|
+
<link rel="replies" href="3302.atom" thr:count="0"/>
|
158
|
+
<title>Web Platform Docs</title>
|
159
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns='http://www.w3.org/2000/svg' width="100" height="100" viewBox="0 0 100 100">
|
160
|
+
<path d='M73,55v-40c0-8,4-13,12-13c7,0,13,4,13,12v68c-7-10-25-27-25-27M85,10c-3,0-5,2-5,5c0,3,2,5,5,5c3,0,5-2,5-6c0-2-2-4-5-4' fill='#31B0BC'></path>
|
161
|
+
<path d='M2,77v-61c0-9,6-14,14-14c7,0,12,5,11,14v40l-25,24M15,9c-3,0-5,2-5,5c0,3,2,5,5,5c3,0,5-2,5-6c0-2-2-4-5-4' fill='#F19620'></path>
|
162
|
+
<path d='M4,77l23-21v35c-4,6-10,10-17,7c-8-3-11-16-6-21M15,91c3,0,5-2,5-5c0-3-2-5-5-5c-4,0-6,2-6,5c0,3,3,5,6,5' fill='#CC2D28'></path>
|
163
|
+
<path d='M73,55c0,0,23,22,25,27c1,7-1,13-8,16c-7,3-13,0-17-6v-37M90,86c0-3-2-5-5-5c-3,0-5,2-5,5c0,3,2,5,5,5c3,0,5-2,5-5' fill='#273C7D'></path>
|
164
|
+
<path d='M73,92l-24-22v-2l14-22l10,9l0,37' fill='#654D97'></path>
|
165
|
+
<path d='M50,67l-12-22l-11,11v1v34l22-21' fill='#D24839'></path>
|
166
|
+
<path d='M49,70c-7-8-14-14-12-24c9-12,17-11,26,0c1,11-7,17-14,24M50,55c3,0,5-2,5-5c0-3-2-5-5-5c-4,0-6,2-6,5c0,3,3,5,6,5' fill='#59152B'></path>
|
167
|
+
</svg>
|
168
|
+
<p><a href="http://blog.webplatform.org/2012/10/one-small-step/"><cite>Doug Sheppers</cite></a>: <em><a href="http://docs.webplatform.org/">WebPlatform.org</a> will have accurate, up-to-date, comprehensive references and tutorials for every part of client-side development and design, with quirks and bugs revealed and explained. It will have in-depth indicators of browser support and interoperability, with links to tests for specific features. It will feature discussions and script libraries for cutting-edge features at various states of implementation or standardization, with the opportunity to give feedback into the process before the features are locked down. It will have features to let you experiment with and share code snippets, examples, and solutions. It will have an API to access the structured information for easy reuse. It will have resources for teachers to help them train their students with critical skills. It will have information you just can’t get anywhere else, and it will have it all in one place.</em></p>
|
169
|
+
<p><em>But it doesn’t. Not yet.</em></p></div></content>
|
170
|
+
<updated>2012-10-09T11:35:17-07:00</updated>
|
171
|
+
</entry>
|
172
|
+
|
173
|
+
<entry>
|
174
|
+
<id>tag:intertwingly.net,2004:3301</id>
|
175
|
+
<link href="/blog/2012/09/04/The-Flowing-Standard"/>
|
176
|
+
<link rel="replies" href="3301.atom" thr:count="1" thr:updated="2013-01-03T17:32:29-08:00"/>
|
177
|
+
<title>The Flowing Standard</title>
|
178
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns='http://www.w3.org/2000/svg' width="131" height="76" viewBox="0 0 131 76">
|
179
|
+
<path d="M36,5l12,41l12-41h33v4l-13,21c30,10,2,69-21,28l7-2c15,27,33,-22,3,-19v-4l12-20h-15l-17,59h-1l-13-42l-12,42h-1l-20-67h9l12,41l8-28l-4-13h9" fill='#005A9C'></path>
|
180
|
+
<path d="M94,53c15,32,30,14,35,7l-1-7c-16,26-32,3-34,0M122,16c-10-21-34,0-21,30c-5-30 16,-38 23,-21l5-10l-2-9"></path>
|
181
|
+
</svg>
|
182
|
+
<a href="http://www.w3.org/QA/2012/09/the_flowing_standard.html"><cite>Robin Berjon</cite></a>: <em>Looking at it in terms of rebounds, plot twists, nurtured healing and abandonment, love and betrayal, strife, toil, stunning victories, dispersions and last minute rallies the only thing that distinguishes HTML’s history from a charts-topping teenage fantasy saga seems to be the lack of vampires. And even then, were vampires around I’m not sure we’d notice them for all the action.</em></div></content>
|
183
|
+
<updated>2012-09-04T16:10:12-07:00</updated>
|
184
|
+
</entry>
|
185
|
+
|
186
|
+
<entry>
|
187
|
+
<id>tag:intertwingly.net,2004:3300</id>
|
188
|
+
<link href="/blog/2012/08/25/Taming-the-wild-wild-web"/>
|
189
|
+
<link rel="replies" href="3300.atom" thr:count="3" thr:updated="2012-10-18T03:54:07-07:00"/>
|
190
|
+
<title>Taming the wild, wild web</title>
|
191
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns='http://www.w3.org/2000/svg' width="100" height="100" viewBox="0 0 100 100">
|
192
|
+
<path fill='#85B916' d='M50,82l-31-31l31-31l10,10l-20,21l10,10l31-31l-27-27c-2-2-6-2-8,0l-43,44c-2,2-2,6,0,8l43,43c2,2,6,2,8,0l43-43c2-2,2-6,0-8l-6-7z'></path>
|
193
|
+
</svg>
|
194
|
+
<a href="http://toc.oreilly.com/2012/08/portable-documents-for-the-open-web-part-3.html"><cite>Bill McCoy</cite></a>: <em>EPUB in effect takes the Wild, Wild Web and tames it. EPUB for example requires use of the XML serialization of HTML5 (XHTML5), rather than “Tag Soup” aka “Street” HTML. This means that EPUB content, unlike arbitrary web pages, can be reliably created and manipulated with XML tool chains. EPUB defined Reading System conformance more tightly than HTML5 defines for browser User Agents, pinning down things that are under-specified in the union of W3C standards.</em> [via <a href="https://twitter.com/pmuellr/status/238664881308565504"><cite>Patrick Mueller</cite></a>]</div></content>
|
195
|
+
<updated>2012-08-25T12:32:40-07:00</updated>
|
196
|
+
</entry>
|
197
|
+
|
198
|
+
<entry>
|
199
|
+
<id>tag:intertwingly.net,2004:3299</id>
|
200
|
+
<link href="/blog/2012/07/16/Inhibiting-Suspend"/>
|
201
|
+
<link rel="replies" href="3299.atom" thr:count="1" thr:updated="2012-07-17T08:34:14-07:00"/>
|
202
|
+
<title>Inhibiting Suspend</title>
|
203
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns='http://www.w3.org/2000/svg' width="109" height="92" viewBox="0 0 109 92">
|
204
|
+
<g style='fill:#FFFFFF;stroke:#3B80AE;stroke-width:3'>
|
205
|
+
<path d='M107,51c3,10-3,20-13,23l-60,15c-10,3-20-3-23-13l-9-36c-2-10,3-20,13-22l60-16c10-2,20,3,23,13z' style='stroke:#BABABA'></path>
|
206
|
+
<path d='M101,50c2,10-2,17-12,19l-53,14c-9,3-18-1-20-11l-8-30c-2-11,1-17,12-20l53-14c10-2,18,2,20,11z' style='fill:#3B80AE;stroke:none'></path>
|
207
|
+
<path d='M57,65l-27-26l48-5z' style='opacity:0.5;fill:none;stroke:#FFFFFF'></path>
|
208
|
+
<path d='M91,36c0,2-1,4-3,5l-15,4c-2,0-4-1-5-3l-3-11c0-2,1-4,3-5l15-4c2,0,4,1,5,3z'></path>
|
209
|
+
<path d='M46,42c0,3-1,5-3,6l-19,5c-3,0-5-1-6-4l-3-13c-1-3,0-5,3-6l19-5c2,0,5,1,5,4z'></path>
|
210
|
+
<path d='M66,67c0,1-1,3-2,3l-11,3c-1,0-2-1-3-2l-2-8c0-1,1-2,2-3l11-3c1,0,3,1,3,2z'></path>
|
211
|
+
</g>
|
212
|
+
</svg>
|
213
|
+
<p>The <a href="http://people.gnome.org/~mccann/gnome-session/docs/gnome-session.html#org.gnome.SessionManager.Inhibit">interface</a> is a bit low level, but workable:</p>
|
214
|
+
<pre class="code">require 'dbus' # gem install ruby-dbus
|
215
|
+
bus = DBus::SessionBus.instance
|
216
|
+
sm = bus.service('org.gnome.SessionManager').object('/org/gnome/SessionManager')
|
217
|
+
sm.introspect
|
218
|
+
sm.default_iface = 'org.gnome.SessionManager'
|
219
|
+
cookie = sm.Inhibit($0, 0, 'inhibiting', 4).first
|
220
|
+
at_exit { cookie = sm.Uninhibit(cookie) if sm.IsInhibited(4).first }</pre>
|
221
|
+
<p>Note: the call to <code>Uninhibit</code> is optional — it will occur on process exit anyway.</p>
|
222
|
+
<p>Hat tip to <a href="http://www.lucidelectricdreams.com/2011/06/disabling-screensaverlock-screen-on.html">JanuZ</a>.</p></div></content>
|
223
|
+
<updated>2012-07-16T08:48:01-07:00</updated>
|
224
|
+
</entry>
|
225
|
+
|
226
|
+
<entry>
|
227
|
+
<id>tag:intertwingly.net,2004:3298</id>
|
228
|
+
<link href="/blog/2012/07/10/utf8mb4"/>
|
229
|
+
<link rel="replies" href="3298.atom" thr:count="7" thr:updated="2012-10-15T14:45:05-07:00"/>
|
230
|
+
<title>utf8mb4</title>
|
231
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" width="115" height="87" viewBox="0 0 115 87">
|
232
|
+
<path d="M0,1v83h26c-10,0-22-11-22-21v-62zM22,1v53c0,16,22,16,22,0v-53zM41,84c10,0,22-11,22-21v-22l27,43zM60,1h30v20h19v-20h5v84h-5v-56h-19v18z" fill="#C60025"></path>
|
233
|
+
</svg>
|
234
|
+
<p><a href="http://golem.ph.utexas.edu/~distler/blog/archives/002539.html"><cite>Jacques Distler</cite></a>: <em>Remarkably, even after a decade of such pain, Unicode is, in 2012, still “cutting edge.”</em></p>
|
235
|
+
<p>Ouch.</p></div></content>
|
236
|
+
<updated>2012-07-10T10:55:32-07:00</updated>
|
237
|
+
</entry>
|
238
|
+
|
239
|
+
<entry>
|
240
|
+
<id>tag:intertwingly.net,2004:3297</id>
|
241
|
+
<link href="/blog/2012/06/23/Ubuntu-12-04-and-Ruby-1-9-3"/>
|
242
|
+
<link rel="replies" href="3297.atom" thr:count="0"/>
|
243
|
+
<title>Ubuntu 12.04 and Ruby 1.9.3</title>
|
244
|
+
<summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I previously had installed Ubuntu 12.04 on a NetBook, and my overall impression was simply that it was more stable than its predecessor — particularly for Unity.</p>
|
245
|
+
<p>For the first time I tried it on a desktop, and to my surprise the following worked:</p>
|
246
|
+
<pre class="code">sudo apt-get install ruby1.9.3</pre>
|
247
|
+
<p>And by worked, I mean not only did it install Ruby 1.9.3, but it made it (and gem, and irc) the default ruby.</p>
|
248
|
+
<p>For those that still use <a href="https://rvm.io//">rvm</a>, (many of the ‘cool kids’ have moved on to <a href="https://github.com/sstephenson/rbenv/">rbenv</a>, I noticed a few niggles</p></div></summary>
|
249
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="140" height="140" viewBox="-70 -70 140 140">
|
250
|
+
|
251
|
+
<defs>
|
252
|
+
<path id="b" d="M 23,-20 A32,32 0,0,0 -23,-20 L -40,-30 A42,42 0,0,1 -14,-47 A17,17 0,0,0 14,-47 A42,42 0,0,1 40,-30 Z"></path>
|
253
|
+
<circle id="h" cx="0" cy="-57" r="12"></circle>
|
254
|
+
</defs>
|
255
|
+
|
256
|
+
<g transform="translate(5,5)" opacity="0.125">
|
257
|
+
<use xlink:href="#h" transform="rotate(30)"></use>
|
258
|
+
<use xlink:href="#b" transform="rotate(30)"></use>
|
259
|
+
<use xlink:href="#h" transform="rotate(150)"></use>
|
260
|
+
<use xlink:href="#b" transform="rotate(150)"></use>
|
261
|
+
<use xlink:href="#h" transform="rotate(-90)"></use>
|
262
|
+
<use xlink:href="#b" transform="rotate(-90)"></use>
|
263
|
+
</g>
|
264
|
+
|
265
|
+
<a xlink:href="http://www.ubuntu.com/">
|
266
|
+
<use xlink:href="#h" fill="#d00" transform="rotate(30)"></use>
|
267
|
+
<use xlink:href="#b" fill="#f40" transform="rotate(30)"></use>
|
268
|
+
<use xlink:href="#h" fill="#f80" transform="rotate(150)"></use>
|
269
|
+
<use xlink:href="#b" fill="#d00" transform="rotate(150)"></use>
|
270
|
+
<use xlink:href="#h" fill="#f40" transform="rotate(-90)"></use>
|
271
|
+
<use xlink:href="#b" fill="#f80" transform="rotate(-90)"></use>
|
272
|
+
</a>
|
273
|
+
|
274
|
+
</svg>
|
275
|
+
<p>I previously had installed Ubuntu 12.04 on a NetBook, and my overall impression was simply that it was more stable than its predecessor — particularly for Unity.</p>
|
276
|
+
<p>For the first time I tried it on a desktop, and to my surprise the following worked:</p>
|
277
|
+
<pre class="code">sudo apt-get install ruby1.9.3</pre>
|
278
|
+
<p>And by worked, I mean not only did it install Ruby 1.9.3, but it made it (and gem, and irc) the default ruby.</p>
|
279
|
+
<p>For those that still use <a href="https://rvm.io//">rvm</a>, (many of the ‘cool kids’ have moved on to <a href="https://github.com/sstephenson/rbenv/">rbenv</a>, I noticed a few niggles:</p>
|
280
|
+
<ul>
|
281
|
+
<li>Don’t follow the <a href="https://rvm.io//rvm/install/installation">instructions</a> and specify <code>--ruby</code> or <code>--rails</code>. You will get a version of Ruby that can’t install gems. Simply omit that parameter.</li>
|
282
|
+
<li>Next set the <a href="https://rvm.io/integration/gnome-terminal/">‘Run command as login shell’</a> checkbox.</li>
|
283
|
+
<li>Then run <code>rvm requirements</code> and install what it tells you to install.</li>
|
284
|
+
<li>Finally, run <code>rvm install 1.9.3</code> to build the latest.</li>
|
285
|
+
</ul>
|
286
|
+
|
287
|
+
<p>Personally, I follow that up with <code>rvm --default system</code>. That means that while I have other Rubies available at my finger-tips, the one I generally use is the one provided with Ubuntu.</p></div></content>
|
288
|
+
<updated>2012-06-23T15:45:50-07:00</updated>
|
289
|
+
</entry>
|
290
|
+
|
291
|
+
<entry>
|
292
|
+
<id>tag:intertwingly.net,2004:3296</id>
|
293
|
+
<link href="/blog/2012/06/07/Prefixed-no-more"/>
|
294
|
+
<link rel="replies" href="3296.atom" thr:count="0"/>
|
295
|
+
<title>Prefixed no more</title>
|
296
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" width="133" height="78" viewBox="0 0 133 78">
|
297
|
+
<path d="M23,72c-2,0-3,2-5,2c-1-2,2-4,2-7c-3,0-4,4-6,4c1-6,9-12,4-12c0,0-10,7-11,6c2-2,10-14,7-14c-1,0-7,4-9,4c0-2,9-10,10-11c2,0,3-2,2-3c-5,0-11,8-15,6l2-2c1-1,16-14,16-16c-3-2-13,6-18,6c22-24,38-33,47-35c7,0,14,2,21,3c0,3,12-1,13-1c5,0,9,4,11,8c0,1,0,2,0,4c3,11,31,7,35,19c0,5,1,9,2,14c-2,4-2,12-6,13c-4,1-4,1-4,1c-3,2-7,5-10,6c0,0-16-6-20-3c-12,4-16,8-19,20l-49-3"></path>
|
298
|
+
<path fill="#FFF" d="M86,22l-1-2h3v2h-2M83,19l-2,1l-1-2h2l1,1M122,57l-1-2c-1,0-1,1-3,1c0-1,0-3,0-4h2l1,2c1-1,2-1,3-1c1,1,1,2,0,3l-2,1M113,56c0-1,0-2,0-3c0-1,1-2,3-2c0,4,0,4-3,5M109,55c0-1-1-3,0-4h2c1,2,0,4-2,4M106,54l-2-2c-1,0-2,1-3,0c-1,0-1-2,0-4c1,0,2,0,3,1v2c1,0,2-1,3-1c1,0,0,2,0,3l-1,1M96,50c-2-1-1-2-1-4c2,0,3,0,4,2c-1,1-2,2-3,2"></path>
|
299
|
+
<path fill="#ED1C24" d="M40,75v-2c-2,0-9,2-9-2c0-2,5-8,3-8c-3-6-7-11-10-17c2-1,0-3,2-6c3-1,2,4,5,3c-4-17,5-22,5-22c-3,0-4,0-6,1c1-7,11-14,17-15c5-1,15-3,18,2c0,1-1,2-1,3c4,0,10-4,15-5c2-1,4-1,7,0l1,2c-7-3-17,3-23,6c-1,0-2,1-3,1l1,1c3,1,4,2,8,2c1,1,2,2,3,3c1,1,2,2,3,2c0-2,0-2-1-4c1-2-1-3,2-5c2,0,2,1,3,1c-4,4-2,8,10,9c1,0,3,1,3-2c-2,0-2-2-2-3l2,1c1,3,27,7,31,12c1,2,0,3-4,5c0,2,2,5,3,6l2-2l1,1c0,2,0,3,0,5v1c-1,0-2,0-3,0c-4-1-9-1-13-1c-11-5-25-16-36-20c-2-1-1-1-4-1c0,2,1,2,3,3c3,4,6,6,5,11l-1,2c-4,0-1-8-4-9c-10,8,5,25,13,20c-4-2-4-4-4-5c10,5,31,10,33,11c0,1-4,1-4,2c-5,1-13-2-17-4c-5-1-11,7-22,4c-2-1-13-8-15-8c0,4,9,12,11,13l0,2c-2,2-5,5-5,7"></path>
|
300
|
+
<path d="M80,24c3,1,11,4,9,5c-3,0-8,0-9-3v-2m-36-4l-2,2c0-1,1-3,1-3c3-6,9-8,14-7l0,1c-8,2-6,12-7,12c-2-1-3-5-6-5m0,34c0-6-8-17,3-22c1,0-2,15,7,19v2c-2,0-3,0-5,0c-1-2-1-1-2-1c0,2,1,5,1,7c-1-1-3-3-4-5m14-26c0-2-2-3,0-4c2,0,3-2,3-4c2,0,5,2,6,3c0,2-1,2-2,4c1,2,1,2,1,4h-1c-2,0-8-1-8,1c-2,0-3,0-5,0c-1-1,1-2,1-3c2,0,3-1,5-1"></path>
|
301
|
+
</svg>
|
302
|
+
<p>Firefox 13 for developers: <em>Support for <a href="https://developer.mozilla.org/en/CSS/border-radius"><code>-moz-border-radius*</code></a> and <a href="https://developer.mozilla.org/en/CSS/box-shadow"><code>-moz-box-shadow</code></a> has been removed. Authors should use unprefixed <code>border-radius</code> or <code>box-shadow</code> instead. See <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=693510">bug 693510</a></em></p>
|
303
|
+
<p>+1</p></div></content>
|
304
|
+
<updated>2012-06-07T05:33:07-07:00</updated>
|
305
|
+
</entry>
|
306
|
+
|
307
|
+
<entry>
|
308
|
+
<id>tag:intertwingly.net,2004:3295</id>
|
309
|
+
<link href="/blog/2012/05/29/Twitter"/>
|
310
|
+
<link rel="replies" href="3295.atom" thr:count="0"/>
|
311
|
+
<title>Twitter -= #!</title>
|
312
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" fill='black' xmlns='http://www.w3.org/2000/svg' width="95" height="105" viewBox="0 0 95 105">
|
313
|
+
<path d='M75,75h-21l-6,28h-10l6-28h-21l-6,28h-10l6-28h-11v-10h13l5-25h-18v-10h20l6-28h10l-6,28h21l6-28h10l-6,28h12v10h-14l-5,25h19zM51,40h-21l-5,25h21z'></path>
|
314
|
+
<path d='M93,25l-3,52h-8l-4-52v-22h15zM93,101h-14v-13h14z'></path>
|
315
|
+
</svg>
|
316
|
+
<a href="http://engineering.twitter.com/2012/05/improving-performance-on-twittercom.html"><cite>Dan Webb</cite></a>: <em>The first thing that you might notice is that permalink URLs are now simpler: they no longer use the hashbang (#!). While hashbang-style URLs have a <a href="http://danwebb.net/2011/5/28/it-is-about-the-hashbangs">handful of limitations</a>, our primary reason for this change is to improve initial page-load performance.</em></div></content>
|
317
|
+
<updated>2012-05-29T14:50:26-07:00</updated>
|
318
|
+
</entry>
|
319
|
+
|
320
|
+
<entry>
|
321
|
+
<id>tag:intertwingly.net,2004:3294</id>
|
322
|
+
<link href="/blog/2012/04/29/WebSocket-Demos"/>
|
323
|
+
<link rel="replies" href="3294.atom" thr:count="0"/>
|
324
|
+
<title>WebSocket Demos</title>
|
325
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
326
|
+
<path d="M4,14h92" stroke="#4682b4" stroke-width="5"></path>
|
327
|
+
<text x="50" y="90" font-size="90" fill="#5f9ea0" font-family="serif" text-anchor="middle"><![CDATA[W]]></text>
|
328
|
+
</svg>
|
329
|
+
<p><a href="https://github.com/rubys/wunderbar/blob/master/demo/chat.rb">chat</a> implements a shared textarea field across multiple clients. Demonstrates bi-directional communication.</p>
|
330
|
+
<p><a href="https://github.com/rubys/wunderbar/blob/master/demo/diskusage.rb">diskusage</a> is more typical of my usage. The <code>du</code> command produces tabular output that the user may want to sort different ways and yet is may take considerable time to complete.</p></div></content>
|
331
|
+
<updated>2012-04-29T18:33:49-07:00</updated>
|
332
|
+
</entry>
|
333
|
+
|
334
|
+
<entry>
|
335
|
+
<id>tag:intertwingly.net,2004:3293</id>
|
336
|
+
<link href="/blog/2012/04/24/Wunderbar-on-Rails"/>
|
337
|
+
<link rel="replies" href="3293.atom" thr:count="0"/>
|
338
|
+
<title>Wunderbar on Rails</title>
|
339
|
+
<summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>Usage: add <code>wunderbar</code> and <code>nokogiri</code> to your <code>Gemfile</code> and run <code>bundle install</code>. Template extensions supported are <code>_html</code> and <code>_json</code>. Examples: <a href="https://github.com/rubys/wunderbar/blob/master/test/views/rails_test/index.html._html">view</a>, <a href="https://github.com/rubys/wunderbar/blob/master/test/views/layouts/application.html._html">layout</a>, <a href="https://github.com/rubys/wunderbar/blob/master/test/views/rails_test/index.json._json">json</a>.</p>
|
340
|
+
<p>Note that as Rails layouts and views are predicated on the assumption that output is produced by concatenating text, one must use <code>_ yield</code> instead of simply <code>yield</code>. On the plus side, Wunderbar will note when the first argument to a call which creates an element is <code>html_safe?</code> and will treat it as markup.</p></div></summary>
|
341
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
342
|
+
<path d="M4,14h92" stroke="#4682b4" stroke-width="5"></path>
|
343
|
+
<text x="50" y="90" font-size="90" fill="#5f9ea0" font-family="serif" text-anchor="middle"><![CDATA[W]]></text>
|
344
|
+
</svg>
|
345
|
+
<p>Usage: add <code>wunderbar</code> and <code>nokogiri</code> to your <code>Gemfile</code> and run <code>bundle install</code>. Template extensions supported are <code>_html</code> and <code>_json</code>. Examples: <a href="https://github.com/rubys/wunderbar/blob/master/test/views/rails_test/index.html._html">view</a>, <a href="https://github.com/rubys/wunderbar/blob/master/test/views/layouts/application.html._html">layout</a>, <a href="https://github.com/rubys/wunderbar/blob/master/test/views/rails_test/index.json._json">json</a>.</p>
|
346
|
+
<p>Note that as Rails layouts and views are predicated on the assumption that output is produced by concatenating text, one must use <code>_ yield</code> instead of simply <code>yield</code>. I have noticed that this may lose blank lines in the process, which apparently is a <a href="http://groups.google.com/group/nokogiri-talk/browse_thread/thread/d332456737253631?pli=1">known</a> <a href="https://github.com/tenderlove/nokogiri/issues/575">issue</a> with Nokogiri. Not a problem if the layout is erb, but then you lose the unified indentation that you get if you have a layout using <code>_html</code>.</p>
|
347
|
+
<p>On the plus side, Wunderbar will note when the first argument to a call which creates an element is <code>html_safe?</code> and will treat it as markup. An example of where this is useful would be in the <code>_td link_to</code> calls below. </p>
|
348
|
+
<pre class="code">_h1_ 'Listing products'
|
349
|
+
|
350
|
+
_table do
|
351
|
+
_tr do
|
352
|
+
_th 'Title'
|
353
|
+
_th
|
354
|
+
_th
|
355
|
+
_th
|
356
|
+
end
|
357
|
+
|
358
|
+
@products.each do |product|
|
359
|
+
_tr_ do
|
360
|
+
_td product.title
|
361
|
+
_td link_to 'Show', product
|
362
|
+
_td link_to 'Edit', edit_product_path(product)
|
363
|
+
_td link_to 'Destroy', product, confirm: 'Are you sure?', method: :delete
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
_br_
|
369
|
+
|
370
|
+
_ link_to 'New Product', new_product_path</pre></div></content>
|
371
|
+
<updated>2012-04-24T14:12:59-07:00</updated>
|
372
|
+
</entry>
|
373
|
+
|
374
|
+
<entry>
|
375
|
+
<id>tag:intertwingly.net,2004:3292</id>
|
376
|
+
<link href="/blog/2012/04/12/Wunderbar-now-does-Sinatra"/>
|
377
|
+
<link rel="replies" href="3292.atom" thr:count="2" thr:updated="2012-04-22T09:44:27-07:00"/>
|
378
|
+
<title>Wunderbar now does Sinatra</title>
|
379
|
+
<summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p><a href="https://github.com/rubys/wunderbar/blob/master/demo/hellosinatra.rb">Demo</a></p>
|
380
|
+
<p>The result is a lot like <a href="http://markaby.rubyforge.org/">Markaby</a>, except you get to be/have to be explicit when you are creating a tag. In this demo, there is no logic, so the benefits of doing so are less clear, but include you being able to use tags that aren’t known to Markaby, like the ones that were <a href="http://www.w3.org/TR/html5-diff/#new-elements">added in HTML5</a>. Both inline and views are supported, but support for layouts has yet to be added.</p>
|
381
|
+
<p>Future plans include <a href="http://rubyonrails.org/">Rails</a>.</p></div></summary>
|
382
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
383
|
+
<path d="M4,14h92" stroke="#4682b4" stroke-width="5"></path>
|
384
|
+
<text x="50" y="90" font-size="90" fill="#5f9ea0" font-family="serif" text-anchor="middle"><![CDATA[W]]></text>
|
385
|
+
</svg>
|
386
|
+
<p><a href="https://github.com/rubys/wunderbar/blob/master/demo/hellosinatra.rb">Demo</a></p>
|
387
|
+
<p>The result is a lot like <a href="http://markaby.rubyforge.org/">Markaby</a>, except you get to be/have to be explicit when you are creating a tag. In this demo, there is no logic, so the benefits of doing so are less clear, but include you being able to use tags that aren’t known to Markaby, like the ones that were <a href="http://www.w3.org/TR/html5-diff/#new-elements">added in HTML5</a>. Both inline and views are supported, but support for layouts has yet to be added.</p>
|
388
|
+
<p>While the demos require Ruby 1.9.2+ (the Hash syntax is nicer), the library works equally well with Ruby 1.8.7.</p>
|
389
|
+
<p>The progression is that you start from <a href="https://github.com/rubys/wunderbar/blob/master/demo/helloworld.rb">scripts</a> that you can run from the command line:</p>
|
390
|
+
<pre class="code">ruby helloworld.rb</pre>
|
391
|
+
<p>...can pass arguments to:</p>
|
392
|
+
<pre class="code">ruby helloword.rb name=Sam</pre>
|
393
|
+
<p>...can run as a standalone server:</p>
|
394
|
+
<pre class="code">ruby helloworld.rb --port=3004</pre>
|
395
|
+
<p>...can install as a CGI:</p>
|
396
|
+
<pre class="code">ruby helloworld.rb --install="/Library/WebServer/Documents/helloworld.cgi"</pre>
|
397
|
+
<p>.,. and can now run under Sinatra. Future plans include <a href="http://rubyonrails.org/">Rails</a>.</p>
|
398
|
+
<p>There even is a <a href="https://github.com/rubys/wunderbar/blob/master/tools/web2script.rb">tool</a> that will reverse engineer an existing web page into a script.</p></div></content>
|
399
|
+
<updated>2012-04-12T17:12:31-07:00</updated>
|
400
|
+
</entry>
|
401
|
+
|
402
|
+
<entry>
|
403
|
+
<id>tag:intertwingly.net,2004:3291</id>
|
404
|
+
<link href="/blog/2012/04/02/Hacked"/>
|
405
|
+
<link rel="replies" href="3291.atom" thr:count="5" thr:updated="2012-05-20T03:28:03-07:00"/>
|
406
|
+
<title>Hacked</title>
|
407
|
+
<summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>This site was hacked. A reader of the site noted that Google’s <a href="https://www.google.com/search?q=site%3Aintertwingly.net">index of this site</a> had been co-opted by dubious pharmaceutical offerings. I’ll gladly thank that individual publicly if they give me permission to do so; but my email reply got bounced as spam.</p>
|
408
|
+
<p>The immediate culprit was the addition of the following lines to a number of <code>.htaccess</code> files</p></div></summary>
|
409
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
410
|
+
<g stroke="#000" stroke-linejoin="round">
|
411
|
+
<path fill="#DDD" d="M27,42c-8-53,55-53,47,0h-8 c10-41-40-41-30,0h-9z"></path>
|
412
|
+
<path fill="#CB9" d="M23,91v-50c18-3,36-2,55,0v50c-19,3-37,2-55,0z"></path>
|
413
|
+
<path fill="#EDA" d="M23,91v-50c18-3,36-2,55,0z"></path>
|
414
|
+
<path fill="#A87" d="M78,41v50c-19,3-37,2-55,0z"></path>
|
415
|
+
</g>
|
416
|
+
<path fill="#EEE" d="M30,21c5-10,7-17,23-16c-10,0-18,14-23,16"></path>
|
417
|
+
<path fill="#CB9" d="M78,41c-50,4-50,0-55,50c50-5,50,0,55-50z"></path>
|
418
|
+
<path fill="#000" d="M46,77h10l-3-11a6,6,0,1,0-5,0z"></path>
|
419
|
+
</svg>
|
420
|
+
<p>This site was hacked. A reader of the site noted that Google’s <a href="https://www.google.com/search?q=site%3Aintertwingly.net">index of this site</a> had been co-opted by dubious pharmaceutical offerings. I’ll gladly thank that individual publicly if they give me permission to do so; but my email reply got bounced as spam.</p>
|
421
|
+
<p>The immediate culprit was the addition of the following lines to a number of <code>.htaccess</code> files:</p>
|
422
|
+
<pre class="code"><IfModule mod_rewrite.c>
|
423
|
+
RewriteEngine On
|
424
|
+
RewriteCond %{HTTP_USER_AGENT} (google|yahoo) [OR]
|
425
|
+
RewriteCond %{HTTP_REFERER} (google|aol|yahoo)
|
426
|
+
RewriteCond %{REQUEST_URI} /$ [OR]
|
427
|
+
RewriteCond %{REQUEST_FILENAME} (html|htm|php)$ [NC]
|
428
|
+
RewriteCond %{REQUEST_FILENAME} !common.php
|
429
|
+
RewriteRule ^.*$ /common.php [L]
|
430
|
+
</IfModule></pre>
|
431
|
+
<p>I removed those lines, as well as the <code>common.php</code> file, and scanned any and all php files on my site. I saw the addition of lines such as the following:</p>
|
432
|
+
<pre class="code">$FYAqxDo='p'.'r'. 'eg_repl'. 'ace';...
|
433
|
+
$IHxWfs=str_rot13('cert_ercynpr');...
|
434
|
+
$DcNZVHCi="eW6DLAlbeAki"^"...
|
435
|
+
$LYDmvYopCKSSSGcfCVNpsskU='ba'.'se64_'.'deco'.'de'...</pre>
|
436
|
+
<p>I had old (vintage 2006) installations of PHP-openid-1.2.1 and PHP-yadis-1.0.2 that I am tentatively assuming were the ports of initial entry.</p>
|
437
|
+
<p>I also wiped my .ssh directory. It has a private key there that was generated for this site that presumably was legitimate, but unused by me and now presumed compromised. I never initiate sessions from this host, nor do I have any passwords saved there, so any damage caused was isolated.</p>
|
438
|
+
<p>I do daily backups of my site, which I keep for a week; as well as monthly backups that I basically keep forever. In addition, as I recently <a href="http://intertwingly.net/blog/2012/02/13/On-The-Move">migrated hosts</a>, I have a hot backup.</p>
|
439
|
+
<p>The PHP hacks were done after I migrated but before March 1st. The htaccess hacks were done over a week ago, but after March 1st.</p>
|
440
|
+
<p>Over the next few days, I’ll be looking at diffs of different snapshots of my site contents to see if there is anything else I missed.</p></div></content>
|
441
|
+
<updated>2012-04-02T04:16:43-07:00</updated>
|
442
|
+
</entry>
|
443
|
+
|
444
|
+
<entry>
|
445
|
+
<id>tag:intertwingly.net,2004:3290</id>
|
446
|
+
<link href="/blog/2012/04/01/Improved-Wunderbar-JSON-support"/>
|
447
|
+
<link rel="replies" href="3290.atom" thr:count="0"/>
|
448
|
+
<title>Improved Wunderbar JSON support</title>
|
449
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
450
|
+
<path d="M4,14h92" stroke="#4682b4" stroke-width="5"></path>
|
451
|
+
<text x="50" y="90" font-size="90" fill="#5f9ea0" font-family="serif" text-anchor="middle"><![CDATA[W]]></text>
|
452
|
+
</svg>
|
453
|
+
<p>I’ve integrated <a href="https://github.com/rails/jbuilder">jbuilder</a> like functionality into <a href="https://github.com/rubys/wunderbar#readme">Wunderbar</a>. Key differences? A DSL that doesn’t suck, and output that isn’t ugly.</p>
|
454
|
+
<p>To harsh? You be the judge. Compare <a href="https://github.com/rails/jbuilder/blob/master/test/jbuilder_test.rb#L176">jbuilder</a> ("json dot bar json bar json dot child bang") vs <a href="https://github.com/rubys/wunderbar/blob/master/test/test_jbuilder.rb#L154">Wunderbar</a> ("underbar underbar underbar underbar").</p>
|
455
|
+
<p>As to the output? Don’t be fooled by the jbuilder <a href="https://github.com/rails/jbuilder#readme">readme</a>. In actuality is no unnecessary whitespace in the output. That’s good if you are bandwidth limited. Not so good when viewing the XHR traffic via firebug...</p></div></content>
|
456
|
+
<updated>2012-04-01T05:57:41-07:00</updated>
|
457
|
+
</entry>
|
458
|
+
|
459
|
+
<entry>
|
460
|
+
<id>tag:intertwingly.net,2004:3289</id>
|
461
|
+
<link href="/blog/2012/03/28/Keeping-it-on-the-Rails"/>
|
462
|
+
<link rel="replies" href="3289.atom" thr:count="0"/>
|
463
|
+
<title>Keeping it on the Rails</title>
|
464
|
+
<summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>It is increasingly becoming the case that <a href="http://pragprog.com/book/rails4/agile-web-development-with-rails">Agile Web Development with Rails</a> is being actively co-developed with <a href="http://rubyonrails.org/">Rails</a> itself.</p>
|
465
|
+
<p>While <a href="http://intertwingly.net/projects/dashboard.html">my tests</a> have been an <a href="https://github.com/rails/rails/blob/master/RELEASING_RAILS.rdoc">official part of the release process</a> for a long time now, yesterday’s release of <a href="http://weblog.rubyonrails.org/2012/3/27/ann-rails-3-2-3-rc1-has-been-released/">3.2.3RC1</a> provides a number of examples that illustrate this.</p>
|
466
|
+
<p>The intent is to prove an updated to the eBook free of charge which incorporates the necessary changes, either concurrent with the final release of 3.2.3 or shortly thereafter.</p></div></summary>
|
467
|
+
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><svg style="float:right" xmlns='http://www.w3.org/2000/svg' width="100" height="100" viewBox="0 0 1000 1000">
|
468
|
+
|
469
|
+
<!-- 5 -->
|
470
|
+
<path d='M160,560c2-6-2-13-6-17l-6-9c-104-164,58-356,234-305c59,18,119,63,158,116c33,45,49,95,53,140c8,87-16,169-62,219c0,0-22,24,8,42c28,16,112-18,152-163c37-132-50-403-312-455c-190-37-302,124-304,268c0,58,30,125,63,159c14,14,21,11,22,5' fill='#17733B'></path>
|
471
|
+
<radialGradient cx='651' cy='363' id='r5g1' r='257' gradientUnits='userSpaceOnUse'>
|
472
|
+
<stop offset='0' style='stop-color:#E0EECF'></stop>
|
473
|
+
<stop offset='1' style='stop-color:#17753C'></stop>
|
474
|
+
</radialGradient>
|
475
|
+
<path d='M581,733c-20,9-31-2-31-2c107-75,132-334-31-471c-159-133-277-83-327-52c0,0,36-73,145-76c61-2,229,40,314,213c99,202-1,327-22,352c-13,17-37,31-48,36' fill='url(#r5g1)'></path>
|
476
|
+
<radialGradient cx='477' cy='494' id='r5g2' r='247' gradientUnits='userSpaceOnUse'>
|
477
|
+
<stop offset='0' style='stop-color:#DAECCE'></stop>
|
478
|
+
<stop offset='1' style='stop-color:#17733B'></stop>
|
479
|
+
</radialGradient>
|
480
|
+
<path d='M562,675c44-90,66-232-27-346c-93-114-198-113-198-113s156-14,250,175c73,147-25,284-25,284' fill='url(#r5g2)'></path>
|
481
|
+
|
482
|
+
<!-- 1 -->
|
483
|
+
<path d='M593,219c4,5,12,4,18,4c3-1,7-1,11-1c194-9,279,228,147,354c-45,43-115,72-180,80c-55,6-106-6-147-25c-79-36-139-97-159-163c0,0-10-31-40-14c-29,16-41,106,64,213c96,98,375,159,551-42c127-146,44-324-80-397c-51-30-123-37-169-25c-20,5-21,12-16,16' fill='#821C35'></path>
|
484
|
+
<radialGradient cx='518' cy='742' id='r1g1' r='257' gradientUnits='userSpaceOnUse'>
|
485
|
+
<stop offset='0' style='stop-color:#F7A8A9'></stop>
|
486
|
+
<stop offset='0.7178' style='stop-color:#821C35'></stop>
|
487
|
+
</radialGradient>
|
488
|
+
<path d='M232,497c3-22,18-25,18-25c12,129,224,280,424,208c195-71,210-198,208-257c0,0,45,67-7,164c-29,53-149,177-342,164c-223-14-282-164-294-194c-7-20-8-48-7-60' fill='url(#r1g1)'></path>
|
489
|
+
<radialGradient cx='492' cy='526' id='r1g2' r='247' gradientUnits='userSpaceOnUse'>
|
490
|
+
<stop offset='0' style='stop-color:#F2A5B7'></stop>
|
491
|
+
<stop offset='1' style='stop-color:#821C35'></stop>
|
492
|
+
</radialGradient>
|
493
|
+
<path d='M293,510c55,83,167,173,312,149c146-24,197-115,197-115s-66,143-276,130c-164-11-233-164-233-164' fill='url(#r1g2)'></path>
|
494
|
+
|
495
|
+
<!-- 3 -->
|
496
|
+
<clipPath id="r3c">
|
497
|
+
<path d="M999,999 L558,370 c-30-50-40-50-70-84h-400v700z" opacity="0"></path>
|
498
|
+
</clipPath>
|
499
|
+
<g clip-path="url(#r3c)">
|
500
|
+
<path d='M677,766c-6,2-10,9-11,14c-2,3-4,7-5,11c-90,172-338,127-381-51c-14-60-5-135,21-195c23-51,58-89,95-115c71-50,154-71,220-56c0,0,32,7,33-28c0-33-71-88-217-51c-133,34-324,245-238,498c62,183,258,200,383,129c51-28,94-88,107-134c5-19-1-23-7-22' fill='#3564AF'></path>
|
501
|
+
<radialGradient cx='262' cy='440' id='r3g1' r='364' gradientUnits='userSpaceOnUse'>
|
502
|
+
<stop offset='0' style='stop-color:#EFF1F6'></stop>
|
503
|
+
<stop offset='1' style='stop-color:#3564AF'></stop>
|
504
|
+
</radialGradient>
|
505
|
+
<path d='M617,315c18,14,13,28,13,28c-118-54-355,54-392,263c-36,205,66,281,118,309c0,0-81,6-138-88c-32-51-79-217,28-378c125-186,283-162,316-157c21,3,45,16,55,23' fill='url(#r3g1)'></path>
|
506
|
+
<radialGradient cx='462' cy='525' id='r3g2' r='350' gradientUnits='userSpaceOnUse'>
|
507
|
+
<stop offset='0' style='stop-color:#EFF1F6'></stop>
|
508
|
+
<stop offset='1' style='stop-color:#3564AF'></stop>
|
509
|
+
</radialGradient>
|
510
|
+
<path d='M576,362c-100,6-234,58-286,195s1,228,1,228s-90-128,26-304c91-136,259-119,259-119' fill='url(#r3g2)'></path>
|
511
|
+
</g>
|
512
|
+
|
513
|
+
<!-- 6 -->
|
514
|
+
<radialGradient cx='528' cy='251' id='r6g1' r='277' gradientUnits='userSpaceOnUse'>
|
515
|
+
<stop offset='0' style='stop-color:#E2EFCF'></stop>
|
516
|
+
<stop offset='1' style='stop-color:#14743B'></stop>
|
517
|
+
</radialGradient>
|
518
|
+
<path d='M804,494c-16,4-38-12-43-43c-17-99-90-288-283-364c-176-69-252-6-252-6c-10,4-6-12,2-18c7-7,105-112,334-13c217,94,278,309,272,383c0,10-3,24-4,29c-5,21-15,28-26,32' fill='url(#r6g1)'></path>
|
519
|
+
<radialGradient cx='748' cy='240' id='r6g2' r='312' gradientUnits='userSpaceOnUse'>
|
520
|
+
<stop offset='0' style='stop-color:#E2EFCF'></stop>
|
521
|
+
<stop offset='1' style='stop-color:#14743B'></stop>
|
522
|
+
</radialGradient>
|
523
|
+
<path d='M800,488c-1-132-88-337-289-418c-193-78-256-19-256-19s73-91,293-4c208,82,265,267,278,321c12,52,4,94-4,108c-9,16-22,12-22,12' fill='url(#r6g2)'></path>
|
524
|
+
<radialGradient cx='634' cy='302' id='r6g3' r='185' gradientUnits='userSpaceOnUse'>
|
525
|
+
<stop offset='0' style='stop-color:#E2EFCF'></stop>
|
526
|
+
<stop offset='1' style='stop-color:#14743B'></stop>
|
527
|
+
</radialGradient>
|
528
|
+
<path d='M767,457c-16-90-50-158-87-212c-45-66-103-114-191-158c0,0,112,25,198,148c73,106,80,222,80,222' fill='url(#r6g3)'></path>
|
529
|
+
|
530
|
+
<!-- 4 -->
|
531
|
+
<path d='M298,243c12,11,9,38-15,58c-78,64-204,222-174,427c28,187,121,221,121,221c8,6-8,11-17,8s-150-35-178-283c-27-235,128-396,195-428c9-4,22-9,27-10c21-6,32-2,41,7' fill='#3564AF'></path>
|
532
|
+
<radialGradient cx='107' cy='418' id='r4g1' r='441' gradientUnits='userSpaceOnUse'>
|
533
|
+
<stop offset='0' style='stop-color:#D3DCE8'></stop>
|
534
|
+
<stop offset='1' style='stop-color:#3564AF'></stop>
|
535
|
+
</radialGradient>
|
536
|
+
<path d='M295,248c-114,68-248,245-217,459c29,207,111,232,111,232s-115-18-150-251c-33-221,99-364,140-402c38-36,78-50,95-50c18,0,21,12,21,12' fill='url(#r4g1)'></path>
|
537
|
+
<radialGradient cx='217' cy='485' id='r4g2' r='261' gradientUnits='userSpaceOnUse'>
|
538
|
+
<stop offset='0' style='stop-color:#F0F1F9'></stop>
|
539
|
+
<stop offset='1' style='stop-color:#3564AF'></stop>
|
540
|
+
</radialGradient>
|
541
|
+
<path d='M285,293c-70,59-112,121-141,182c-34,71-47,145-41,243c0,0-34-109,29-244c55-117,153-181,153-181' fill='url(#r4g2)'></path>
|
542
|
+
|
543
|
+
<!-- 2 -->
|
544
|
+
<radialGradient cx='661' cy='712' id='r2g1' r='275' gradientUnits='userSpaceOnUse'>
|
545
|
+
<stop offset='0' style='stop-color:#E89EB0'></stop>
|
546
|
+
<stop offset='1' style='stop-color:#821C35'></stop>
|
547
|
+
</radialGradient>
|
548
|
+
<path d='M329,810c4-16,28-27,58-16c94,35,294,66,457-63c147-118,131-216,131-216c1-10,13,2,15,11c2,10,44,147-156,296c-190,141-407,87-468,45l-23-18c-15-16-17-27-14-39' fill='url(#r2g1)'></path>
|
549
|
+
<radialGradient cx='576' cy='888' id='r2g2' r='312' gradientUnits='userSpaceOnUse'>
|
550
|
+
<stop offset='0' style='stop-color:#CFA2AD'></stop>
|
551
|
+
<stop offset='1' style='stop-color:#821C35'></stop>
|
552
|
+
</radialGradient>
|
553
|
+
<path d='M335,810c116,64,336,92,506-42c164-128,145-212,145-212s43,108-142,255c-175,139-365,96-418,80c-50-15-83-42-91-57c-9-16,0-24,0-24' fill='url(#r2g2)'></path>
|
554
|
+
<radialGradient cx='579' cy='758' id='r2g3' r='185' gradientUnits='userSpaceOnUse'>
|
555
|
+
<stop offset='0' style='stop-color:#DE95A7'></stop>
|
556
|
+
<stop offset='1' style='stop-color:#821C35'></stop>
|
557
|
+
</radialGradient>
|
558
|
+
<path d='M379,796c86,31,161,36,227,31c79-6,150-32,232-87c0,0-78,85-226,98c-129,11-233-42-233-42' fill='url(#r2g3)'></path>
|
559
|
+
|
560
|
+
</svg>
|
561
|
+
<p>It is increasingly becoming the case that <a href="http://pragprog.com/book/rails4/agile-web-development-with-rails">Agile Web Development with Rails</a> is being actively co-developed with <a href="http://rubyonrails.org/">Rails</a> itself.</p>
|
562
|
+
<p>While <a href="http://intertwingly.net/projects/dashboard.html">my tests</a> have been an <a href="https://github.com/rails/rails/blob/master/RELEASING_RAILS.rdoc">official part of the release process</a> for a long time now, yesterday’s release of <a href="http://weblog.rubyonrails.org/2012/3/27/ann-rails-3-2-3-rc1-has-been-released/">3.2.3RC1</a> provides a number of examples that illustrate this.</p>
|
563
|
+
<p>Within hours after the release, I got an excited IM from Santiago Pastorino that my tests were failing. In particular, the failure was thus:</p>
|
564
|
+
<pre class="code">rake db:migrate
|
565
|
+
rake aborted!
|
566
|
+
An error has occurred, this and all later migrations canceled:
|
567
|
+
uninitialized constant Arel::Relation
|
568
|
+
Tasks: TOP => db:migrate
|
569
|
+
(See full trace by running task with --trace)</pre>
|
570
|
+
<p>The root cause was quickly determined to be a recent change to <a href="https://github.com/rails/arel/commit/9978fc40a8a5a262670279129a335845ad647f48">arel</a>, and a number of corrective actions were promptly taken: first, <a href="https://github.com/rails/arel/commit/6e8d1587091e00a84ea24ab92d9e836c3c38bcb8">the change was backed out</a>, then <a href="https://github.com/rails/rails/commit/2fa7ccf7aee3696e99f1b528db848aff5a671f77">Rails 4.0 was updated</a> and <a href="https://github.com/rails/rails/commit/24208d9a8662e2e35afc9c64695c600b2e960418">Rails 3.2 was changed to point to a branch of arel</a>, and finally, the <a href="https://github.com/rails/arel/commit/d43ae586aab7092c6bf742609ff1dc3ebf6aff6a">original change was reapplied</a>.</p>
|
571
|
+
<p>The previous error that was caught was <a href="https://github.com/rails/rails/commit/b700153507b7d539a57a6e3bcf03c84776795051"> connection pool of new applications have size 1</a>. This demonstrates the unique value that my tests bring to the table. Outside of my tests, the bulk of the test of Rails is an impressive array of unit tests (which verify that the connection pool setting does what it is supposed to do), and real world testing (using applications with highly tuned configurations), and my tests. Only the latter is effectively testing that the defaults provided actually work together to provide a viable configuration to use as a starter set for new applications.</p>
|
572
|
+
<p>One last example, this one shows the level cooperation involved. The underlying security changes that were the raison d'être for the 3.2.3 release caused the following scenario to fail:</p>
|
573
|
+
<pre class="code">rails generate scaffold Product title:string
|
574
|
+
rake db:migrate
|
575
|
+
rake test</pre>
|
576
|
+
<p>The root cause was that the code generated as scaffolding used the very feature which is now being discouraged as it creates a security issue. The fix required both changes to Rails itself (to change the scaffolding generated) and to the scenario provided in the book (both in identifying the code that needs to be changed, and in the changes that need to be made).</p>
|
577
|
+
<p>The intent is to prove an updated to the eBook free of charge which incorporates the necessary changes, either concurrent with the final release of 3.2.3 or shortly thereafter.</p></div></content>
|
578
|
+
<updated>2012-03-28T13:44:13-07:00</updated>
|
579
|
+
</entry>
|
580
|
+
|
581
|
+
</feed>
|
582
|
+
|