caring-nokogiri 1.4.1.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (270) hide show
  1. data/.autotest +27 -0
  2. data/CHANGELOG.ja.rdoc +330 -0
  3. data/CHANGELOG.rdoc +324 -0
  4. data/Manifest.txt +269 -0
  5. data/README.ja.rdoc +105 -0
  6. data/README.rdoc +118 -0
  7. data/Rakefile +248 -0
  8. data/bin/nokogiri +49 -0
  9. data/ext/nokogiri/extconf.rb +147 -0
  10. data/ext/nokogiri/html_document.c +145 -0
  11. data/ext/nokogiri/html_document.h +10 -0
  12. data/ext/nokogiri/html_element_description.c +272 -0
  13. data/ext/nokogiri/html_element_description.h +10 -0
  14. data/ext/nokogiri/html_entity_lookup.c +32 -0
  15. data/ext/nokogiri/html_entity_lookup.h +8 -0
  16. data/ext/nokogiri/html_sax_parser_context.c +92 -0
  17. data/ext/nokogiri/html_sax_parser_context.h +11 -0
  18. data/ext/nokogiri/nokogiri.c +95 -0
  19. data/ext/nokogiri/nokogiri.h +145 -0
  20. data/ext/nokogiri/xml_attr.c +92 -0
  21. data/ext/nokogiri/xml_attr.h +9 -0
  22. data/ext/nokogiri/xml_attribute_decl.c +67 -0
  23. data/ext/nokogiri/xml_attribute_decl.h +9 -0
  24. data/ext/nokogiri/xml_cdata.c +54 -0
  25. data/ext/nokogiri/xml_cdata.h +9 -0
  26. data/ext/nokogiri/xml_comment.c +52 -0
  27. data/ext/nokogiri/xml_comment.h +9 -0
  28. data/ext/nokogiri/xml_document.c +388 -0
  29. data/ext/nokogiri/xml_document.h +24 -0
  30. data/ext/nokogiri/xml_document_fragment.c +46 -0
  31. data/ext/nokogiri/xml_document_fragment.h +10 -0
  32. data/ext/nokogiri/xml_dtd.c +192 -0
  33. data/ext/nokogiri/xml_dtd.h +10 -0
  34. data/ext/nokogiri/xml_element_content.c +123 -0
  35. data/ext/nokogiri/xml_element_content.h +10 -0
  36. data/ext/nokogiri/xml_element_decl.c +69 -0
  37. data/ext/nokogiri/xml_element_decl.h +9 -0
  38. data/ext/nokogiri/xml_entity_decl.c +97 -0
  39. data/ext/nokogiri/xml_entity_decl.h +10 -0
  40. data/ext/nokogiri/xml_entity_reference.c +50 -0
  41. data/ext/nokogiri/xml_entity_reference.h +9 -0
  42. data/ext/nokogiri/xml_io.c +31 -0
  43. data/ext/nokogiri/xml_io.h +11 -0
  44. data/ext/nokogiri/xml_namespace.c +74 -0
  45. data/ext/nokogiri/xml_namespace.h +12 -0
  46. data/ext/nokogiri/xml_node.c +1060 -0
  47. data/ext/nokogiri/xml_node.h +13 -0
  48. data/ext/nokogiri/xml_node_set.c +397 -0
  49. data/ext/nokogiri/xml_node_set.h +9 -0
  50. data/ext/nokogiri/xml_processing_instruction.c +54 -0
  51. data/ext/nokogiri/xml_processing_instruction.h +9 -0
  52. data/ext/nokogiri/xml_reader.c +593 -0
  53. data/ext/nokogiri/xml_reader.h +10 -0
  54. data/ext/nokogiri/xml_relax_ng.c +159 -0
  55. data/ext/nokogiri/xml_relax_ng.h +9 -0
  56. data/ext/nokogiri/xml_sax_parser.c +286 -0
  57. data/ext/nokogiri/xml_sax_parser.h +43 -0
  58. data/ext/nokogiri/xml_sax_parser_context.c +155 -0
  59. data/ext/nokogiri/xml_sax_parser_context.h +10 -0
  60. data/ext/nokogiri/xml_sax_push_parser.c +91 -0
  61. data/ext/nokogiri/xml_sax_push_parser.h +9 -0
  62. data/ext/nokogiri/xml_schema.c +156 -0
  63. data/ext/nokogiri/xml_schema.h +9 -0
  64. data/ext/nokogiri/xml_syntax_error.c +261 -0
  65. data/ext/nokogiri/xml_syntax_error.h +13 -0
  66. data/ext/nokogiri/xml_text.c +48 -0
  67. data/ext/nokogiri/xml_text.h +9 -0
  68. data/ext/nokogiri/xml_xpath.c +53 -0
  69. data/ext/nokogiri/xml_xpath.h +11 -0
  70. data/ext/nokogiri/xml_xpath_context.c +239 -0
  71. data/ext/nokogiri/xml_xpath_context.h +9 -0
  72. data/ext/nokogiri/xslt_stylesheet.c +131 -0
  73. data/ext/nokogiri/xslt_stylesheet.h +9 -0
  74. data/lib/nokogiri.rb +116 -0
  75. data/lib/nokogiri/css.rb +25 -0
  76. data/lib/nokogiri/css/generated_parser.rb +646 -0
  77. data/lib/nokogiri/css/generated_tokenizer.rb +143 -0
  78. data/lib/nokogiri/css/node.rb +99 -0
  79. data/lib/nokogiri/css/parser.rb +82 -0
  80. data/lib/nokogiri/css/parser.y +227 -0
  81. data/lib/nokogiri/css/syntax_error.rb +7 -0
  82. data/lib/nokogiri/css/tokenizer.rb +7 -0
  83. data/lib/nokogiri/css/tokenizer.rex +54 -0
  84. data/lib/nokogiri/css/xpath_visitor.rb +162 -0
  85. data/lib/nokogiri/decorators/slop.rb +33 -0
  86. data/lib/nokogiri/ffi/html/document.rb +28 -0
  87. data/lib/nokogiri/ffi/html/element_description.rb +85 -0
  88. data/lib/nokogiri/ffi/html/entity_lookup.rb +16 -0
  89. data/lib/nokogiri/ffi/html/sax/parser_context.rb +38 -0
  90. data/lib/nokogiri/ffi/io_callbacks.rb +42 -0
  91. data/lib/nokogiri/ffi/libxml.rb +356 -0
  92. data/lib/nokogiri/ffi/structs/common_node.rb +26 -0
  93. data/lib/nokogiri/ffi/structs/html_elem_desc.rb +24 -0
  94. data/lib/nokogiri/ffi/structs/html_entity_desc.rb +13 -0
  95. data/lib/nokogiri/ffi/structs/xml_alloc.rb +16 -0
  96. data/lib/nokogiri/ffi/structs/xml_attr.rb +19 -0
  97. data/lib/nokogiri/ffi/structs/xml_attribute.rb +27 -0
  98. data/lib/nokogiri/ffi/structs/xml_buffer.rb +16 -0
  99. data/lib/nokogiri/ffi/structs/xml_document.rb +108 -0
  100. data/lib/nokogiri/ffi/structs/xml_dtd.rb +28 -0
  101. data/lib/nokogiri/ffi/structs/xml_element.rb +26 -0
  102. data/lib/nokogiri/ffi/structs/xml_element_content.rb +17 -0
  103. data/lib/nokogiri/ffi/structs/xml_entity.rb +32 -0
  104. data/lib/nokogiri/ffi/structs/xml_enumeration.rb +12 -0
  105. data/lib/nokogiri/ffi/structs/xml_node.rb +28 -0
  106. data/lib/nokogiri/ffi/structs/xml_node_set.rb +53 -0
  107. data/lib/nokogiri/ffi/structs/xml_notation.rb +11 -0
  108. data/lib/nokogiri/ffi/structs/xml_ns.rb +15 -0
  109. data/lib/nokogiri/ffi/structs/xml_parser_context.rb +19 -0
  110. data/lib/nokogiri/ffi/structs/xml_relax_ng.rb +14 -0
  111. data/lib/nokogiri/ffi/structs/xml_sax_handler.rb +51 -0
  112. data/lib/nokogiri/ffi/structs/xml_sax_push_parser_context.rb +15 -0
  113. data/lib/nokogiri/ffi/structs/xml_schema.rb +13 -0
  114. data/lib/nokogiri/ffi/structs/xml_syntax_error.rb +31 -0
  115. data/lib/nokogiri/ffi/structs/xml_text_reader.rb +12 -0
  116. data/lib/nokogiri/ffi/structs/xml_xpath_context.rb +37 -0
  117. data/lib/nokogiri/ffi/structs/xml_xpath_object.rb +35 -0
  118. data/lib/nokogiri/ffi/structs/xml_xpath_parser_context.rb +20 -0
  119. data/lib/nokogiri/ffi/structs/xslt_stylesheet.rb +13 -0
  120. data/lib/nokogiri/ffi/xml/attr.rb +41 -0
  121. data/lib/nokogiri/ffi/xml/attribute_decl.rb +27 -0
  122. data/lib/nokogiri/ffi/xml/cdata.rb +19 -0
  123. data/lib/nokogiri/ffi/xml/comment.rb +18 -0
  124. data/lib/nokogiri/ffi/xml/document.rb +135 -0
  125. data/lib/nokogiri/ffi/xml/document_fragment.rb +21 -0
  126. data/lib/nokogiri/ffi/xml/dtd.rb +69 -0
  127. data/lib/nokogiri/ffi/xml/element_content.rb +43 -0
  128. data/lib/nokogiri/ffi/xml/element_decl.rb +19 -0
  129. data/lib/nokogiri/ffi/xml/entity_decl.rb +27 -0
  130. data/lib/nokogiri/ffi/xml/entity_reference.rb +19 -0
  131. data/lib/nokogiri/ffi/xml/namespace.rb +44 -0
  132. data/lib/nokogiri/ffi/xml/node.rb +444 -0
  133. data/lib/nokogiri/ffi/xml/node_set.rb +133 -0
  134. data/lib/nokogiri/ffi/xml/processing_instruction.rb +20 -0
  135. data/lib/nokogiri/ffi/xml/reader.rb +227 -0
  136. data/lib/nokogiri/ffi/xml/relax_ng.rb +85 -0
  137. data/lib/nokogiri/ffi/xml/sax/parser.rb +142 -0
  138. data/lib/nokogiri/ffi/xml/sax/parser_context.rb +67 -0
  139. data/lib/nokogiri/ffi/xml/sax/push_parser.rb +39 -0
  140. data/lib/nokogiri/ffi/xml/schema.rb +92 -0
  141. data/lib/nokogiri/ffi/xml/syntax_error.rb +91 -0
  142. data/lib/nokogiri/ffi/xml/text.rb +18 -0
  143. data/lib/nokogiri/ffi/xml/xpath.rb +19 -0
  144. data/lib/nokogiri/ffi/xml/xpath_context.rb +135 -0
  145. data/lib/nokogiri/ffi/xslt/stylesheet.rb +47 -0
  146. data/lib/nokogiri/html.rb +35 -0
  147. data/lib/nokogiri/html/builder.rb +35 -0
  148. data/lib/nokogiri/html/document.rb +88 -0
  149. data/lib/nokogiri/html/document_fragment.rb +15 -0
  150. data/lib/nokogiri/html/element_description.rb +23 -0
  151. data/lib/nokogiri/html/entity_lookup.rb +13 -0
  152. data/lib/nokogiri/html/sax/parser.rb +48 -0
  153. data/lib/nokogiri/html/sax/parser_context.rb +16 -0
  154. data/lib/nokogiri/syntax_error.rb +4 -0
  155. data/lib/nokogiri/version.rb +33 -0
  156. data/lib/nokogiri/version_warning.rb +11 -0
  157. data/lib/nokogiri/xml.rb +67 -0
  158. data/lib/nokogiri/xml/attr.rb +14 -0
  159. data/lib/nokogiri/xml/attribute_decl.rb +18 -0
  160. data/lib/nokogiri/xml/builder.rb +405 -0
  161. data/lib/nokogiri/xml/cdata.rb +11 -0
  162. data/lib/nokogiri/xml/character_data.rb +7 -0
  163. data/lib/nokogiri/xml/document.rb +131 -0
  164. data/lib/nokogiri/xml/document_fragment.rb +73 -0
  165. data/lib/nokogiri/xml/dtd.rb +11 -0
  166. data/lib/nokogiri/xml/element_content.rb +36 -0
  167. data/lib/nokogiri/xml/element_decl.rb +13 -0
  168. data/lib/nokogiri/xml/entity_decl.rb +15 -0
  169. data/lib/nokogiri/xml/fragment_handler.rb +73 -0
  170. data/lib/nokogiri/xml/namespace.rb +13 -0
  171. data/lib/nokogiri/xml/node.rb +665 -0
  172. data/lib/nokogiri/xml/node/save_options.rb +42 -0
  173. data/lib/nokogiri/xml/node_set.rb +307 -0
  174. data/lib/nokogiri/xml/notation.rb +6 -0
  175. data/lib/nokogiri/xml/parse_options.rb +85 -0
  176. data/lib/nokogiri/xml/pp.rb +2 -0
  177. data/lib/nokogiri/xml/pp/character_data.rb +18 -0
  178. data/lib/nokogiri/xml/pp/node.rb +56 -0
  179. data/lib/nokogiri/xml/processing_instruction.rb +8 -0
  180. data/lib/nokogiri/xml/reader.rb +74 -0
  181. data/lib/nokogiri/xml/relax_ng.rb +32 -0
  182. data/lib/nokogiri/xml/sax.rb +4 -0
  183. data/lib/nokogiri/xml/sax/document.rb +160 -0
  184. data/lib/nokogiri/xml/sax/parser.rb +115 -0
  185. data/lib/nokogiri/xml/sax/parser_context.rb +16 -0
  186. data/lib/nokogiri/xml/sax/push_parser.rb +60 -0
  187. data/lib/nokogiri/xml/schema.rb +61 -0
  188. data/lib/nokogiri/xml/syntax_error.rb +38 -0
  189. data/lib/nokogiri/xml/xpath.rb +10 -0
  190. data/lib/nokogiri/xml/xpath/syntax_error.rb +8 -0
  191. data/lib/nokogiri/xml/xpath_context.rb +16 -0
  192. data/lib/nokogiri/xslt.rb +48 -0
  193. data/lib/nokogiri/xslt/stylesheet.rb +25 -0
  194. data/lib/xsd/xmlparser/nokogiri.rb +71 -0
  195. data/tasks/test.rb +100 -0
  196. data/test/css/test_nthiness.rb +159 -0
  197. data/test/css/test_parser.rb +277 -0
  198. data/test/css/test_tokenizer.rb +183 -0
  199. data/test/css/test_xpath_visitor.rb +76 -0
  200. data/test/ffi/test_document.rb +35 -0
  201. data/test/files/2ch.html +108 -0
  202. data/test/files/address_book.rlx +12 -0
  203. data/test/files/address_book.xml +10 -0
  204. data/test/files/bar/bar.xsd +4 -0
  205. data/test/files/dont_hurt_em_why.xml +422 -0
  206. data/test/files/exslt.xml +8 -0
  207. data/test/files/exslt.xslt +35 -0
  208. data/test/files/foo/foo.xsd +4 -0
  209. data/test/files/po.xml +32 -0
  210. data/test/files/po.xsd +66 -0
  211. data/test/files/shift_jis.html +10 -0
  212. data/test/files/shift_jis.xml +5 -0
  213. data/test/files/snuggles.xml +3 -0
  214. data/test/files/staff.dtd +10 -0
  215. data/test/files/staff.xml +59 -0
  216. data/test/files/staff.xslt +32 -0
  217. data/test/files/tlm.html +850 -0
  218. data/test/files/valid_bar.xml +2 -0
  219. data/test/helper.rb +136 -0
  220. data/test/html/sax/test_parser.rb +64 -0
  221. data/test/html/sax/test_parser_context.rb +48 -0
  222. data/test/html/test_builder.rb +164 -0
  223. data/test/html/test_document.rb +390 -0
  224. data/test/html/test_document_encoding.rb +77 -0
  225. data/test/html/test_document_fragment.rb +142 -0
  226. data/test/html/test_element_description.rb +94 -0
  227. data/test/html/test_named_characters.rb +14 -0
  228. data/test/html/test_node.rb +228 -0
  229. data/test/html/test_node_encoding.rb +27 -0
  230. data/test/test_convert_xpath.rb +135 -0
  231. data/test/test_css_cache.rb +45 -0
  232. data/test/test_gc.rb +15 -0
  233. data/test/test_memory_leak.rb +77 -0
  234. data/test/test_nokogiri.rb +138 -0
  235. data/test/test_reader.rb +358 -0
  236. data/test/test_xslt_transforms.rb +131 -0
  237. data/test/xml/node/test_save_options.rb +20 -0
  238. data/test/xml/node/test_subclass.rb +44 -0
  239. data/test/xml/sax/test_parser.rb +307 -0
  240. data/test/xml/sax/test_parser_context.rb +56 -0
  241. data/test/xml/sax/test_push_parser.rb +106 -0
  242. data/test/xml/test_attr.rb +38 -0
  243. data/test/xml/test_attribute_decl.rb +82 -0
  244. data/test/xml/test_builder.rb +167 -0
  245. data/test/xml/test_cdata.rb +38 -0
  246. data/test/xml/test_comment.rb +29 -0
  247. data/test/xml/test_document.rb +607 -0
  248. data/test/xml/test_document_encoding.rb +26 -0
  249. data/test/xml/test_document_fragment.rb +144 -0
  250. data/test/xml/test_dtd.rb +82 -0
  251. data/test/xml/test_dtd_encoding.rb +33 -0
  252. data/test/xml/test_element_content.rb +56 -0
  253. data/test/xml/test_element_decl.rb +73 -0
  254. data/test/xml/test_entity_decl.rb +83 -0
  255. data/test/xml/test_entity_reference.rb +21 -0
  256. data/test/xml/test_namespace.rb +68 -0
  257. data/test/xml/test_node.rb +889 -0
  258. data/test/xml/test_node_attributes.rb +34 -0
  259. data/test/xml/test_node_encoding.rb +107 -0
  260. data/test/xml/test_node_set.rb +531 -0
  261. data/test/xml/test_parse_options.rb +52 -0
  262. data/test/xml/test_processing_instruction.rb +30 -0
  263. data/test/xml/test_reader_encoding.rb +126 -0
  264. data/test/xml/test_relax_ng.rb +60 -0
  265. data/test/xml/test_schema.rb +89 -0
  266. data/test/xml/test_syntax_error.rb +27 -0
  267. data/test/xml/test_text.rb +30 -0
  268. data/test/xml/test_unparented_node.rb +381 -0
  269. data/test/xml/test_xpath.rb +106 -0
  270. metadata +428 -0
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0"?>
2
+ <root>
3
+ <max>
4
+ <value>1</value>
5
+ <value>3</value>
6
+ <value>2</value>
7
+ </max>
8
+ </root>
@@ -0,0 +1,35 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1"?>
2
+
3
+ <xsl:stylesheet version="1.0"
4
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
5
+ xmlns:func="http://exslt.org/functions"
6
+ xmlns:my="urn:my-functions"
7
+ xmlns:date="http://exslt.org/dates-and-times"
8
+ xmlns:math="http://exslt.org/math"
9
+ extension-element-prefixes="func date"
10
+ >
11
+
12
+ <xsl:param name="p1"/>
13
+ <xsl:param name="p2"/>
14
+ <xsl:param name="p3"/>
15
+ <xsl:param name="p4"/>
16
+
17
+ <xsl:template match="/">
18
+ <root>
19
+ <function><xsl:value-of select="my:func()"/></function>
20
+ <date><xsl:value-of select="date:date()"/></date>
21
+ <max><xsl:value-of select="math:max(//max/value)"/></max>
22
+ <params>
23
+ <p1><xsl:value-of select="$p1"/></p1>
24
+ <p2><xsl:value-of select="$p2"/></p2>
25
+ <p3><xsl:value-of select="$p3"/></p3>
26
+ <p4><xsl:value-of select="$p4"/></p4>
27
+ </params>
28
+ </root>
29
+ </xsl:template>
30
+
31
+ <func:function name="my:func">
32
+ <func:result select="'func-result'"/>
33
+ </func:function>
34
+
35
+ </xsl:stylesheet>
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
3
+ <xsd:include schemaLocation="../bar/bar.xsd"/>
4
+ </xsd:schema>
data/test/files/po.xml ADDED
@@ -0,0 +1,32 @@
1
+ <?xml version="1.0"?>
2
+ <purchaseOrder orderDate="1999-10-20">
3
+ <shipTo country="US">
4
+ <name>Alice Smith</name>
5
+ <street>123 Maple Street</street>
6
+ <city>Mill Valley</city>
7
+ <state>CA</state>
8
+ <zip>90952</zip>
9
+ </shipTo>
10
+ <billTo country="US">
11
+ <name>Robert Smith</name>
12
+ <street>8 Oak Avenue</street>
13
+ <city>Old Town</city>
14
+ <state>PA</state>
15
+ <zip>95819</zip>
16
+ </billTo>
17
+ <comment>Hurry, my lawn is going wild!</comment>
18
+ <items>
19
+ <item partNum="872-AA">
20
+ <productName>Lawnmower</productName>
21
+ <quantity>1</quantity>
22
+ <USPrice>148.95</USPrice>
23
+ <comment>Confirm this is electric</comment>
24
+ </item>
25
+ <item partNum="926-AA">
26
+ <productName>Baby Monitor</productName>
27
+ <quantity>1</quantity>
28
+ <USPrice>39.98</USPrice>
29
+ <shipDate>1999-05-21</shipDate>
30
+ </item>
31
+ </items>
32
+ </purchaseOrder>
data/test/files/po.xsd ADDED
@@ -0,0 +1,66 @@
1
+ <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
2
+
3
+ <xsd:annotation>
4
+ <xsd:documentation xml:lang="en">
5
+ Purchase order schema for Example.com.
6
+ Copyright 2000 Example.com. All rights reserved.
7
+ </xsd:documentation>
8
+ </xsd:annotation>
9
+
10
+ <xsd:element name="purchaseOrder" type="PurchaseOrderType"/>
11
+
12
+ <xsd:element name="comment" type="xsd:string"/>
13
+
14
+ <xsd:complexType name="PurchaseOrderType">
15
+ <xsd:sequence>
16
+ <xsd:element name="shipTo" type="USAddress"/>
17
+ <xsd:element name="billTo" type="USAddress"/>
18
+ <xsd:element ref="comment" minOccurs="0"/>
19
+ <xsd:element name="items" type="Items"/>
20
+ </xsd:sequence>
21
+ <xsd:attribute name="orderDate" type="xsd:date"/>
22
+ </xsd:complexType>
23
+
24
+ <xsd:complexType name="USAddress">
25
+ <xsd:sequence>
26
+ <xsd:element name="name" type="xsd:string"/>
27
+ <xsd:element name="street" type="xsd:string"/>
28
+ <xsd:element name="city" type="xsd:string"/>
29
+ <xsd:element name="state" type="xsd:string"/>
30
+ <xsd:element name="zip" type="xsd:decimal"/>
31
+ </xsd:sequence>
32
+ <xsd:attribute name="country" type="xsd:NMTOKEN"
33
+ fixed="US"/>
34
+ </xsd:complexType>
35
+
36
+ <xsd:complexType name="Items">
37
+ <xsd:sequence>
38
+ <xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
39
+ <xsd:complexType>
40
+ <xsd:sequence>
41
+ <xsd:element name="productName" type="xsd:string"/>
42
+ <xsd:element name="quantity">
43
+ <xsd:simpleType>
44
+ <xsd:restriction base="xsd:positiveInteger">
45
+ <xsd:maxExclusive value="100"/>
46
+ </xsd:restriction>
47
+ </xsd:simpleType>
48
+ </xsd:element>
49
+ <xsd:element name="USPrice" type="xsd:decimal"/>
50
+ <xsd:element ref="comment" minOccurs="0"/>
51
+ <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
52
+ </xsd:sequence>
53
+ <xsd:attribute name="partNum" type="SKU" use="required"/>
54
+ </xsd:complexType>
55
+ </xsd:element>
56
+ </xsd:sequence>
57
+ </xsd:complexType>
58
+
59
+ <!-- Stock Keeping Unit, a code for identifying products -->
60
+ <xsd:simpleType name="SKU">
61
+ <xsd:restriction base="xsd:string">
62
+ <xsd:pattern value="\d{3}-[A-Z]{2}"/>
63
+ </xsd:restriction>
64
+ </xsd:simpleType>
65
+
66
+ </xsd:schema>
@@ -0,0 +1,10 @@
1
+ <html>
2
+ <head>
3
+ <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
4
+ <title>����ɂ��́I</title>
5
+ </head>
6
+ <body>
7
+ <h1>This is a Shift_JIS File</h1>
8
+ <h2>����ɂ��́I</h2>
9
+ </body>
10
+ </html>
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="Shift_JIS"?>
2
+ <root>
3
+ <hi>This is a Shift_JIS File</hi>
4
+ <hi_again>����ɂ���</hi_again>
5
+ </root>
@@ -0,0 +1,3 @@
1
+ <x xmlns:tenderlove='http://tenderlovemaking.com/'>
2
+ <tenderlove:foo awesome='true'>snuggles!</tenderlove:foo>
3
+ </x>
@@ -0,0 +1,10 @@
1
+ <!ENTITY ent1 "es">
2
+ <!ENTITY ent2 "1900 Dallas Road">
3
+ <!ENTITY ent3 "Texas">
4
+ <!ENTITY ent4 "<entElement domestic='Yes'>Element data</entElement><?PItarget PIdata?>">
5
+ <!ENTITY ent5 PUBLIC "entityURI" "entityFile" NDATA notation1>
6
+ <!ENTITY ent1 "This entity should be discarded">
7
+ <!ELEMENT br EMPTY>
8
+ <!ATTLIST br width CDATA "0">
9
+ <!NOTATION notation1 PUBLIC "notation1File">
10
+ <!NOTATION notation2 SYSTEM "notation2File">
@@ -0,0 +1,59 @@
1
+ <?xml version="1.0"?><?TEST-STYLE PIDATA?>
2
+ <!DOCTYPE staff SYSTEM "staff.dtd" [
3
+ <!ENTITY ent1 "es">
4
+ <!ENTITY ent2 "1900 Dallas Road">
5
+ <!ENTITY ent3 "Texas">
6
+ <!ENTITY ent4 "<entElement domestic='Yes'>Element data</entElement><?PItarget PIdata?>">
7
+ <!ENTITY ent5 PUBLIC "entityURI" "entityFile" NDATA notation1>
8
+ <!ENTITY ent1 "This entity should be discarded">
9
+ <!ELEMENT br EMPTY>
10
+ <!ATTLIST br width CDATA "0">
11
+ <!NOTATION notation1 PUBLIC "notation1File">
12
+ <!NOTATION notation2 SYSTEM "notation2File">
13
+ ]>
14
+ <!-- This is comment number 1.-->
15
+ <staff>
16
+ <employee>
17
+ <employeeId>EMP0001</employeeId>
18
+ <name>Margaret Martin</name>
19
+ <position>Accountant</position>
20
+ <salary>56,000</salary>
21
+ <gender>Female</gender>
22
+ <address domestic="Yes">1230 North Ave. Dallas, Texas 98551</address>
23
+ </employee>
24
+ <employee>
25
+ <employeeId>EMP0002</employeeId>
26
+ <name>Martha Raynolds<![CDATA[This is a CDATASection with EntityReference number 2 &ent2;]]>
27
+ <![CDATA[This is an adjacent CDATASection with a reference to a tab &tab;]]></name>
28
+ <position>Secretary</position>
29
+ <salary>35,000</salary>
30
+ <gender>Female</gender>
31
+ <address domestic="Yes" street="Yes">&ent2; Dallas, &ent3;
32
+ 98554</address>
33
+ </employee>
34
+ <employee>
35
+ <employeeId>EMP0003</employeeId>
36
+ <name>Roger
37
+ Jones</name>
38
+ <position>Department Manager</position>
39
+ <salary>100,000</salary>
40
+ <gender>&ent4;</gender>
41
+ <address domestic="Yes" street="No">PO Box 27 Irving, texas 98553</address>
42
+ </employee>
43
+ <employee>
44
+ <employeeId>EMP0004</employeeId>
45
+ <name>Jeny Oconnor</name>
46
+ <position>Personnel Director</position>
47
+ <salary>95,000</salary>
48
+ <gender>Female</gender>
49
+ <address domestic="Yes" street="Y&ent1;">27 South Road. Dallas, Texas 98556</address>
50
+ </employee>
51
+ <employee>
52
+ <employeeId>EMP0005</employeeId>
53
+ <name>Robert Myers</name>
54
+ <position>Computer Specialist</position>
55
+ <salary>90,000</salary>
56
+ <gender>male</gender>
57
+ <address street="Yes">1821 Nordic. Road, Irving Texas 98558</address>
58
+ </employee>
59
+ </staff>
@@ -0,0 +1,32 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1"?>
2
+
3
+ <xsl:stylesheet version="1.0"
4
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
5
+
6
+ <xsl:param name="title"/>
7
+
8
+ <xsl:template match="/">
9
+ <html>
10
+ <body>
11
+ <h1><xsl:value-of select="$title"/></h1>
12
+ <table border="1">
13
+ <tr bgcolor="#9acd32">
14
+ <th align="left">Employee ID</th>
15
+ <th align="left">Name</th>
16
+ <th align="left">Position</th>
17
+ <th align="left">Salary</th>
18
+ </tr>
19
+ <xsl:for-each select="staff/employee">
20
+ <tr>
21
+ <td><xsl:value-of select="employeeId"/></td>
22
+ <td><xsl:value-of select="name"/></td>
23
+ <td><xsl:value-of select="position"/></td>
24
+ <td><xsl:value-of select="salary"/></td>
25
+ </tr>
26
+ </xsl:for-each>
27
+ </table>
28
+ </body>
29
+ </html>
30
+ </xsl:template>
31
+
32
+ </xsl:stylesheet>
@@ -0,0 +1,850 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml">
3
+ <head profile="http://gmpg.org/xfn/11">
4
+
5
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
6
+
7
+ <title>Tender Lovemaking </title>
8
+
9
+ <meta name="generator" content="WordPress 2.6" /> <!-- leave this for stats -->
10
+
11
+ <link rel="stylesheet" href="http://tenderlovemaking.com/wp-content/themes/cherry-berry-pr/style.css" type="text/css" media="screen" />
12
+ <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://tenderlovemaking.com/feed/" />
13
+ <link rel="alternate" type="text/xml" title="RSS .92" href="http://tenderlovemaking.com/feed/rss/" />
14
+ <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="http://tenderlovemaking.com/feed/atom/" />
15
+ <link rel="pingback" href="http://tenderlovemaking.com/xmlrpc.php" />
16
+
17
+ <link rel='archives' title='July 2008' href='http://tenderlovemaking.com/2008/07/' />
18
+ <link rel='archives' title='June 2008' href='http://tenderlovemaking.com/2008/06/' />
19
+ <link rel='archives' title='May 2008' href='http://tenderlovemaking.com/2008/05/' />
20
+ <link rel='archives' title='April 2008' href='http://tenderlovemaking.com/2008/04/' />
21
+ <link rel='archives' title='March 2008' href='http://tenderlovemaking.com/2008/03/' />
22
+ <link rel='archives' title='February 2008' href='http://tenderlovemaking.com/2008/02/' />
23
+ <link rel='archives' title='January 2008' href='http://tenderlovemaking.com/2008/01/' />
24
+ <link rel='archives' title='December 2007' href='http://tenderlovemaking.com/2007/12/' />
25
+ <link rel='archives' title='November 2007' href='http://tenderlovemaking.com/2007/11/' />
26
+ <link rel='archives' title='October 2007' href='http://tenderlovemaking.com/2007/10/' />
27
+ <link rel='archives' title='September 2007' href='http://tenderlovemaking.com/2007/09/' />
28
+ <link rel='archives' title='August 2007' href='http://tenderlovemaking.com/2007/08/' />
29
+ <link rel='archives' title='July 2007' href='http://tenderlovemaking.com/2007/07/' />
30
+ <link rel='archives' title='June 2007' href='http://tenderlovemaking.com/2007/06/' />
31
+ <link rel='archives' title='May 2007' href='http://tenderlovemaking.com/2007/05/' />
32
+ <link rel='archives' title='April 2007' href='http://tenderlovemaking.com/2007/04/' />
33
+ <link rel='archives' title='March 2007' href='http://tenderlovemaking.com/2007/03/' />
34
+ <link rel='archives' title='February 2007' href='http://tenderlovemaking.com/2007/02/' />
35
+ <link rel='archives' title='January 2007' href='http://tenderlovemaking.com/2007/01/' />
36
+ <link rel='archives' title='December 2006' href='http://tenderlovemaking.com/2006/12/' />
37
+ <link rel='archives' title='November 2006' href='http://tenderlovemaking.com/2006/11/' />
38
+ <link rel='archives' title='October 2006' href='http://tenderlovemaking.com/2006/10/' />
39
+ <link rel='archives' title='September 2006' href='http://tenderlovemaking.com/2006/09/' />
40
+ <link rel='archives' title='August 2006' href='http://tenderlovemaking.com/2006/08/' />
41
+ <link rel='archives' title='July 2006' href='http://tenderlovemaking.com/2006/07/' />
42
+ <link rel='archives' title='June 2006' href='http://tenderlovemaking.com/2006/06/' />
43
+ <link rel='archives' title='May 2006' href='http://tenderlovemaking.com/2006/05/' />
44
+ <link rel="stylesheet" href="http://tenderlovemaking.com/wp-content/plugins/codesnippet/codesnippet.css" type="text/css" />
45
+ <style type="text/css">
46
+ .codesnip-container {border:1px solid #ccc; background:#eee; padding: 5px;margin:10px;}
47
+ </style>
48
+ <link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://tenderlovemaking.com/xmlrpc.php?rsd" />
49
+ <link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://tenderlovemaking.com/wp-includes/wlwmanifest.xml" />
50
+ <meta name="generator" content="WordPress 2.6" />
51
+
52
+ <link rel="stylesheet" type="text/css" href="http://tenderlovemaking.com/wp-content/plugins/spell_checker/spell_checker.css" />
53
+ <script src="http://tenderlovemaking.com/wp-content/plugins/spell_checker/spell_checker.js" type="text/javascript"></script>
54
+ <script src="http://tenderlovemaking.com/wp-content/plugins/spell_checker/cpaint.inc.js" type="text/javascript"></script>
55
+
56
+ <link rel="stylesheet" type="text/css" href="http://tenderlovemaking.com/wp-content/plugins/spell_checker/spellchecker.css" />
57
+ <script type="text/javascript" src="http://tenderlovemaking.com/wp-content/plugins/spell_checker/spellchecker.js"></script>
58
+
59
+
60
+ </head>
61
+
62
+ <body>
63
+
64
+ <div id="wrap">
65
+
66
+ <div id="header">
67
+ <h1><a href="http://tenderlovemaking.com">Tender Lovemaking</a></h1>
68
+ <small>The act of making love, tenderly.</small>
69
+ </div>
70
+
71
+ <!-- unComment only when you want a navigation bar like my site
72
+
73
+ how to use?
74
+ <a href="link">Linkname</a> &bull; <a href="link2">Linkname2</a> &bull;
75
+
76
+ just remember link<space>&bull;<space>link
77
+
78
+ try not to exceeed 1 line, it may messed up.
79
+
80
+ simple rite? =D
81
+
82
+ <div id="navigation">
83
+ <a href="#">Link 1</a> &bull;
84
+ <a href="#">Link 2</a> &bull;
85
+ <a href="#">Link 3</a> &bull;
86
+ <a href="#">Link 4</a> &bull;
87
+ <a href="#">And so on...</a>
88
+ </div>
89
+ -->
90
+
91
+ <!-- end of header --><div id="body">
92
+
93
+
94
+ <div class="post" id="post-146">
95
+ <h2 class="postitle"><a href="http://tenderlovemaking.com/2008/07/08/back-home/" rel="bookmark" title="Permanent Link to Back Home!">Back Home!</a></h2>
96
+ <p class="postmeta">Tuesday, 8 July 2008 @ 11:34am &bull; <a href="http://tenderlovemaking.com/category/life/" title="View all posts in life" rel="category tag">life</a></p>
97
+
98
+ <div class="postentry">
99
+ <p>I'm finally back home. I went to Japan a few weeks ago for vacation, and I also spoke at <a href="http://jp.rubyist.net/RubyKaigi2008/" onclick="javascript:urchinTracker ('/outbound/article/jp.rubyist.net');">Ruby Kaigi 2008</a>. Ruby Kaigi was so much fun! I've been studying Japanese for a little over a year, but I've never been to Japan. It was exciting and fun to talk to people, and I made a bunch of new Japanese friends. I'd really like to thank Leonard Chin for helping out at the Kaigi. My language skills aren't good enough, and he was kind enough to fill in the gaps. Thank you!</p>
100
+ <p>While I was in Japan, I noticed <a href="http://en.wikipedia.org/wiki/QR_Code" onclick="javascript:urchinTracker ('/outbound/article/en.wikipedia.org');">QR Codes</a> everywhere. QR Codes are basically really awesome bar codes. They can hold much more information in a smaller amount of space. They can be easily decoded from images taken with digital cameras. They have these codes everywhere in Japan, and the idea is that people can take a photo with the camera on their cell phone, then the phone decodes the QR Code. I believe most of the QR codes contain information about the company, or possibly a URL to the company's website.</p>
101
+ <p>The company that created the format says that the format is open, but unfortunately I have to pay for the spec. I can download the spec in Japanese for free, but my Japanese isn't that good! So unfortunately I'm stuck with either the <a href="http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=43655" onclick="javascript:urchinTracker ('/outbound/article/www.iso.org');">ISO spec</a> (which is over $200) or the <a href="https://www.aimglobal.org/estore/ProductDetails.aspx?ProductID=31" onclick="javascript:urchinTracker ('/outbound/article/www.aimglobal.org');">AIM spec</a> ($85). I don't understand why they are so expensive..... I think I'll buy the AIM one, and hope that it is the same as the ISO one.</p>
102
+ </div>
103
+
104
+ <p class="postfeedback">
105
+ Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> &bull;
106
+ <a href="http://tenderlovemaking.com/2008/07/08/back-home/" rel="bookmark" title="Permanent Link to Back Home!">Permalink</a> &bull;
107
+ <a href="http://tenderlovemaking.com/2008/07/08/back-home/#comments">Comments (1)</a> &bull;
108
+ <a href="http://tenderlovemaking.com/2008/07/08/back-home/#respond" title="Leave your Comment">Leave your Comment &raquo;</a>
109
+ </p>
110
+
111
+ <!--
112
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
113
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
114
+ xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
115
+ <rdf:Description rdf:about="http://tenderlovemaking.com/2008/07/08/back-home/"
116
+ dc:identifier="http://tenderlovemaking.com/2008/07/08/back-home/"
117
+ dc:title="Back Home!"
118
+ trackback:ping="http://tenderlovemaking.com/2008/07/08/back-home/trackback/" />
119
+ </rdf:RDF> -->
120
+
121
+ </div>
122
+
123
+
124
+ <div class="post" id="post-141">
125
+ <h2 class="postitle"><a href="http://tenderlovemaking.com/2008/06/06/meow-meow-meow-meow-meow/" rel="bookmark" title="Permanent Link to Meow meow meow meow meow">Meow meow meow meow meow</a></h2>
126
+ <p class="postmeta">Friday, 6 June 2008 @ 12:56pm &bull; <a href="http://tenderlovemaking.com/category/computadora/" title="View all posts in computadora" rel="category tag">computadora</a>, <a href="http://tenderlovemaking.com/category/computadora/meow/" title="View all posts in meow" rel="category tag">meow</a></p>
127
+
128
+ <div class="postentry">
129
+ <p>The other day I wrote an app called <a href="http://github.com/aaronp/dejour/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">dejour</a> to give me growl notifications from <a href="http://github.com/chad/gitjour/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">all</a> <a href="http://github.com/evanphx/gemjour/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">the</a> <a href="http://github.com/jbarnette/pastejour/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">*jour</a> gems out there. I used Eric Hodel's awesome <a href="http://segment7.net/projects/ruby/growl/" onclick="javascript:urchinTracker ('/outbound/article/segment7.net');">ruby-growl</a> library. Unfortunately it does all communications over the interweb, so you have to tweak some knobs in Growl to get it to work. I stumbled across a ruby/cocoa example using Growl, fixed it up, and released a gem called "Meow".</p>
130
+ <p>Meow lets you post notifications to your local machine without adjusting Growl. If you're on OS X 10.5, just do:</p>
131
+ <div class="codesnip-container" >$ gem install meow</div>
132
+ <p>Then you can do this:</p>
133
+ <div class="codesnip-container" >$ ruby -r rubygems -e'require "meow"; Meow.notify("meow", "meow", "meow")'</div>
134
+ <p>No growl tweaks required! Here is a code sample that is a little more explanatory:</p>
135
+ <div class="codesnip-container" >
136
+ <div class="codesnip" style="font-family: monospace;"><span class="kw3">require</span> 'rubygems'<br />
137
+ <span class="kw3">require</span> 'meow'</p>
138
+ <p>meep = Meow.<span class="me1">new</span><span class="br0">&#40;</span>'My Application Name'<span class="br0">&#41;</span><br />
139
+ meep.<span class="me1">notify</span><span class="br0">&#40;</span>'Message Title', 'Message Description'<span class="br0">&#41;</span></div>
140
+ </div>
141
+ <p>Be sure to check out <a href="http://meow.rubyforge.org/" onclick="javascript:urchinTracker ('/outbound/article/meow.rubyforge.org');">the documentation</a>.</p>
142
+ </div>
143
+
144
+ <p class="postfeedback">
145
+ Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> &bull;
146
+ <a href="http://tenderlovemaking.com/2008/06/06/meow-meow-meow-meow-meow/" rel="bookmark" title="Permanent Link to Meow meow meow meow meow">Permalink</a> &bull;
147
+ <a href="http://tenderlovemaking.com/2008/06/06/meow-meow-meow-meow-meow/#comments">Comments (4)</a> &bull;
148
+ <a href="http://tenderlovemaking.com/2008/06/06/meow-meow-meow-meow-meow/#respond" title="Leave your Comment">Leave your Comment &raquo;</a>
149
+ </p>
150
+
151
+ <!--
152
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
153
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
154
+ xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
155
+ <rdf:Description rdf:about="http://tenderlovemaking.com/2008/06/06/meow-meow-meow-meow-meow/"
156
+ dc:identifier="http://tenderlovemaking.com/2008/06/06/meow-meow-meow-meow-meow/"
157
+ dc:title="Meow meow meow meow meow"
158
+ trackback:ping="http://tenderlovemaking.com/2008/06/06/meow-meow-meow-meow-meow/trackback/" />
159
+ </rdf:RDF> -->
160
+
161
+ </div>
162
+
163
+
164
+ <div class="post" id="post-139">
165
+ <h2 class="postitle"><a href="http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/" rel="bookmark" title="Permanent Link to Write your Rails view in&#8230;&#8230;. JavaScript?">Write your Rails view in&#8230;&#8230;. JavaScript?</a></h2>
166
+ <p class="postmeta">Tuesday, 6 May 2008 @ 11:33am &bull; <a href="http://tenderlovemaking.com/category/computadora/johnson/" title="View all posts in johnson" rel="category tag">johnson</a>, <a href="http://tenderlovemaking.com/category/rails/" title="View all posts in rails" rel="category tag">rails</a></p>
167
+
168
+ <div class="postentry">
169
+ <p>In my <a href="/2008/04/23/take-it-to-the-limit-one-more-time/">last post about Johnson</a>, I said that next time I would talk about the JavaScript parse tree that <a href="http://github.com/jbarnette/johnson/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">Johnson</a> provides. Well, I changed my mind. Sorry.</p>
170
+ <p>I want to write about a rails plugin that I added to Johnson. <a href="http://www.yehudakatz.com/" onclick="javascript:urchinTracker ('/outbound/article/www.yehudakatz.com');">Brohuda Katz</a> wrote an <a href="http://github.com/jbarnette/johnson/tree/master/js/johnson/template.js" onclick="javascript:urchinTracker ('/outbound/article/github.com');">ERb type parser in JavaScript</a>, and added it to the (yet to be released) Johnson distribution. With that in mind, and looking at the new template handlers in edge rails, I was able to throw together a rails plugin that allows me to use JavaScript in my rails view code.</p>
171
+ <p>Lets get to the code. Here is my controller:</p>
172
+ <div class="codesnip-container" >
173
+ <div class="codesnip" style="font-family: monospace;"><span class="kw1">class</span> JohnsonController &lt; ApplicationController<br />
174
+ &nbsp; <span class="kw1">def</span> index<br />
175
+ &nbsp; &nbsp; @users = User.<span class="me1">find</span><span class="br0">&#40;</span>:all<span class="br0">&#41;</span><br />
176
+ &nbsp; <span class="kw1">end</span><br />
177
+ <span class="kw1">end</span></div>
178
+ </div>
179
+ <p>And my EJS view (the file is named index.html.ejs):</p>
180
+ <div class="codesnip-container" >
181
+ <div class="codesnip" style="font-family: monospace;">&lt;% <span class="kw1">for</span><span class="br0">&#40;</span><span class="kw2">var</span> user in at.users<span class="br0">&#41;</span> <span class="br0">&#123;</span> %&gt;<br />
182
+ &nbsp; &lt;%= user.first_name<span class="br0">&#40;</span><span class="br0">&#41;</span> %&gt;&lt;br /&gt;<br />
183
+ &lt;% <span class="br0">&#125;</span> %&gt;</div>
184
+ </div>
185
+ <p>The johnson rails plugin puts controller instance variables in to a special javascript variable called "at". The "at" variable is actually a proxy to the controller, lazily fetching instance variables from the controller and importing those objects in to javascript land.</p>
186
+ <p>Lets take a look at the plugin, its only a few lines:</p>
187
+ <div class="codesnip-container" >
188
+ <div class="codesnip" style="font-family: monospace;"><span class="kw1">class</span> EJSHandler &lt; ActionView::TemplateHandler<br />
189
+ &nbsp; <span class="kw1">class</span> EJSProxy <span class="co1"># :nodoc:</span><br />
190
+ &nbsp; &nbsp; <span class="kw1">def</span> initialize<span class="br0">&#40;</span>controller<span class="br0">&#41;</span><br />
191
+ &nbsp; &nbsp; &nbsp; @controller = controller<br />
192
+ &nbsp; &nbsp; <span class="kw1">end</span></p>
193
+ <p>&nbsp; &nbsp; <span class="kw1">def</span> key?<span class="br0">&#40;</span>pooperty<span class="br0">&#41;</span><br />
194
+ &nbsp; &nbsp; &nbsp; @controller.<span class="me1">instance_variables</span>.<span class="kw1">include</span>?<span class="br0">&#40;</span><span class="st0">&quot;@#{pooperty}&quot;</span><span class="br0">&#41;</span><br />
195
+ &nbsp; &nbsp; <span class="kw1">end</span></p>
196
+ <p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#40;</span>pooperty<span class="br0">&#41;</span><br />
197
+ &nbsp; &nbsp; &nbsp; @controller.<span class="me1">instance_variable_get</span><span class="br0">&#40;</span><span class="st0">&quot;@#{pooperty}&quot;</span><span class="br0">&#41;</span><br />
198
+ &nbsp; &nbsp; <span class="kw1">end</span></p>
199
+ <p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="br0">&#91;</span><span class="br0">&#93;</span>=<span class="br0">&#40;</span>pooperty, value<span class="br0">&#41;</span><br />
200
+ &nbsp; &nbsp; &nbsp; @controller.<span class="me1">instance_variable_set</span><span class="br0">&#40;</span><span class="st0">&quot;@#{pooperty}&quot;</span>, value<span class="br0">&#41;</span><br />
201
+ &nbsp; &nbsp; <span class="kw1">end</span><br />
202
+ &nbsp; <span class="kw1">end</span></p>
203
+ <p>&nbsp; <span class="kw1">def</span> initialize<span class="br0">&#40;</span>view<span class="br0">&#41;</span><br />
204
+ &nbsp; &nbsp; @view = view<br />
205
+ &nbsp; <span class="kw1">end</span></p>
206
+ <p>&nbsp; <span class="kw1">def</span> render<span class="br0">&#40;</span>template<span class="br0">&#41;</span><br />
207
+ &nbsp; &nbsp; ctx = Johnson::Context.<span class="me1">new</span><br />
208
+ &nbsp; &nbsp; ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span>'Johnson.<span class="kw3">require</span><span class="br0">&#40;</span><span class="st0">&quot;johnson/template&quot;</span><span class="br0">&#41;</span>;'<span class="br0">&#41;</span><br />
209
+ &nbsp; &nbsp; ctx<span class="br0">&#91;</span>'template'<span class="br0">&#93;</span> = template.<span class="me1">source</span><br />
210
+ &nbsp; &nbsp; ctx<span class="br0">&#91;</span>'controller'<span class="br0">&#93;</span> = @view.<span class="me1">controller</span><br />
211
+ &nbsp; &nbsp; ctx<span class="br0">&#91;</span>'at'<span class="br0">&#93;</span> = EJSProxy.<span class="me1">new</span><span class="br0">&#40;</span>@view.<span class="me1">controller</span><span class="br0">&#41;</span></p>
212
+ <p>&nbsp; &nbsp; ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span>'Johnson.<span class="me1">templatize</span><span class="br0">&#40;</span>template<span class="br0">&#41;</span>.<span class="me1">call</span><span class="br0">&#40;</span>at<span class="br0">&#41;</span>'<span class="br0">&#41;</span><br />
213
+ &nbsp; <span class="kw1">end</span><br />
214
+ <span class="kw1">end</span></p>
215
+ <p>ActionView::Template.<span class="me1">register_template_handler</span><span class="br0">&#40;</span><span class="st0">&quot;ejs&quot;</span>, EJSHandler<span class="br0">&#41;</span></div>
216
+ </div>
217
+ <p>When the template gets rendered (the render method), I wrap the controller with an EJS proxy, then compile the template into a javascript function, and call that function. The "at" variable is set to the EJSProxy before executing the template, and all property accessing on the "at" variable is passed along to fetching instance variables from the controller.</p>
218
+ <p>Server side javascript coding in rails. Weird, eh?</p>
219
+ </div>
220
+
221
+ <p class="postfeedback">
222
+ Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> &bull;
223
+ <a href="http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/" rel="bookmark" title="Permanent Link to Write your Rails view in&#8230;&#8230;. JavaScript?">Permalink</a> &bull;
224
+ <a href="http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/#comments">Comments (7)</a> &bull;
225
+ <a href="http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/#respond" title="Leave your Comment">Leave your Comment &raquo;</a>
226
+ </p>
227
+
228
+ <!--
229
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
230
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
231
+ xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
232
+ <rdf:Description rdf:about="http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/"
233
+ dc:identifier="http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/"
234
+ dc:title="Write your Rails view in&#8230;&#8230;. JavaScript?"
235
+ trackback:ping="http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/trackback/" />
236
+ </rdf:RDF> -->
237
+
238
+ </div>
239
+
240
+
241
+ <div class="post" id="post-138">
242
+ <h2 class="postitle"><a href="http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/" rel="bookmark" title="Permanent Link to Take it to the limit one more time">Take it to the limit one more time</a></h2>
243
+ <p class="postmeta">Wednesday, 23 April 2008 @ 11:22am &bull; <a href="http://tenderlovemaking.com/category/computadora/" title="View all posts in computadora" rel="category tag">computadora</a>, <a href="http://tenderlovemaking.com/category/ecma/" title="View all posts in ecma" rel="category tag">ecma</a>, <a href="http://tenderlovemaking.com/category/computadora/johnson/" title="View all posts in johnson" rel="category tag">johnson</a>, <a href="http://tenderlovemaking.com/category/rkelly/" title="View all posts in rkelly" rel="category tag">rkelly</a></p>
244
+
245
+ <div class="postentry">
246
+ <p>Sup bros. I need to post in this thing more often. Yesterday, someone tipped over <a href="http://flickr.com/photos/aaronp/150189237/" onclick="javascript:urchinTracker ('/outbound/article/flickr.com');">my scooter</a> again. I'm getting kind of tired of that.</p>
247
+ <p>Anyway, its time for me to write about this. <a href="http://rubyforge.org/projects/rkelly/" onclick="javascript:urchinTracker ('/outbound/article/rubyforge.org');">RKelly</a> is pretty much dead. For the past few months, <a href="http://geeksomnia.com/" onclick="javascript:urchinTracker ('/outbound/article/geeksomnia.com');">John</a> and I have been working on RKelly's replacement called <a href="http://github.com/jbarnette/johnson/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">Johnson</a>. Basically we're now putting a ruby wrapper around <a href="http://www.mozilla.org/js/spidermonkey/" onclick="javascript:urchinTracker ('/outbound/article/www.mozilla.org');">Mozilla's Spidermonkey</a>. The project is coming along quite nicely. Ruby objects can be passed in to javascript land, and javascript objects can be passed back in to ruby land.</p>
248
+ <p>For example, we can define an alert function in our javascript context:</p>
249
+ <div class="codesnip-container" >
250
+ <div class="codesnip" style="font-family: monospace;"><span class="kw3">require</span> 'johnson'</p>
251
+ <p>ctx = Johnson::Context.<span class="me1">new</span><br />
252
+ ctx<span class="br0">&#91;</span>'alert'<span class="br0">&#93;</span> = <span class="kw3">lambda</span> <span class="br0">&#123;</span> |x| <span class="kw3">puts</span> x <span class="br0">&#125;</span><br />
253
+ ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span>'alert<span class="br0">&#40;</span><span class="st0">&quot;Hello world!&quot;</span><span class="br0">&#41;</span>;'<span class="br0">&#41;</span></div>
254
+ </div>
255
+ <p>Johnson::Context#evaluate will also return the last statement evaluated. We can evaluate an expression, and manipulate that expression in ruby land. For example, I'll create an object in javascript, return it to ruby land, then access a property of the javascript object:</p>
256
+ <div class="codesnip-container" >
257
+ <div class="codesnip" style="font-family: monospace;"><span class="kw3">require</span> 'johnson'</p>
258
+ <p>ctx = Johnson::Context.<span class="me1">new</span><br />
259
+ obj = ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span>'var foo = <span class="br0">&#123;</span> x: <span class="st0">&quot;hello world&quot;</span> <span class="br0">&#125;</span>; foo'<span class="br0">&#41;</span><br />
260
+ <span class="kw3">puts</span> obj.<span class="me1">x</span>&nbsp; <span class="co1"># =&gt; 'hello world' </span></div>
261
+ </div>
262
+ <p>We can even do the reverse by stuffing ruby objects in to the context:</p>
263
+ <div class="codesnip-container" >
264
+ <div class="codesnip" style="font-family: monospace;">A = Struct.<span class="me1">new</span><span class="br0">&#40;</span>:foo<span class="br0">&#41;</span></p>
265
+ <p>ctx = Johnson::Context.<span class="me1">new</span><br />
266
+ ctx<span class="br0">&#91;</span>'alert'<span class="br0">&#93;</span> = <span class="kw3">lambda</span> <span class="br0">&#123;</span> |x| <span class="kw3">puts</span> x <span class="br0">&#125;</span><br />
267
+ ctx<span class="br0">&#91;</span>'a'<span class="br0">&#93;</span> = A.<span class="me1">new</span><span class="br0">&#40;</span><span class="st0">&quot;bar&quot;</span><span class="br0">&#41;</span><br />
268
+ ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span>'alert<span class="br0">&#40;</span>a.<span class="me1">foo</span><span class="br0">&#41;</span>;'<span class="br0">&#41;</span> <span class="co1"># =&gt; 'bar' </span></div>
269
+ </div>
270
+ <p>But it gets better. We added a top level variable called "Ruby" that lets you access constants and globals from Ruby land. We can rewrite the previous example completely in javascript:</p>
271
+ <div class="codesnip-container" >
272
+ <div class="codesnip" style="font-family: monospace;">ctx = Johnson::Context.<span class="me1">new</span><br />
273
+ ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span><span class="st0">&quot;var x = new (new Ruby.Struct(Johnson.symbolize('foo')));&quot;</span><span class="br0">&#41;</span><br />
274
+ ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span><span class="st0">&quot;x.foo = 'bar'&quot;</span><span class="br0">&#41;</span><br />
275
+ <span class="kw3">puts</span> ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span>'x'<span class="br0">&#41;</span>.<span class="me1">foo</span> <span class="co1"># =&gt; 'bar'</span><br />
276
+ <span class="kw3">puts</span> ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span>'x'<span class="br0">&#41;</span>.<span class="kw1">class</span> <span class="co1"># =&gt; #&lt;Class:0x49714&gt; </span></div>
277
+ </div>
278
+ <p>Since the 'Ruby' constant delegates to Object, you can access any constant. Including ones you've defined yourself. We could, for example, look up a bunch of User records through rails:</p>
279
+ <div class="codesnip-container" >
280
+ <div class="codesnip" style="font-family: monospace;">ctx = Johnson::Context.<span class="me1">new</span><br />
281
+ ctx<span class="br0">&#91;</span>'alert'<span class="br0">&#93;</span> = <span class="kw3">lambda</span> <span class="br0">&#123;</span> |x| <span class="kw3">puts</span> x <span class="br0">&#125;</span><br />
282
+ ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span>&lt;&lt;-<span class="kw1">END</span><br />
283
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">for</span><span class="br0">&#40;</span>var user <span class="kw1">in</span> Ruby.<span class="me1">User</span>.<span class="me1">find</span><span class="br0">&#40;</span>Johnson.<span class="me1">symbolize</span><span class="br0">&#40;</span>'all'<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
284
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;alert<span class="br0">&#40;</span>user.<span class="me1">first_name</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
285
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#125;</span><br />
286
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">END</span><br />
287
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span></div>
288
+ </div>
289
+ <p>You might be wondering what this Johnson.symbolize business is about. Since Javascript doesn't have a concept of a symbol, we've created a helper to "mark" a string as a symbol and pass it back in to ruby land.</p>
290
+ <p>To conclude this update about my Johnson, I'd like to show off an interactive shell for Johnson (thanks to <a href="http://www.yehudakatz.com/" onclick="javascript:urchinTracker ('/outbound/article/www.yehudakatz.com');">Brohuda Katz</a>). Johnson has an interactive shell that lets you try things out in javascript land or ruby land, and let you quickly switch between the two. Typing 'js' will put in you the javascript shell, 'rb' will switch you to the ruby shell. In the ruby shell, you can use the 'cx' variable to get ahold of you javascript context:</p>
291
+ <div class="codesnip-container" >$ ruby -I lib bin/johnson<br />
292
+ js> var x = { foo: 'bar', hello: function() { return 'world' } };<br />
293
+ => nil<br />
294
+ js> rb<br />
295
+ rb> cx['x'].foo<br />
296
+ => "bar"<br />
297
+ rb> cx['x'].hello()<br />
298
+ => "world"<br />
299
+ rb></div>
300
+ <p>We aren't quite ready for a release yet, but if you'd like to play around with Johnson, you can pull it down from github <a href="http://github.com/jbarnette/johnson/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">here</a>. Just run 'rake', and you should have it compiled and running!</p>
301
+ <p>My next Johnson related post will be about Javascript parse trees and Javascript code generation.</p>
302
+ </div>
303
+
304
+ <p class="postfeedback">
305
+ Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> &bull;
306
+ <a href="http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/" rel="bookmark" title="Permanent Link to Take it to the limit one more time">Permalink</a> &bull;
307
+ <a href="http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/#comments">Comments (11)</a> &bull;
308
+ <a href="http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/#respond" title="Leave your Comment">Leave your Comment &raquo;</a>
309
+ </p>
310
+
311
+ <!--
312
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
313
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
314
+ xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
315
+ <rdf:Description rdf:about="http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/"
316
+ dc:identifier="http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/"
317
+ dc:title="Take it to the limit one more time"
318
+ trackback:ping="http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/trackback/" />
319
+ </rdf:RDF> -->
320
+
321
+ </div>
322
+
323
+
324
+ <div class="post" id="post-137">
325
+ <h2 class="postitle"><a href="http://tenderlovemaking.com/2008/04/01/new-ruby-implementation-brobinius/" rel="bookmark" title="Permanent Link to New Ruby Implementation - Brobinius">New Ruby Implementation - Brobinius</a></h2>
326
+ <p class="postmeta">Tuesday, 1 April 2008 @ 3:00pm &bull; <a href="http://tenderlovemaking.com/category/computadora/" title="View all posts in computadora" rel="category tag">computadora</a></p>
327
+
328
+ <div class="postentry">
329
+ <p>Brobinius version 1.0.0 has been released!</p>
330
+ <ul>
331
+ <li><a href="http://brobinius.org/" onclick="javascript:urchinTracker ('/outbound/article/brobinius.org');">http://brobinius.org/</a></li>
332
+ <li><a href="http://tenderlovemaking.com/" >http://tenderlovemaking.com/</a></li>
333
+ <li><a href="&#109;&#x61;&#105;&#x6c;&#116;&#x6f;:&#97;&#x61;&#114;&#x6f;&#110;&#x40;&#116;&#x65;n&#100;&#x65;&#114;&#x6c;&#111;&#x76;&#101;&#x6d;&#x61;&#107;&#x69;&#110;&#x67;&#46;&#x63;o&#109;">&#97;&#x61;&#114;&#x6f;&#110;&#x40;&#116;&#x65;n&#100;&#x65;&#114;&#x6c;&#111;&#x76;&#101;&#x6d;&#x61;&#107;&#x69;&#110;&#x67;&#46;&#x63;o&#109;</a></li>
334
+ </ul>
335
+ <p>I am happy to annouce the first release of my new fork of Ruby called<br />
336
+ Brobinius. The goal of Brobinius is to implement new language features<br />
337
+ that I have noticed to be completely missing.</p>
338
+ <p>For example, Object#tase! The tase method is featured in many other languages<br />
339
+ but is sadly missing from Ruby. Brobinius has a fully implemented tase! method.</p>
340
+ <div class="codesnip-container" >>> x = Class.new<br />
341
+ => #&lt;Class:0x3632ec><br />
342
+ >> x.tase!<br />
343
+ RuntimeError: Don't tase me bro<br />
344
+ from (irb):2:in `tase!'<br />
345
+ from (irb):6<br />
346
+ >></div>
347
+ <p>Brobinius also has fully serializable kittenuations. You can create and<br />
348
+ serialize your kittenuations, then pick up your snuggling where you left off.<br />
349
+ For example:</p>
350
+ <div class="codesnip-container" >>> lol = Kittenuation.new {<br />
351
+ ?> look_cute<br />
352
+ >> throw :yarn<br />
353
+ >> look_cute<br />
354
+ >> }<br />
355
+ => #&lt;Kittenuation:0x366244><br />
356
+ >> lol.snuggle<br />
357
+ >> Marshal.load(Marshal.dump(lol)).snuggle</div>
358
+ <p>Since Brobinius's kittenuations are serializable, you can share them over the<br />
359
+ network with friends!</p>
360
+ <p>Brobinius also features screencasts with automatic YouTube uploads. All you<br />
361
+ have to do write your program, then pass the --screencast option to Brobinius.<br />
362
+ Brobinius will automatically create a screencast of your program and upload it<br />
363
+ to YouTube:</p>
364
+ <div class="codesnip-container" >$ brobinius --screencast my_code.rb</div>
365
+ <p>You can even add the --geoff flag to create screencasts with Geoffrey<br />
366
+ Grosenbach doing the voice over.</p>
367
+ <ul>
368
+ <li><a href="http://brobinius.org/" onclick="javascript:urchinTracker ('/outbound/article/brobinius.org');">http://brobinius.org/</a></li>
369
+ <li><a href="http://tenderlovemaking.com/" >http://tenderlovemaking.com/</a></li>
370
+ <li><a href="&#109;&#x61;&#105;&#x6c;&#116;&#x6f;:&#97;&#x61;&#114;&#x6f;&#110;&#x40;&#116;&#x65;n&#100;&#x65;&#114;&#x6c;&#111;&#x76;&#101;&#x6d;&#x61;&#107;&#x69;&#110;&#x67;&#46;&#x63;o&#109;">&#97;&#x61;&#114;&#x6f;&#110;&#x40;&#116;&#x65;n&#100;&#x65;&#114;&#x6c;&#111;&#x76;&#101;&#x6d;&#x61;&#107;&#x69;&#110;&#x67;&#46;&#x63;o&#109;</a></li>
371
+ </ul>
372
+ </div>
373
+
374
+ <p class="postfeedback">
375
+ Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> &bull;
376
+ <a href="http://tenderlovemaking.com/2008/04/01/new-ruby-implementation-brobinius/" rel="bookmark" title="Permanent Link to New Ruby Implementation - Brobinius">Permalink</a> &bull;
377
+ <a href="http://tenderlovemaking.com/2008/04/01/new-ruby-implementation-brobinius/#comments">Comments (2)</a> &bull;
378
+ <a href="http://tenderlovemaking.com/2008/04/01/new-ruby-implementation-brobinius/#respond" title="Leave your Comment">Leave your Comment &raquo;</a>
379
+ </p>
380
+
381
+ <!--
382
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
383
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
384
+ xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
385
+ <rdf:Description rdf:about="http://tenderlovemaking.com/2008/04/01/new-ruby-implementation-brobinius/"
386
+ dc:identifier="http://tenderlovemaking.com/2008/04/01/new-ruby-implementation-brobinius/"
387
+ dc:title="New Ruby Implementation - Brobinius"
388
+ trackback:ping="http://tenderlovemaking.com/2008/04/01/new-ruby-implementation-brobinius/trackback/" />
389
+ </rdf:RDF> -->
390
+
391
+ </div>
392
+
393
+
394
+ <div class="post" id="post-136">
395
+ <h2 class="postitle"><a href="http://tenderlovemaking.com/2008/03/20/laser-etch-my-macbook-air/" rel="bookmark" title="Permanent Link to Laser Etch My Macbook Air">Laser Etch My Macbook Air</a></h2>
396
+ <p class="postmeta">Thursday, 20 March 2008 @ 3:03pm &bull; <a href="http://tenderlovemaking.com/category/computadora/" title="View all posts in computadora" rel="category tag">computadora</a></p>
397
+
398
+ <div class="postentry">
399
+ <p>Dear Lazyweb,</p>
400
+ <p>I would really like to <a href="http://blog.makezine.com/archive/2008/02/macbook_air_yes_it_can_be.html" onclick="javascript:urchinTracker ('/outbound/article/blog.makezine.com');">Laser Etch</a> my Macbook Air with <a href="http://blogs1.marthastewart.com/martha/2008/03/my-new-macbook.html" onclick="javascript:urchinTracker ('/outbound/article/blogs1.marthastewart.com');">Martha Stewart's</a> face. Where can I get that done? How much would it cost?</p>
401
+ </div>
402
+
403
+ <p class="postfeedback">
404
+ Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> &bull;
405
+ <a href="http://tenderlovemaking.com/2008/03/20/laser-etch-my-macbook-air/" rel="bookmark" title="Permanent Link to Laser Etch My Macbook Air">Permalink</a> &bull;
406
+ <a href="http://tenderlovemaking.com/2008/03/20/laser-etch-my-macbook-air/#comments">Comments (6)</a> &bull;
407
+ <a href="http://tenderlovemaking.com/2008/03/20/laser-etch-my-macbook-air/#respond" title="Leave your Comment">Leave your Comment &raquo;</a>
408
+ </p>
409
+
410
+ <!--
411
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
412
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
413
+ xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
414
+ <rdf:Description rdf:about="http://tenderlovemaking.com/2008/03/20/laser-etch-my-macbook-air/"
415
+ dc:identifier="http://tenderlovemaking.com/2008/03/20/laser-etch-my-macbook-air/"
416
+ dc:title="Laser Etch My Macbook Air"
417
+ trackback:ping="http://tenderlovemaking.com/2008/03/20/laser-etch-my-macbook-air/trackback/" />
418
+ </rdf:RDF> -->
419
+
420
+ </div>
421
+
422
+
423
+ <div class="post" id="post-135">
424
+ <h2 class="postitle"><a href="http://tenderlovemaking.com/2008/03/15/mechanize-version-075-has-been-released/" rel="bookmark" title="Permanent Link to mechanize version 0.7.5 has been released!">mechanize version 0.7.5 has been released!</a></h2>
425
+ <p class="postmeta">Saturday, 15 March 2008 @ 10:19am &bull; <a href="http://tenderlovemaking.com/category/life/" title="View all posts in life" rel="category tag">life</a></p>
426
+
427
+ <div class="postentry">
428
+ <p>The Mechanize library is used for automating interaction with websites.<br />
429
+ Mechanize automatically stores and sends cookies, follows redirects,<br />
430
+ can follow links, and submit forms. Form fields can be populated and<br />
431
+ submitted. Mechanize also keeps track of the sites that you have visited as<br />
432
+ a history.</p>
433
+ <p>Changes:</p>
434
+ <p># Mechanize CHANGELOG</p>
435
+ <p>## 0.7.5</p>
436
+ <ul>
437
+ <li>
438
+ <p>Fixed a bug when fetching files and not pages. Thanks Mat Schaffer!</p>
439
+ </li>
440
+ <li>
441
+ <p><a href="http://mechanize.rubyforge.org/" onclick="javascript:urchinTracker ('/outbound/article/mechanize.rubyforge.org');">http://mechanize.rubyforge.org/</a></p>
442
+ </li>
443
+ </ul>
444
+ </div>
445
+
446
+ <p class="postfeedback">
447
+ Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> &bull;
448
+ <a href="http://tenderlovemaking.com/2008/03/15/mechanize-version-075-has-been-released/" rel="bookmark" title="Permanent Link to mechanize version 0.7.5 has been released!">Permalink</a> &bull;
449
+ <a href="http://tenderlovemaking.com/2008/03/15/mechanize-version-075-has-been-released/#comments">Comments (0)</a> &bull;
450
+ <a href="http://tenderlovemaking.com/2008/03/15/mechanize-version-075-has-been-released/#respond" title="Leave your Comment">Leave your Comment &raquo;</a>
451
+ </p>
452
+
453
+ <!--
454
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
455
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
456
+ xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
457
+ <rdf:Description rdf:about="http://tenderlovemaking.com/2008/03/15/mechanize-version-075-has-been-released/"
458
+ dc:identifier="http://tenderlovemaking.com/2008/03/15/mechanize-version-075-has-been-released/"
459
+ dc:title="mechanize version 0.7.5 has been released!"
460
+ trackback:ping="http://tenderlovemaking.com/2008/03/15/mechanize-version-075-has-been-released/trackback/" />
461
+ </rdf:RDF> -->
462
+
463
+ </div>
464
+
465
+
466
+ <div class="post" id="post-133">
467
+ <h2 class="postitle"><a href="http://tenderlovemaking.com/2008/03/13/profiling-database-queries-in-rails/" rel="bookmark" title="Permanent Link to Profiling Database Queries in Rails">Profiling Database Queries in Rails</a></h2>
468
+ <p class="postmeta">Thursday, 13 March 2008 @ 2:16pm &bull; <a href="http://tenderlovemaking.com/category/computadora/" title="View all posts in computadora" rel="category tag">computadora</a>, <a href="http://tenderlovemaking.com/category/rails/" title="View all posts in rails" rel="category tag">rails</a></p>
469
+
470
+ <div class="postentry">
471
+ <p>Despite the recent Ruby webserver <a href="http://www.rubyinside.com/ebb-web-framework-http-server-786.html" onclick="javascript:urchinTracker ('/outbound/article/www.rubyinside.com');">speed contests</a>, most of the slowness at <a href="http://adready.com/" onclick="javascript:urchinTracker ('/outbound/article/adready.com');">my job</a> results from slow (or too many) database queries.</p>
472
+ <p>To help keep database queries down, I added a stats to every page that shows the number of queries vs. cache hits, the number of rows returned, and the amount of data transferred from the database. In this screenshot I'm using the "live" environment, 3 cache hits, 169 misses, 577 rows returned, and 458.9k data transferred. Clicking the box hides it, and clicking "Super Hide!" hides the box and sets a cookie so that the box doesn't show up again for a while.</p>
473
+ <p><a href="http://www.flickr.com/photos/aaronp/2331927606/" title="Debug Window by fakebeard, on Flickr" onclick="javascript:urchinTracker ('/outbound/article/www.flickr.com');"><img src="http://farm3.static.flickr.com/2106/2331927606_46cc9fa937.jpg" width="500" height="187" alt="Debug Window" /></a></p>
474
+ <p>To get this working, first I monkey patch the MysqlAdapter to collect database stats:</p>
475
+ <div class="codesnip-container" >
476
+ <div class="codesnip" style="font-family: monospace;">ActiveRecord::ConnectionAdapters::MysqlAdapter.<span class="me1">module_eval</span> <span class="kw1">do</span><br />
477
+ &nbsp; &nbsp; @@stats_queries = @@stats_bytes = @@stats_rows = <span class="nu0">0</span></p>
478
+ <p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">get_stats</span><br />
479
+ &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> :queries =&gt; @@stats_queries,<br />
480
+ &nbsp; &nbsp; &nbsp; &nbsp; :rows =&gt; @@stats_rows,<br />
481
+ &nbsp; &nbsp; &nbsp; &nbsp; :bytes =&gt; @@stats_bytes <span class="br0">&#125;</span><br />
482
+ &nbsp; &nbsp; <span class="kw1">end</span><br />
483
+ &nbsp; &nbsp; <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">reset_stats</span><br />
484
+ &nbsp; &nbsp; &nbsp; @@stats_queries = @@stats_bytes = @@stats_rows = <span class="nu0">0</span><br />
485
+ &nbsp; &nbsp; <span class="kw1">end</span></p>
486
+ <p>&nbsp; &nbsp; <span class="kw1">def</span> select_with_stats<span class="br0">&#40;</span>sql, name<span class="br0">&#41;</span><br />
487
+ &nbsp; &nbsp; &nbsp; bytes = <span class="nu0">0</span><br />
488
+ &nbsp; &nbsp; &nbsp; rows = select_without_stats<span class="br0">&#40;</span>sql, name<span class="br0">&#41;</span><br />
489
+ &nbsp; &nbsp; &nbsp; rows.<span class="me1">each</span> <span class="kw1">do</span> |row|<br />
490
+ &nbsp; &nbsp; &nbsp; &nbsp; row.<span class="me1">each</span> <span class="kw1">do</span> |key, value|<br />
491
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bytes += key.<span class="me1">length</span><br />
492
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bytes += value.<span class="me1">length</span> <span class="kw1">if</span> value<br />
493
+ &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
494
+ &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
495
+ &nbsp; &nbsp; &nbsp; @@stats_queries += <span class="nu0">1</span><br />
496
+ &nbsp; &nbsp; &nbsp; @@stats_rows += rows.<span class="me1">length</span><br />
497
+ &nbsp; &nbsp; &nbsp; @@stats_bytes += bytes<br />
498
+ &nbsp; &nbsp; &nbsp; rows<br />
499
+ &nbsp; &nbsp; <span class="kw1">end</span><br />
500
+ &nbsp; &nbsp; alias_method_chain :<span class="kw3">select</span>, :stats<br />
501
+ &nbsp; <span class="kw1">end</span></div>
502
+ </div>
503
+ <p>Next I patched the QueryCache to keep track of hits and misses:</p>
504
+ <div class="codesnip-container" >
505
+ <div class="codesnip" style="font-family: monospace;">ActiveRecord::ConnectionAdapters::QueryCache.<span class="me1">module_eval</span> <span class="kw1">do</span><br />
506
+ &nbsp; &nbsp; @@hits = @@misses = <span class="nu0">0</span></p>
507
+ <p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">get_stats</span><br />
508
+ &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> :hits =&gt; @@hits,<br />
509
+ &nbsp; &nbsp; &nbsp; &nbsp; :misses =&gt; @@misses <span class="br0">&#125;</span><br />
510
+ &nbsp; &nbsp; <span class="kw1">end</span><br />
511
+ &nbsp; &nbsp; <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">reset_stats</span><br />
512
+ &nbsp; &nbsp; &nbsp; @@hits = @@misses = <span class="nu0">0</span><br />
513
+ &nbsp; &nbsp; <span class="kw1">end</span></p>
514
+ <p>&nbsp; &nbsp; <span class="kw1">def</span> cache_sql_with_stats<span class="br0">&#40;</span>sql, &amp;block<span class="br0">&#41;</span><br />
515
+ &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> @query_cache.<span class="me1">has_key</span>?<span class="br0">&#40;</span>sql<span class="br0">&#41;</span><br />
516
+ &nbsp; &nbsp; &nbsp; &nbsp; @@hits += <span class="nu0">1</span><br />
517
+ &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
518
+ &nbsp; &nbsp; &nbsp; &nbsp; @@misses += <span class="nu0">1</span><br />
519
+ &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
520
+ &nbsp; &nbsp; &nbsp; cache_sql_without_stats<span class="br0">&#40;</span>sql, &amp;block<span class="br0">&#41;</span><br />
521
+ &nbsp; &nbsp; <span class="kw1">end</span><br />
522
+ &nbsp; &nbsp; alias_method_chain :cache_sql, :stats<br />
523
+ &nbsp; <span class="kw1">end</span></div>
524
+ </div>
525
+ <p>Then modify ActionController to reset stats for each request:</p>
526
+ <div class="codesnip-container" >
527
+ <div class="codesnip" style="font-family: monospace;">ActionController::Base.<span class="me1">module_eval</span> <span class="kw1">do</span><br />
528
+ &nbsp; &nbsp; <span class="kw1">def</span> perform_action_with_reset<br />
529
+ &nbsp; &nbsp; &nbsp; ActiveRecord::ConnectionAdapters::MysqlAdapter::reset_stats<br />
530
+ &nbsp; &nbsp; &nbsp; ActiveRecord::ConnectionAdapters::QueryCache::reset_stats<br />
531
+ &nbsp; &nbsp; &nbsp; perform_action_without_reset<br />
532
+ &nbsp; &nbsp; <span class="kw1">end</span></p>
533
+ <p>&nbsp; &nbsp; alias_method_chain :perform_action, :reset</p>
534
+ <p>&nbsp; &nbsp; <span class="kw1">def</span> active_record_runtime<span class="br0">&#40;</span>runtime<span class="br0">&#41;</span><br />
535
+ &nbsp; &nbsp; &nbsp; stats = ActiveRecord::ConnectionAdapters::MysqlAdapter::get_stats<br />
536
+ &nbsp; &nbsp; &nbsp; <span class="st0">&quot;#{super} #{sprintf(&quot;</span>%.1fk<span class="st0">&quot;, stats[:bytes].to_f / 1024)} queries: #{stats[:queries]}&quot;</span><br />
537
+ &nbsp; &nbsp; <span class="kw1">end</span><br />
538
+ &nbsp; <span class="kw1">end</span></div>
539
+ </div>
540
+ <p>Just drop all that inside the after_initialize in your development.rb and you'll get the nice stats. After that, just create a partial that displays the stats and include the partial at the bottom of your layout. Our partial looks like this:</p>
541
+ <div class="codesnip-container" >
542
+ <div class="codesnip" style="font-family: monospace;"><span class="sc2">&lt;% unless %w<span class="br0">&#40;</span>production test<span class="br0">&#41;</span>.include?<span class="br0">&#40;</span>RAILS_ENV<span class="br0">&#41;</span> -%<span class="kw2">&gt;</span></span><br />
543
+ &nbsp; <span class="sc2"><a href="http://december.com/html/4/element/h4.html" onclick="javascript:urchinTracker ('/outbound/article/december.com');"><span class="kw2">&lt;h4</span></a> <span class="kw3">id</span>=<span class="st0">&quot;debug&quot;</span> <span class="kw3">onclick</span>=<span class="st0">&quot;$(this).remove()&quot;</span> <span class="kw3">style</span>=<span class="st0">&quot;background:pink;text-align:center;position:absolute;top:16px;left:35%;padding:0.5em;border: 2px solid red;&quot;</span><span class="kw2">&gt;</span></span><br />
544
+ &nbsp; <span class="sc2">&lt;%= RAILS_ENV %<span class="kw2">&gt;</span></span><br />
545
+ &nbsp; <span class="sc2"><a href="http://december.com/html/4/element/br.html" onclick="javascript:urchinTracker ('/outbound/article/december.com');"><span class="kw2">&lt;br</span></a> /<span class="kw2">&gt;</span></span><br />
546
+ &nbsp; <span class="sc2">&lt;% if ActiveRecord::ConnectionAdapters::QueryCache.respond_to?<span class="br0">&#40;</span>:get_stats<span class="br0">&#41;</span> %<span class="kw2">&gt;</span></span><br />
547
+ &nbsp; &nbsp; <span class="sc2">&lt;% stats = ActiveRecord::ConnectionAdapters::QueryCache.get_stats %<span class="kw2">&gt;</span></span><br />
548
+ &nbsp; &nbsp; Queries: <span class="sc2">&lt;%= stats<span class="br0">&#91;</span>:hits<span class="br0">&#93;</span> %<span class="kw2">&gt;</span></span> / <span class="sc2">&lt;%= stats<span class="br0">&#91;</span>:misses<span class="br0">&#93;</span> %<span class="kw2">&gt;</span></span> /<br />
549
+ &nbsp; &nbsp; <span class="sc2">&lt;%= number_to_percentage<span class="br0">&#40;</span><span class="br0">&#40;</span>stats<span class="br0">&#91;</span>:hits<span class="br0">&#93;</span>.to_f / <span class="br0">&#40;</span>stats<span class="br0">&#91;</span>:hits<span class="br0">&#93;</span> + stats<span class="br0">&#91;</span>:misses<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> * <span class="nu0">100</span>, :precision =<span class="kw2">&gt;</span></span> 0) %&gt;<br />
550
+ &nbsp; &nbsp; |<br />
551
+ &nbsp; <span class="sc2">&lt;% end %<span class="kw2">&gt;</span></span><br />
552
+ &nbsp; <span class="sc2">&lt;% if ActiveRecord::ConnectionAdapters::MysqlAdapter.respond_to?<span class="br0">&#40;</span>:get_stats<span class="br0">&#41;</span> %<span class="kw2">&gt;</span></span><br />
553
+ &nbsp; &nbsp; <span class="sc2">&lt;% stats = ActiveRecord::ConnectionAdapters::MysqlAdapter.get_stats %<span class="kw2">&gt;</span></span><br />
554
+ &nbsp; &nbsp; Rows: <span class="sc2">&lt;%= stats<span class="br0">&#91;</span>:<span class="kw3">rows</span><span class="br0">&#93;</span> %<span class="kw2">&gt;</span></span> |<br />
555
+ &nbsp; &nbsp; Transfer: <span class="sc2">&lt;%= sprintf<span class="br0">&#40;</span><span class="st0">&quot;%.1fk&quot;</span>, stats<span class="br0">&#91;</span>:bytes<span class="br0">&#93;</span>.to_f / <span class="nu0">1024</span><span class="br0">&#41;</span> %<span class="kw2">&gt;</span></span><br />
556
+ &nbsp; <span class="sc2">&lt;% end %<span class="kw2">&gt;</span></span><br />
557
+ &nbsp; <span class="sc2"><a href="http://december.com/html/4/element/p.html" onclick="javascript:urchinTracker ('/outbound/article/december.com');"><span class="kw2">&lt;p</span></a> <span class="kw3">style</span>=<span class="st0">&quot;margin:0&quot;</span><span class="kw2">&gt;</span></span><br />
558
+ &nbsp; &nbsp; <span class="sc2"><a href="http://december.com/html/4/element/a.html" onclick="javascript:urchinTracker ('/outbound/article/december.com');"><span class="kw2">&lt;a</span></a> <span class="kw3">style</span>=<span class="st0">&quot;color:magenta&quot;</span> <span class="kw3">href</span>=<span class="st0">&quot;#&quot;</span> <span class="kw3">onclick</span>=<span class="st0">&quot;superHide()&quot;</span><span class="kw2">&gt;</span></span>super hide!<span class="sc2"><span class="kw2">&lt;/a&gt;</span></span><br />
559
+ &nbsp; <span class="sc2"><span class="kw2">&lt;/p&gt;</span></span><br />
560
+ &nbsp; <span class="sc2"><span class="kw2">&lt;/h4&gt;</span></span><br />
561
+ &nbsp; <span class="sc2"><a href="http://december.com/html/4/element/script.html" onclick="javascript:urchinTracker ('/outbound/article/december.com');"><span class="kw2">&lt;script</span></a> <span class="kw3">type</span>=<span class="st0">&quot;text/javascript&quot;</span><span class="kw2">&gt;</span></span><br />
562
+ &nbsp; &nbsp; function superHide() {<br />
563
+ &nbsp; &nbsp; &nbsp; document.cookie = 'debug=hidden; path=/; domain=<span class="sc2">&lt;%= request.host %<span class="kw2">&gt;</span></span>; max-age=14400';<br />
564
+ &nbsp; &nbsp; }<br />
565
+ &nbsp; &nbsp; if(document.cookie.indexOf('debug=hidden') != -1) {<br />
566
+ &nbsp; &nbsp; &nbsp; $('debug').hide();<br />
567
+ &nbsp; &nbsp; }<br />
568
+ &nbsp; <span class="sc2"><span class="kw2">&lt;/script&gt;</span></span><br />
569
+ <span class="sc2">&lt;% end -%<span class="kw2">&gt;</span></span></div>
570
+ </div>
571
+ <p>It's a little work, but it helps keep my mind on reducing the queries. With enough work, one of these days the speed of the webserver will matter to me. Thanks to <a href="http://gurge.com/blog/2006/11/09/rails-sql-logging-improvements/" onclick="javascript:urchinTracker ('/outbound/article/gurge.com');">Adam Doppelt</a> for the basis of this monkey patch. Any bugs are mine, not his!</p>
572
+ </div>
573
+
574
+ <p class="postfeedback">
575
+ Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> &bull;
576
+ <a href="http://tenderlovemaking.com/2008/03/13/profiling-database-queries-in-rails/" rel="bookmark" title="Permanent Link to Profiling Database Queries in Rails">Permalink</a> &bull;
577
+ <a href="http://tenderlovemaking.com/2008/03/13/profiling-database-queries-in-rails/#comments">Comments (2)</a> &bull;
578
+ <a href="http://tenderlovemaking.com/2008/03/13/profiling-database-queries-in-rails/#respond" title="Leave your Comment">Leave your Comment &raquo;</a>
579
+ </p>
580
+
581
+ <!--
582
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
583
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
584
+ xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
585
+ <rdf:Description rdf:about="http://tenderlovemaking.com/2008/03/13/profiling-database-queries-in-rails/"
586
+ dc:identifier="http://tenderlovemaking.com/2008/03/13/profiling-database-queries-in-rails/"
587
+ dc:title="Profiling Database Queries in Rails"
588
+ trackback:ping="http://tenderlovemaking.com/2008/03/13/profiling-database-queries-in-rails/trackback/" />
589
+ </rdf:RDF> -->
590
+
591
+ </div>
592
+
593
+
594
+ <div class="post" id="post-132">
595
+ <h2 class="postitle"><a href="http://tenderlovemaking.com/2008/03/04/mechanize-version-071-has-been-released/" rel="bookmark" title="Permanent Link to mechanize version 0.7.1 has been released!">mechanize version 0.7.1 has been released!</a></h2>
596
+ <p class="postmeta">Tuesday, 4 March 2008 @ 8:42pm &bull; <a href="http://tenderlovemaking.com/category/life/" title="View all posts in life" rel="category tag">life</a></p>
597
+
598
+ <div class="postentry">
599
+ <p>The Mechanize library is used for automating interaction with websites.<br />
600
+ Mechanize automatically stores and sends cookies, follows redirects,<br />
601
+ can follow links, and submit forms. Form fields can be populated and<br />
602
+ submitted. Mechanize also keeps track of the sites that you have visited as<br />
603
+ a history.</p>
604
+ <p>Changes:</p>
605
+ <p># Mechanize CHANGELOG</p>
606
+ <p>## 0.7.1</p>
607
+ <ul>
608
+ <li>Added iPhone to the user agent aliases. [#17572]</li>
609
+ <li>Fixed a bug with EOF errors in net/http. [#17570]</li>
610
+ <li>
611
+ <p>Handling 0 length gzipped responses. [#17471]</p>
612
+ </li>
613
+ <li>
614
+ <p><a href="http://mechanize.rubyforge.org/" onclick="javascript:urchinTracker ('/outbound/article/mechanize.rubyforge.org');">http://mechanize.rubyforge.org/</a></p>
615
+ </li>
616
+ </ul>
617
+ </div>
618
+
619
+ <p class="postfeedback">
620
+ Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> &bull;
621
+ <a href="http://tenderlovemaking.com/2008/03/04/mechanize-version-071-has-been-released/" rel="bookmark" title="Permanent Link to mechanize version 0.7.1 has been released!">Permalink</a> &bull;
622
+ <a href="http://tenderlovemaking.com/2008/03/04/mechanize-version-071-has-been-released/#comments">Comments (1)</a> &bull;
623
+ <a href="http://tenderlovemaking.com/2008/03/04/mechanize-version-071-has-been-released/#respond" title="Leave your Comment">Leave your Comment &raquo;</a>
624
+ </p>
625
+
626
+ <!--
627
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
628
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
629
+ xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
630
+ <rdf:Description rdf:about="http://tenderlovemaking.com/2008/03/04/mechanize-version-071-has-been-released/"
631
+ dc:identifier="http://tenderlovemaking.com/2008/03/04/mechanize-version-071-has-been-released/"
632
+ dc:title="mechanize version 0.7.1 has been released!"
633
+ trackback:ping="http://tenderlovemaking.com/2008/03/04/mechanize-version-071-has-been-released/trackback/" />
634
+ </rdf:RDF> -->
635
+
636
+ </div>
637
+
638
+
639
+ <div class="post" id="post-131">
640
+ <h2 class="postitle"><a href="http://tenderlovemaking.com/2008/02/26/automated-youtube-uploads/" rel="bookmark" title="Permanent Link to Automated Youtube Uploads">Automated Youtube Uploads</a></h2>
641
+ <p class="postmeta">Tuesday, 26 February 2008 @ 10:38am &bull; <a href="http://tenderlovemaking.com/category/computadora/" title="View all posts in computadora" rel="category tag">computadora</a>, <a href="http://tenderlovemaking.com/category/mechanize/" title="View all posts in mechanize" rel="category tag">mechanize</a></p>
642
+
643
+ <div class="postentry">
644
+ <p>I thought I would share the part of my <a href="http://twitterbrite.com/" onclick="javascript:urchinTracker ('/outbound/article/twitterbrite.com');">twitterbrite</a> scripts that uploads videos to <a href="http://youtube.com/" onclick="javascript:urchinTracker ('/outbound/article/youtube.com');">Youtube</a>. Its about 30 lines long, and took me an hour or so to write. Most of my time was spent figuring out form fields to fill out rather than writing code though....</p>
645
+ <p>I've broken the script down to three parts: logging in, setting the video attributes, and uploading the video file.</p>
646
+ <h3>Step 1: Logging In</h3>
647
+ <p>The first step is pretty simple. Just instantiate a new mechanize object, fetch youtube.com, set your login credentials, and submit!</p>
648
+ <div class="codesnip-container" >
649
+ <div class="codesnip" style="font-family: monospace;">agent = WWW::Mechanize.<span class="me1">new</span> <span class="br0">&#123;</span> |a|<br />
650
+ &nbsp; a.<span class="me1">user_agent_alias</span> = 'Mac Safari'<br />
651
+ <span class="br0">&#125;</span><br />
652
+ page = agent.<span class="me1">get</span><span class="br0">&#40;</span>'http://youtube.<span class="me1">com</span>/'<span class="br0">&#41;</span></p>
653
+ <p><span class="co1"># Login</span><br />
654
+ page.<span class="me1">form</span><span class="br0">&#40;</span>'loginForm'<span class="br0">&#41;</span> <span class="br0">&#123;</span> |f|<br />
655
+ &nbsp; f.<span class="me1">username</span> = 'username'<br />
656
+ &nbsp; f.<span class="me1">password</span> = 'password'<br />
657
+ <span class="br0">&#125;</span>.<span class="me1">submit</span></div>
658
+ </div>
659
+ <h3>Step 2: Setting video attributes</h3>
660
+ <p>This is probably the most difficult step. Now that the agent is logged in, we have to fetch the upload page and fill out the video attributes form. You have to set the title, description, category, and keywords for your video. The you have to tell the agent to click a special button.</p>
661
+ <div class="codesnip-container" >
662
+ <div class="codesnip" style="font-family: monospace;"><span class="co1"># Set the video attributes</span><br />
663
+ page = agent.<span class="me1">get</span><span class="br0">&#40;</span>'http://youtube.<span class="me1">com</span>/my_videos_upload'<span class="br0">&#41;</span><br />
664
+ form = page.<span class="me1">form</span><span class="br0">&#40;</span>'theForm'<span class="br0">&#41;</span><br />
665
+ form.<span class="me1">field_myvideo_title</span> = 'My video title'<br />
666
+ form.<span class="me1">field_myvideo_descr</span> = <span class="st0">&quot;My video description&quot;</span><br />
667
+ form.<span class="me1">field_myvideo_categories</span> = <span class="nu0">28</span><br />
668
+ form.<span class="me1">field_myvideo_keywords</span> = 'my tag'<br />
669
+ page = form.<span class="me1">submit</span><span class="br0">&#40;</span>form.<span class="me1">buttons</span>.<span class="me1">name</span><span class="br0">&#40;</span>'action_upload'<span class="br0">&#41;</span>.<span class="me1">first</span><span class="br0">&#41;</span></div>
670
+ </div>
671
+ <p>The number "28" is just the value from the category drop down list. You can iterate over the select options using mechanize, but I leave that as an exercise to the reader.</p>
672
+ <h3>Step 3: Upload the video file</h3>
673
+ <p>My script expects that the video file name will be supplied on the command line, so ARGV[0] should point to the file you want to upload. In this step, you simply set the video file name, then submit the form.</p>
674
+ <div class="codesnip-container" >
675
+ <div class="codesnip" style="font-family: monospace;"><span class="co1"># Upload the video</span><br />
676
+ page = page.<span class="me1">form</span><span class="br0">&#40;</span>'theForm'<span class="br0">&#41;</span> <span class="br0">&#123;</span> |f|<br />
677
+ &nbsp; f.<span class="me1">file_uploads</span>.<span class="me1">name</span><span class="br0">&#40;</span>'field_uploadfile'<span class="br0">&#41;</span>.<span class="me1">first</span>.<span class="me1">file_name</span> = ARGV<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><br />
678
+ <span class="br0">&#125;</span>.<span class="me1">submit</span><br />
679
+ page.<span class="me1">body</span> =~ /&lt;textarea<span class="br0">&#91;</span>^&gt;<span class="br0">&#93;</span>*&gt;<span class="br0">&#40;</span>.<span class="me1">*</span><span class="br0">&#41;</span>&lt;\/textarea&gt;/m<br />
680
+ <span class="kw3">puts</span> $<span class="nu0">1</span></div>
681
+ </div>
682
+ <p>The last two lines grab the html needed to display the video and prints it.</p>
683
+ <p>There you go. Upload lots of videos now! Yay!</p>
684
+ </div>
685
+
686
+ <p class="postfeedback">
687
+ Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> &bull;
688
+ <a href="http://tenderlovemaking.com/2008/02/26/automated-youtube-uploads/" rel="bookmark" title="Permanent Link to Automated Youtube Uploads">Permalink</a> &bull;
689
+ <a href="http://tenderlovemaking.com/2008/02/26/automated-youtube-uploads/#comments">Comments (0)</a> &bull;
690
+ <a href="http://tenderlovemaking.com/2008/02/26/automated-youtube-uploads/#respond" title="Leave your Comment">Leave your Comment &raquo;</a>
691
+ </p>
692
+
693
+ <!--
694
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
695
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
696
+ xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
697
+ <rdf:Description rdf:about="http://tenderlovemaking.com/2008/02/26/automated-youtube-uploads/"
698
+ dc:identifier="http://tenderlovemaking.com/2008/02/26/automated-youtube-uploads/"
699
+ dc:title="Automated Youtube Uploads"
700
+ trackback:ping="http://tenderlovemaking.com/2008/02/26/automated-youtube-uploads/trackback/" />
701
+ </rdf:RDF> -->
702
+
703
+ </div>
704
+
705
+
706
+ <a href="http://tenderlovemaking.com/page/2/">Next Page &raquo;</a>
707
+ </div>
708
+
709
+ <div id="sidebar">
710
+
711
+ <div style="margin-top: 2em;">
712
+ <form method="get" id="searchform" action="/index.php">
713
+ <input type="text" value="" name="s" id="search" />
714
+ <input type="submit" id="searchsubmit" value="Search" />
715
+ </form></div>
716
+ <br />
717
+
718
+ <ul>
719
+
720
+ <li class="pagenav"><h2>Pages</h2><ul><li class="page_item page-item-2"><a href="http://tenderlovemaking.com/about/" title="About">About</a></li>
721
+ </ul></li>
722
+ <!-- unComment if you wan to use the author thing :D
723
+ <li><h2>The Author</h2>
724
+ <ul>
725
+ <li>This is all about me :D</li>
726
+ </ul>
727
+ </li>
728
+ -->
729
+
730
+ <li><h2>Categories</h2>
731
+ <ul>
732
+ <li class="cat-item cat-item-6"><a href="http://tenderlovemaking.com/category/computadora/betabrite/" title="View all posts filed under betabrite">betabrite</a> (4)
733
+ </li>
734
+ <li class="cat-item cat-item-2"><a href="http://tenderlovemaking.com/category/computadora/" title="View all posts filed under computadora">computadora</a> (42)
735
+ </li>
736
+ <li class="cat-item cat-item-15"><a href="http://tenderlovemaking.com/category/csspool/" title="View all posts filed under csspool">csspool</a> (2)
737
+ </li>
738
+ <li class="cat-item cat-item-5"><a href="http://tenderlovemaking.com/category/daap/" title="View all posts filed under daap">daap</a> (3)
739
+ </li>
740
+ <li class="cat-item cat-item-10"><a href="http://tenderlovemaking.com/category/ecma/" title="View all posts filed under ecma">ecma</a> (7)
741
+ </li>
742
+ <li class="cat-item cat-item-14"><a href="http://tenderlovemaking.com/category/icanhasaudio/" title="View all posts filed under icanhasaudio">icanhasaudio</a> (2)
743
+ </li>
744
+ <li class="cat-item cat-item-33"><a href="http://tenderlovemaking.com/category/computadora/johnson/" title="View all posts filed under johnson">johnson</a> (2)
745
+ </li>
746
+ <li class="cat-item cat-item-4"><a href="http://tenderlovemaking.com/category/life/" title="View all posts filed under life">life</a> (69)
747
+ </li>
748
+ <li class="cat-item cat-item-3"><a href="http://tenderlovemaking.com/category/mechanize/" title="View all posts filed under mechanize">mechanize</a> (14)
749
+ </li>
750
+ <li class="cat-item cat-item-34"><a href="http://tenderlovemaking.com/category/computadora/meow/" title="View all posts filed under meow">meow</a> (1)
751
+ </li>
752
+ <li class="cat-item cat-item-13"><a href="http://tenderlovemaking.com/category/objectgraph/" title="View all posts filed under objectgraph">objectgraph</a> (1)
753
+ </li>
754
+ <li class="cat-item cat-item-9"><a href="http://tenderlovemaking.com/category/rails/" title="View all posts filed under rails">rails</a> (4)
755
+ </li>
756
+ <li class="cat-item cat-item-12"><a href="http://tenderlovemaking.com/category/raop/" title="View all posts filed under raop">raop</a> (2)
757
+ </li>
758
+ <li class="cat-item cat-item-11"><a href="http://tenderlovemaking.com/category/rkelly/" title="View all posts filed under rkelly">rkelly</a> (6)
759
+ </li>
760
+ <li class="cat-item cat-item-28"><a href="http://tenderlovemaking.com/category/rubygems/" title="View all posts filed under rubygems">rubygems</a> (1)
761
+ </li>
762
+ </ul>
763
+ </li>
764
+
765
+
766
+ <li><h2>Archive</h2>
767
+ <ul>
768
+ <li><a href='http://tenderlovemaking.com/2008/07/' title='July 2008'>July 2008</a></li>
769
+ <li><a href='http://tenderlovemaking.com/2008/06/' title='June 2008'>June 2008</a></li>
770
+ <li><a href='http://tenderlovemaking.com/2008/05/' title='May 2008'>May 2008</a></li>
771
+ <li><a href='http://tenderlovemaking.com/2008/04/' title='April 2008'>April 2008</a></li>
772
+ <li><a href='http://tenderlovemaking.com/2008/03/' title='March 2008'>March 2008</a></li>
773
+ <li><a href='http://tenderlovemaking.com/2008/02/' title='February 2008'>February 2008</a></li>
774
+ <li><a href='http://tenderlovemaking.com/2008/01/' title='January 2008'>January 2008</a></li>
775
+ <li><a href='http://tenderlovemaking.com/2007/12/' title='December 2007'>December 2007</a></li>
776
+ <li><a href='http://tenderlovemaking.com/2007/11/' title='November 2007'>November 2007</a></li>
777
+ <li><a href='http://tenderlovemaking.com/2007/10/' title='October 2007'>October 2007</a></li>
778
+ <li><a href='http://tenderlovemaking.com/2007/09/' title='September 2007'>September 2007</a></li>
779
+ <li><a href='http://tenderlovemaking.com/2007/08/' title='August 2007'>August 2007</a></li>
780
+ </ul>
781
+ </li>
782
+
783
+
784
+
785
+ <li id="linkcat-7" class="linkcat"><h2>My Friends</h2>
786
+ <ul>
787
+ <li><a href="http://blog.segment7.net/" rel="friend met">Eric Hodel</a></li>
788
+ <li><a href="http://blog.fallingsnow.net/" rel="friend met">Evan Phoenix</a></li>
789
+ <li><a href="http://grapefruitgallery.com/">gfg</a></li>
790
+ <li><a href="http://metametta.blogspot.com/" rel="friend met" title="Gregory Brown&#8217;s blog.">Gregory Brown</a></li>
791
+ <li><a href="http://obvio171.wordpress.com/" rel="friend">Helder Ribeiro</a></li>
792
+ <li><a href="http://highwayinsomnia.com/" rel="friend met" title="BFF">Jackie</a></li>
793
+ <li><a href="http://geeksomnia.com/" rel="friend met co-worker">John Barnette</a></li>
794
+ <li><a href="http://donkeyonwheels.com/" rel="friend met neighbor">Pam</a></li>
795
+ <li><a href="http://ruby.sadi.st/" title="Holler!">Ruby Sadist</a></li>
796
+ <li><a href="http://blog.zenspider.com/" rel="friend met neighbor">Ryan Davis</a></li>
797
+ <li><a href="http://tersesystems.com/" rel="friend met">Will Sargent</a></li>
798
+
799
+ </ul>
800
+ </li>
801
+ <li id="linkcat-8" class="linkcat"><h2>My Ruby Projects</h2>
802
+ <ul>
803
+ <li><a href="http://rubyforge.org/projects/betabrite/" title="BetaBrite Sign Library">BetaBrite Sign Library</a></li>
804
+ <li><a href="http://csspool.rubyforge.org/">csspool</a></li>
805
+ <li><a href="http://seattlerb.rubyforge.org/icanhasaudio/" title="icanhasaudio">icanhasaudio</a></li>
806
+ <li><a href="http://lamestore.com/">lamestore</a></li>
807
+ <li><a href="http://daapclient.rubyforge.org/">Net::DAAP::Client</a></li>
808
+ <li><a href="http://raop.rubyforge.org/" title="Stream music to your airport express.">Net::RAOP::Client</a></li>
809
+ <li><a href="http://seattlerb.rubyforge.org/ograph/" title="Graph your ruby objects.">Object Graph</a></li>
810
+ <li><a href="http://mechanize.rubyforge.org/">WWW::Mechanize</a></li>
811
+
812
+ </ul>
813
+ </li>
814
+
815
+ <li><h2>Meta</h2>
816
+ <ul>
817
+ <li><a href="http://tenderlovemaking.com/wp-login.php">Log in</a></li>
818
+ <li><a href="http://tenderlovemaking.com/feed/">RSS Feed Entries</a></li>
819
+ <li><a href="http://tenderlovemaking.com/comments/feed/">RSS Feed Comments</a></li>
820
+ <li><a href="http://tenderlovemaking.com/feed/atom/">Atom Feed</a></li>
821
+ <li><a href="http://gmpg.org/xfn/"><abbr title="XHTML Friends Network">XFN</abbr></a></li>
822
+ <li><a href="http://wordpress.org/" title="Powered by WordPress, state-of-the-art semantic personal publishing platform.">WordPress</a></li>
823
+ </ul>
824
+ </li>
825
+
826
+ </ul>
827
+ </div>
828
+
829
+ <div id="footer">
830
+ A design by <a href="http://blog.geminigeek.com/wordpress-theme">GeminiGeek</a> &bull; Powered by <a href="http://wordpress.org">Wordpress</a><!--&bull; <a href="#">CSS</a> &bull; <a href="#">xHTML 1.0</a>-->
831
+ </div>
832
+
833
+ </div><!-- wrap close -->
834
+
835
+
836
+
837
+ <!--
838
+ Google Analytics Plugin for Wordpress and BBPress
839
+ http://boakes.org/analytics
840
+ -->
841
+ <script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
842
+ </script>
843
+ <script type="text/javascript">
844
+ _uacct = "UA-1260604-1";
845
+ urchinTracker();
846
+ </script>
847
+
848
+
849
+ </body>
850
+ </html>