readit 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. data/.travis.yml +12 -0
  2. data/Gemfile +3 -1
  3. data/Readme.md +61 -5
  4. data/features/bookmarks.feature +9 -9
  5. data/features/readability.yml.sample +6 -0
  6. data/features/step_definitions/api_steps.rb +4 -4
  7. data/lib/readit/version.rb +1 -1
  8. data/lib/readit.rb +89 -11
  9. data/spec/cases/api_spec.rb +29 -6
  10. data/spec/cases/parser_spec.rb +19 -0
  11. data/spec/cases/tags_spec.rb +46 -0
  12. data/spec/cassettes/Readit_API/can_add_tags_to_one_bookmark.yml +699 -0
  13. data/spec/cassettes/Readit_API/can_fetch_all_tags_information_of_current_user.yml +45 -0
  14. data/spec/cassettes/Readit_API/can_fetch_tags_of_one_bookmark.yml +687 -0
  15. data/spec/cassettes/Readit_API/can_get_bookmark_location_when_bookmarked_a_url.yml +52 -0
  16. data/spec/cassettes/Readit_API/can_get_meta_infos_of_bookmarks.yml +646 -0
  17. data/spec/cassettes/Readit_API/can_remove_tag_info_of_one_bookmark_by_tag_id.yml +786 -0
  18. data/spec/cassettes/Readit_API/should_add_bookmark.yml +52 -0
  19. data/spec/cassettes/Readit_API/should_get_bookmarks_according_to_added_since.yml +86 -0
  20. data/spec/cassettes/Readit_API/should_get_the_article_content.yml +322 -0
  21. data/spec/cassettes/Readit_API/should_get_the_bookmark_info_by_bookmark_id.yml +713 -0
  22. data/spec/cassettes/Readit_API/should_get_user_infos.yml +51 -0
  23. data/spec/cassettes/Readit_API/should_get_user_s_bookmarks.yml +634 -0
  24. data/spec/cassettes/Readit_API/should_provide_the_bookmark_id_of_an_already_bookmarked_url.yml +683 -0
  25. data/spec/cassettes/Readit_API/should_update_bookmark_to_archive.yml +808 -0
  26. data/spec/cassettes/Readit_API/should_update_bookmark_to_favarite.yml +808 -0
  27. data/spec/cassettes/Readit_Parser/should_return_parsed_article_cotents.yml +638 -0
  28. data/spec/readability.yml.sample +7 -0
  29. data/spec/spec_helper.rb +28 -1
  30. metadata +65 -11
  31. data/readability.yml.sample +0 -3
@@ -0,0 +1,52 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://www.readability.com/api/rest/v1/bookmarks
6
+ body:
7
+ encoding: US-ASCII
8
+ string: url=http%3A%2F%2Fwww.tripadvisor.com%2FRestaurant_Review-g297701-d1182615-Reviews-Cafe_Lotus-Ubud_Bali.html
9
+ headers:
10
+ Accept:
11
+ - ! '*/*'
12
+ User-Agent:
13
+ - OAuth gem v0.4.7
14
+ Content-Length:
15
+ - '0'
16
+ Content-Type:
17
+ - application/x-www-form-urlencoded
18
+ Authorization:
19
+ - OAuth oauth_consumer_key="<TOKENS>", oauth_nonce="LxDHPjGRmZ3krV9MEDEUhlD9RzfDb6WL6vdL5VwF3Es",
20
+ oauth_signature="yDdXZC4itrqQHzLT8YTStpA%2FNvs%3D", oauth_signature_method="HMAC-SHA1",
21
+ oauth_timestamp="1361335756", oauth_token="<TOKENS>", oauth_version="1.0"
22
+ response:
23
+ status:
24
+ code: 409
25
+ message: CONFLICT
26
+ headers:
27
+ Content-Type:
28
+ - application/json
29
+ Date:
30
+ - Wed, 20 Feb 2013 04:49:13 GMT
31
+ Location:
32
+ - https://www.readability.com/api/rest/v1/bookmarks/2420783
33
+ P3p:
34
+ - CP='Legacy Only. Go to https://readability.com/about/terms/ for full terms.'
35
+ Server:
36
+ - nginx/1.2.1
37
+ Set-Cookie:
38
+ - readabilityToken=4FCRyvwJt8enJ7LvesTWKphGwNRyT5h9B3t5KWfP; expires=Wed, 20-Mar-2013
39
+ 04:49:13 GMT; Max-Age=2419200; Path=/
40
+ Vary:
41
+ - Authorization, Cookie
42
+ Content-Length:
43
+ - '117'
44
+ Connection:
45
+ - keep-alive
46
+ body:
47
+ encoding: US-ASCII
48
+ string: ! '{"meta": {"redirect": true, "existing_bookmark": 2420783}, "messages":
49
+ ["Bookmark already exists."], "success": true}'
50
+ http_version:
51
+ recorded_at: Wed, 20 Feb 2013 04:49:16 GMT
52
+ recorded_with: VCR 2.0.1
@@ -0,0 +1,86 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://www.readability.com/api/rest/v1/bookmarks?added_until=2012-1-1&per_page=2
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - ! '*/*'
12
+ User-Agent:
13
+ - OAuth gem v0.4.7
14
+ Authorization:
15
+ - OAuth oauth_consumer_key="<TOKENS>", oauth_nonce="Xc8HCVOzxhpz8sgPCUVDer3spA2TLJy4FMBQcDIcolI",
16
+ oauth_signature="cX%2FCeK0pYubEOv07oH0333F7%2BKM%3D", oauth_signature_method="HMAC-SHA1",
17
+ oauth_timestamp="1361335761", oauth_token="<TOKENS>", oauth_version="1.0"
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Content-Type:
24
+ - application/json; charset=utf-8
25
+ Date:
26
+ - Wed, 20 Feb 2013 04:49:17 GMT
27
+ P3p:
28
+ - CP='Legacy Only. Go to https://readability.com/about/terms/ for full terms.'
29
+ Server:
30
+ - nginx/1.2.1
31
+ Set-Cookie:
32
+ - readabilityToken=4FCRyvwJt8enJ7LvesTWKphGwNRyT5h9B3t5KWfP; expires=Wed, 20-Mar-2013
33
+ 04:49:17 GMT; Max-Age=2419200; Path=/
34
+ Vary:
35
+ - Accept-Encoding
36
+ - Authorization, Cookie
37
+ Content-Length:
38
+ - '3068'
39
+ Connection:
40
+ - keep-alive
41
+ body:
42
+ encoding: US-ASCII
43
+ string: ! "{\n \"bookmarks\": [\n {\n \"user_id\": 24591,\n
44
+ \ \"read_percent\": \"0.00\",\n \"tags\": [],\n \"date_updated\":
45
+ \"2012-01-16 21:48:53\",\n \"favorite\": false,\n \"id\":
46
+ 1836432,\n \"date_archived\": \"2012-01-16 21:48:53\",\n \"date_opened\":
47
+ null,\n \"article\": {\n \"domain\": \"www.everpix.com\",\n
48
+ \ \"title\": \"Everpix\",\n \"url\": \"https://www.everpix.com/#year=2010\",\n
49
+ \ \"lead_image_url\": null,\n \"author\": null,\n
50
+ \ \"excerpt\": \"From Aug 22, 4:38 PM to Jun 10, 8:05 PM\",\n
51
+ \ \"direction\": \"ltr\",\n \"word_count\": 506,\n
52
+ \ \"date_published\": null,\n \"dek\": null,\n
53
+ \ \"processed\": true,\n \"id\": \"uunhk2gr\"\n
54
+ \ },\n \"article_href\": \"/api/rest/v1/articles/uunhk2gr\",\n
55
+ \ \"date_favorited\": null,\n \"date_added\": \"2011-12-30
56
+ 21:43:48\",\n \"archive\": true\n },\n {\n \"user_id\":
57
+ 24591,\n \"read_percent\": \"0.00\",\n \"tags\": [],\n
58
+ \ \"date_updated\": \"2012-01-16 21:48:58\",\n \"favorite\":
59
+ false,\n \"id\": 1834877,\n \"date_archived\": \"2012-01-16
60
+ 21:48:58\",\n \"date_opened\": null,\n \"article\":
61
+ {\n \"domain\": \"hangar.runway7.net\",\n \"title\":
62
+ \"The Javascript Guide to Objects, Functions, Closures and Scope\",\n \"url\":
63
+ \"http://hangar.runway7.net/javascript-guide-to-objects-functions-scope-prototpyes-closures\",\n
64
+ \ \"lead_image_url\": null,\n \"author\": null,\n
65
+ \ \"excerpt\": \"Dec 26, 2011 Throughout my time writing Javascript
66
+ code, I've come to realize that while I love the language to bits, it is a
67
+ little difficult to understand. A lot of people have attributed this to&hellip;\",\n
68
+ \ \"direction\": \"ltr\",\n \"word_count\": 1941,\n
69
+ \ \"date_published\": null,\n \"dek\": null,\n
70
+ \ \"processed\": true,\n \"id\": \"obhnzmjt\"\n
71
+ \ },\n \"article_href\": \"/api/rest/v1/articles/obhnzmjt\",\n
72
+ \ \"date_favorited\": null,\n \"date_added\": \"2011-12-30
73
+ 19:24:44\",\n \"archive\": true\n }\n ],\n \"meta\":
74
+ {\n \"num_pages\": 28,\n \"page\": 1,\n \"item_count_total\":
75
+ 55,\n \"item_count\": 2\n },\n \"conditions\": {\n \"opened_since\":
76
+ null,\n \"added_until\": \"2012-01-01 00:00:00\",\n \"domain\":
77
+ \"\",\n \"updated_until\": null,\n \"tags\": [],\n \"archive\":
78
+ null,\n \"archived_until\": null,\n \"favorite\": null,\n \"opened_until\":
79
+ null,\n \"archived_since\": null,\n \"favorited_since\": null,\n
80
+ \ \"updated_since\": null,\n \"exclude_accessibility\": \"\",\n
81
+ \ \"per_page\": 2,\n \"favorited_until\": null,\n \"order\":
82
+ \"-date_added\",\n \"only_deleted\": null,\n \"page\": 1,\n
83
+ \ \"added_since\": null,\n \"user\": \"<TOKENS>\"\n }\n}"
84
+ http_version:
85
+ recorded_at: Wed, 20 Feb 2013 04:49:21 GMT
86
+ recorded_with: VCR 2.0.1
@@ -0,0 +1,322 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://www.readability.com/api/rest/v1/articles/eg60dxbv
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - ! '*/*'
12
+ User-Agent:
13
+ - OAuth gem v0.4.7
14
+ Authorization:
15
+ - OAuth oauth_consumer_key="<TOKENS>", oauth_nonce="Tqe0Nusx85HijyKr71dEJFRitn0d9Cn3O4DDGKNjFj8",
16
+ oauth_signature="LmJ8MmzMdlFqyyPDUi0C%2FsbMnKQ%3D", oauth_signature_method="HMAC-SHA1",
17
+ oauth_timestamp="1361335758", oauth_token="<TOKENS>", oauth_version="1.0"
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Content-Type:
24
+ - application/json; charset=utf-8
25
+ Date:
26
+ - Wed, 20 Feb 2013 04:49:15 GMT
27
+ P3p:
28
+ - CP='Legacy Only. Go to https://readability.com/about/terms/ for full terms.'
29
+ Server:
30
+ - nginx/1.2.1
31
+ Set-Cookie:
32
+ - readabilityToken=4FCRyvwJt8enJ7LvesTWKphGwNRyT5h9B3t5KWfP; expires=Wed, 20-Mar-2013
33
+ 04:49:15 GMT; Max-Age=2419200; Path=/
34
+ Vary:
35
+ - Accept-Encoding
36
+ - Authorization, Cookie
37
+ Content-Length:
38
+ - '22030'
39
+ Connection:
40
+ - keep-alive
41
+ body:
42
+ encoding: US-ASCII
43
+ string: ! "{\n \"direction\": \"ltr\",\n \"next_page_href\": null,\n \"author\":
44
+ null,\n \"url\": \"http://www.joezimjs.com/javascript/javascript-design-patterns-decorator/?utm_source=javascriptweekly&utm_medium=email\",\n
45
+ \ \"lead_image_url\": \"http://www.joezimjs.com/wp-content/uploads/decorator_structure.png\",\n
46
+ \ \"title\": \"JavaScript Design Patterns: Decorator\",\n \"excerpt\":
47
+ \"Today I&#x2019;d like to show another JavaScript Design Pattern: the Decorator,
48
+ which is a way to add features to objects without subclassing or adding extra
49
+ attributes. This post continues the&hellip;\",\n \"domain\": \"www.joezimjs.com\",\n
50
+ \ \"word_count\": 1351,\n \"content\": \"<div><div class=\\\"entry-content\\\">\\n\\n\\t\\t<p>Today
51
+ I&#x2019;d like to show another JavaScript Design Pattern: the Decorator,
52
+ which is a way to add features to objects without subclassing or adding extra
53
+ attributes. This post continues the JavaScript Design Patterns series that
54
+ I started several months ago. If you&#x2019;re new to the JavaScript Design
55
+ Patterns series that I&#x2019;m running here, you can find a list of the previous
56
+ and upcoming posts in the series at the <a href=\\\"http://www.joezimjs.com/javascript/javascript-design-patterns-decorator/#series\\\">bottom
57
+ of the post</a>.</p>\\n<h2>Back on Course with Tutorial Posts</h2>\\n<p>After
58
+ the exciting launch of my new <a href=\\\"http://www.joezimjs.com/projects/publish-subscribe-jquery-plugin/\\\"
59
+ title=\\\"JZ Publish/Subscribe Project Page\\\">jQuery plugin</a> it&#x2019;s
60
+ been difficult to bring myself back to normal blogging and back to this series.
61
+ If you don&#x2019;t know what I&#x2019;m talking about, then you should hop
62
+ on over to the <a href=\\\"http://www.joezimjs.com/javascript/new-jquery-plugin-publish-subscribe/\\\"
63
+ title=\\\"New jQuery Plugin: Publish/Subscribe\\\">plugin&#x2019;s announcement
64
+ post</a> (when you&#x2019;re done reading this, of course). However, regardless
65
+ of how this month started out, I&#x2019;ve decided to make a commitment to
66
+ at least 2 &#x201C;tutorial&#x201D; posts per month. I put the word &#x201C;tutorial&#x201D;
67
+ in quotes because I&#x2019;m not sure they can all be generally considered
68
+ tutorials, but I&#x2019;m using the word to mean any post whose purpose is
69
+ to teach, as opposed to announcements or news and the like.</p>\\n<h2>On with
70
+ the Decorator Pattern</h2>\\n<p>Let&#x2019;s return to purpose of this post:
71
+ learning about the decorator pattern. Like I said, this pattern permits us
72
+ to add features to an object without needing to subclass it. Instead we &#x201C;decorate&#x201D;
73
+ (wrap) it with another object with the same interface that has the one feature
74
+ we&#x2019;re adding. To get a better idea of what I&#x2019;m talking about,
75
+ let&#x2019;s first demonstrate how someone lacking knowledge of the decorator
76
+ pattern would attempt this, especially if they&#x2019;re coming from a background
77
+ of classical inheritance.</p>\\n<div class=\\\"geshi javascript\\\">\\n<ol><li
78
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span class=\\\"co1\\\">// Superclass</span></p>\\n</li>\\n<li
79
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span class=\\\"kw2\\\">var</span>
80
+ Car = <span class=\\\"kw2\\\">function</span><span class=\\\"br0\\\">(</span><span
81
+ class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span>&#x2026;<span class=\\\"br0\\\">}</span>;</p>\\n</li>\\n\\n<li
82
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span class=\\\"co1\\\">// Subclasses
83
+ with different features</span></p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span
84
+ class=\\\"kw2\\\">var</span> CarWithPowerLocks = <span class=\\\"kw2\\\">function</span><span
85
+ class=\\\"br0\\\">(</span><span class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span>&#x2026;<span
86
+ class=\\\"br0\\\">}</span>;</p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span
87
+ class=\\\"kw2\\\">var</span> CarWithPowerWindows = <span class=\\\"kw2\\\">function</span><span
88
+ class=\\\"br0\\\">(</span><span class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span>&#x2026;<span
89
+ class=\\\"br0\\\">}</span>;</p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span
90
+ class=\\\"kw2\\\">var</span> CarWithPowerLocksAndPowerWindows = <span class=\\\"kw2\\\">function</span><span
91
+ class=\\\"br0\\\">(</span><span class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span>&#x2026;<span
92
+ class=\\\"br0\\\">}</span>;</p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span
93
+ class=\\\"kw2\\\">var</span> CarWithAC = <span class=\\\"kw2\\\">function</span><span
94
+ class=\\\"br0\\\">(</span><span class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span>&#x2026;<span
95
+ class=\\\"br0\\\">}</span>;</p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span
96
+ class=\\\"kw2\\\">var</span> CarWithACAndPowerLocks = <span class=\\\"kw2\\\">function</span><span
97
+ class=\\\"br0\\\">(</span><span class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span>&#x2026;<span
98
+ class=\\\"br0\\\">}</span>;</p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span
99
+ class=\\\"kw2\\\">var</span> CarWithACAndPowerWindows = <span class=\\\"kw2\\\">function</span><span
100
+ class=\\\"br0\\\">(</span><span class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span>&#x2026;<span
101
+ class=\\\"br0\\\">}</span>;</p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span
102
+ class=\\\"kw2\\\">var</span> CarWithACAndPowerLocksAndPowerWindows = <span
103
+ class=\\\"kw2\\\">function</span><span class=\\\"br0\\\">(</span><span class=\\\"br0\\\">)</span>
104
+ <span class=\\\"br0\\\">{</span>&#x2026;<span class=\\\"br0\\\">}</span>;</p>\\n</li>\\n<li
105
+ class=\\\"li1\\\">\\n\\n</li>\\n</ol></div>\\n<p>As you can see, every combination
106
+ of features needs to be represented by a new &#x201C;class&#x201D;. This might
107
+ be okay if you have only a couple features, but once you start growing the
108
+ number of features, this becomes more and more of a nightmare. Of course,
109
+ if you want to be a jerk, you can do this in an app and leave it for someone
110
+ else to maintain, but I don&#x2019;t know how long you&#x2019;d go before
111
+ being punched in the face if that programmer needs to add another feature
112
+ (or 5 more!).</p>\\n<h2>How the Decorator Pattern can Help</h2>\\n<p>Thankfully
113
+ the Decorator Pattern can make things considerably simpler for us and future
114
+ maintainers of our code. First we&#x2019;ll create the base object that will
115
+ be a <code>Car</code> with no cool features. This also sets up the interface
116
+ that the decorators will use.</p>\\n<div class=\\\"geshi javascript\\\">\\n<ol><li
117
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span class=\\\"kw2\\\">var</span>
118
+ Car = <span class=\\\"kw2\\\">function</span><span class=\\\"br0\\\">(</span><span
119
+ class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span></p>\\n</li>\\n<li
120
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0; &#xA0; console.<span class=\\\"me1\\\">log</span><span
121
+ class=\\\"br0\\\">(</span><span class=\\\"st0\\\">'Assemble: build frame,
122
+ add core parts'</span><span class=\\\"br0\\\">)</span>;</p>\\n</li>\\n<li
123
+ class=\\\"li1\\\">\\n\\n</li>\\n\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span
124
+ class=\\\"co1\\\">// The decorators will also need to implement these functions</span></p>\\n</li>\\n<li
125
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span class=\\\"co1\\\">// to comply
126
+ with Car's interface.</span></p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\">Car.<span
127
+ class=\\\"me1\\\">prototype</span> = <span class=\\\"br0\\\">{</span></p>\\n</li>\\n<li
128
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0; &#xA0; start: <span class=\\\"kw2\\\">function</span><span
129
+ class=\\\"br0\\\">(</span><span class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span></p>\\n</li>\\n<li
130
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0; &#xA0; &#xA0; &#xA0; console.<span
131
+ class=\\\"me1\\\">log</span><span class=\\\"br0\\\">(</span><span class=\\\"st0\\\">'The
132
+ engine starts with roar!'</span><span class=\\\"br0\\\">)</span>;</p>\\n</li>\\n<li
133
+ class=\\\"li1\\\">\\n\\n</li>\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0;
134
+ &#xA0; drive: <span class=\\\"kw2\\\">function</span><span class=\\\"br0\\\">(</span><span
135
+ class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span></p>\\n</li>\\n<li
136
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0; &#xA0; &#xA0; &#xA0; console.<span
137
+ class=\\\"me1\\\">log</span><span class=\\\"br0\\\">(</span><span class=\\\"st0\\\">'Away
138
+ we go!'</span><span class=\\\"br0\\\">)</span>;</p>\\n</li>\\n<li class=\\\"li1\\\">\\n\\n</li>\\n<li
139
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0; &#xA0; getPrice: <span class=\\\"kw2\\\">function</span><span
140
+ class=\\\"br0\\\">(</span><span class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span></p>\\n</li>\\n<li
141
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0; &#xA0; &#xA0; &#xA0; <span
142
+ class=\\\"kw1\\\">return</span> <span class=\\\"nu0\\\">11000.00</span>;</p>\\n</li>\\n<li
143
+ class=\\\"li1\\\">\\n\\n</li>\\n<li class=\\\"li1\\\">\\n\\n</li>\\n</ol></div>\\n<p>Now
144
+ we&#x2019;ll create the decorator &#x201C;class&#x201D; that each of the decorator
145
+ will inherit from. You&#x2019;ll notice that each of the functions simply
146
+ pass the call on to the <code>Car</code> that they&#x2019;re wrapping. In
147
+ this case the only functions that will be overridden are <code>assemble</code>
148
+ and <code>getPrice</code>.</p>\\n<div class=\\\"geshi javascript\\\">\\n<ol><li
149
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span class=\\\"co1\\\">// You need
150
+ to pass in the Car (or CarDecorator) in order to</span></p>\\n</li>\\n<li
151
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span class=\\\"co1\\\">// be able
152
+ to add features to it.</span></p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span
153
+ class=\\\"kw2\\\">var</span> CarDecorator = <span class=\\\"kw2\\\">function</span><span
154
+ class=\\\"br0\\\">(</span>car<span class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span></p>\\n</li>\\n<li
155
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0; &#xA0; <span class=\\\"kw1\\\">this</span>.<span
156
+ class=\\\"me1\\\">car</span> = car;</p>\\n</li>\\n<li class=\\\"li1\\\">\\n\\n</li>\\n\\n<li
157
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span class=\\\"co1\\\">// CarDecorator
158
+ is implementing the same interface</span></p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p
159
+ class=\\\"de1\\\">CarDecorator.<span class=\\\"me1\\\">prototype</span> =
160
+ <span class=\\\"br0\\\">{</span></p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p
161
+ class=\\\"de1\\\">&#xA0; &#xA0; start: <span class=\\\"kw2\\\">function</span><span
162
+ class=\\\"br0\\\">(</span><span class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span></p>\\n</li>\\n<li
163
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0; &#xA0; &#xA0; &#xA0; <span
164
+ class=\\\"kw1\\\">this</span>.<span class=\\\"me1\\\">car</span>.<span class=\\\"me1\\\">start</span><span
165
+ class=\\\"br0\\\">(</span><span class=\\\"br0\\\">)</span>;</p>\\n</li>\\n<li
166
+ class=\\\"li1\\\">\\n\\n</li>\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0;
167
+ &#xA0; drive: <span class=\\\"kw2\\\">function</span><span class=\\\"br0\\\">(</span><span
168
+ class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span></p>\\n</li>\\n<li
169
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0; &#xA0; &#xA0; &#xA0; <span
170
+ class=\\\"kw1\\\">this</span>.<span class=\\\"me1\\\">car</span>.<span class=\\\"me1\\\">drive</span><span
171
+ class=\\\"br0\\\">(</span><span class=\\\"br0\\\">)</span>;</p>\\n</li>\\n<li
172
+ class=\\\"li1\\\">\\n\\n</li>\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0;
173
+ &#xA0; getPrice: <span class=\\\"kw2\\\">function</span><span class=\\\"br0\\\">(</span><span
174
+ class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span></p>\\n</li>\\n<li
175
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0; &#xA0; &#xA0; &#xA0; <span
176
+ class=\\\"kw1\\\">return</span> <span class=\\\"kw1\\\">this</span>.<span
177
+ class=\\\"me1\\\">car</span>.<span class=\\\"me1\\\">getPrice</span><span
178
+ class=\\\"br0\\\">(</span><span class=\\\"br0\\\">)</span>;</p>\\n</li>\\n<li
179
+ class=\\\"li1\\\">\\n\\n</li>\\n<li class=\\\"li1\\\">\\n\\n</li>\\n</ol></div>\\n<p>Next
180
+ we create a decorator object for each feature and override the parent&#x2019;s
181
+ functions whenever we want to add more or different functionality there.</p>\\n<div
182
+ class=\\\"geshi javascript\\\">\\n<ol><li class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span
183
+ class=\\\"kw2\\\">var</span> PowerLocksDecorator = <span class=\\\"kw2\\\">function</span><span
184
+ class=\\\"br0\\\">(</span>car<span class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span></p>\\n</li>\\n<li
185
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0; &#xA0; <span class=\\\"co1\\\">//
186
+ JavaScript's way of calling a parent class' constructor</span></p>\\n</li>\\n<li
187
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0; &#xA0; CarDecorator.<span
188
+ class=\\\"me1\\\">call</span><span class=\\\"br0\\\">(</span><span class=\\\"kw1\\\">this</span>,
189
+ car<span class=\\\"br0\\\">)</span>;</p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p
190
+ class=\\\"de1\\\">&#xA0; &#xA0; console.<span class=\\\"me1\\\">log</span><span
191
+ class=\\\"br0\\\">(</span><span class=\\\"st0\\\">'Assemble: add power locks'</span><span
192
+ class=\\\"br0\\\">)</span>;</p>\\n</li>\\n<li class=\\\"li1\\\">\\n\\n</li>\\n<li
193
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">PowerLocksDecorator.<span class=\\\"me1\\\">prototype</span>
194
+ = <span class=\\\"kw2\\\">new</span> CarDecorator<span class=\\\"br0\\\">(</span><span
195
+ class=\\\"br0\\\">)</span>;</p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\">PowerLocksDecorator.<span
196
+ class=\\\"me1\\\">prototype</span>.<span class=\\\"me1\\\">drive</span> =
197
+ <span class=\\\"kw2\\\">function</span><span class=\\\"br0\\\">(</span><span
198
+ class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span></p>\\n</li>\\n<li
199
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0; &#xA0; <span class=\\\"co1\\\">//
200
+ You can either do this</span></p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0;
201
+ &#xA0; <span class=\\\"kw1\\\">this</span>.<span class=\\\"me1\\\">car</span>.<span
202
+ class=\\\"me1\\\">drive</span><span class=\\\"br0\\\">(</span><span class=\\\"br0\\\">)</span>;</p>\\n</li>\\n<li
203
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0; &#xA0; <span class=\\\"co1\\\">//
204
+ or you can call the parent's drive function:</span></p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p
205
+ class=\\\"de1\\\">&#xA0; &#xA0; <span class=\\\"co1\\\">// CarDecorator.prototype.drive.call(this);</span></p>\\n</li>\\n<li
206
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0; &#xA0; console.<span class=\\\"me1\\\">log</span><span
207
+ class=\\\"br0\\\">(</span><span class=\\\"st0\\\">'The doors automatically
208
+ lock'</span><span class=\\\"br0\\\">)</span>;</p>\\n</li>\\n<li class=\\\"li1\\\">\\n\\n</li>\\n\\n<li
209
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span class=\\\"kw2\\\">var</span>
210
+ PowerWindowsDecorator = <span class=\\\"kw2\\\">function</span><span class=\\\"br0\\\">(</span>car<span
211
+ class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span></p>\\n</li>\\n<li
212
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0; &#xA0; CarDecorator.<span
213
+ class=\\\"me1\\\">call</span><span class=\\\"br0\\\">(</span><span class=\\\"kw1\\\">this</span>,
214
+ car<span class=\\\"br0\\\">)</span>;</p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p
215
+ class=\\\"de1\\\">&#xA0; &#xA0; console.<span class=\\\"me1\\\">log</span><span
216
+ class=\\\"br0\\\">(</span><span class=\\\"st0\\\">'Assemble: add power windows'</span><span
217
+ class=\\\"br0\\\">)</span>;</p>\\n</li>\\n<li class=\\\"li1\\\">\\n\\n</li>\\n<li
218
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">PowerWindowsDecorator.<span class=\\\"me1\\\">prototype</span>
219
+ = <span class=\\\"kw2\\\">new</span> CarDecorator<span class=\\\"br0\\\">(</span><span
220
+ class=\\\"br0\\\">)</span>;</p>\\n</li>\\n\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span
221
+ class=\\\"kw2\\\">var</span> ACDecorator = <span class=\\\"kw2\\\">function</span><span
222
+ class=\\\"br0\\\">(</span>car<span class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span></p>\\n</li>\\n<li
223
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0; &#xA0; CarDecorator.<span
224
+ class=\\\"me1\\\">call</span><span class=\\\"br0\\\">(</span><span class=\\\"kw1\\\">this</span>,
225
+ car<span class=\\\"br0\\\">)</span>;</p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p
226
+ class=\\\"de1\\\">&#xA0; &#xA0; console.<span class=\\\"me1\\\">log</span><span
227
+ class=\\\"br0\\\">(</span><span class=\\\"st0\\\">'Assemble: add A/C unit'</span><span
228
+ class=\\\"br0\\\">)</span>;</p>\\n</li>\\n<li class=\\\"li1\\\">\\n\\n</li>\\n<li
229
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">ACDecorator.<span class=\\\"me1\\\">prototype</span>
230
+ = <span class=\\\"kw2\\\">new</span> CarDecorator<span class=\\\"br0\\\">(</span><span
231
+ class=\\\"br0\\\">)</span>;</p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\">ACDecorator.<span
232
+ class=\\\"me1\\\">prototype</span>.<span class=\\\"me1\\\">start</span> =
233
+ <span class=\\\"kw2\\\">function</span><span class=\\\"br0\\\">(</span><span
234
+ class=\\\"br0\\\">)</span> <span class=\\\"br0\\\">{</span></p>\\n</li>\\n<li
235
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0; &#xA0; <span class=\\\"kw1\\\">this</span>.<span
236
+ class=\\\"me1\\\">car</span>.<span class=\\\"me1\\\">start</span><span class=\\\"br0\\\">(</span><span
237
+ class=\\\"br0\\\">)</span>;</p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\">&#xA0;
238
+ &#xA0; console.<span class=\\\"me1\\\">log</span><span class=\\\"br0\\\">(</span><span
239
+ class=\\\"st0\\\">'The cool air starts blowing.'</span><span class=\\\"br0\\\">)</span>;</p>\\n</li>\\n<li
240
+ class=\\\"li1\\\">\\n\\n</li>\\n</ol></div>\\n<p>Notice that we always call
241
+ the same function on the wrapped object as well. This is somewhat similar
242
+ to the way a <a href=\\\"http://www.joezimjs.com/javascript/javascript-design-patterns-composite/\\\"
243
+ title=\\\"JavaScript Design Patterns: Composite\\\">composite</a> works, though
244
+ the similarities between the two patterns pretty much end there. In this example,
245
+ we always call the wrapped object&#x2019;s function first before adding in
246
+ the new information from the decorator (if any exists for that function).
247
+ This creates the desired effect of having the core functions executing first,
248
+ \ but other applications might require different order, or possibly might
249
+ not even call the wrapped object&#x2019;s function if the intention is to
250
+ completely change the functionality rather than adding on to it.</p>\\n<p><img
251
+ src=\\\"http://www.joezimjs.com/wp-content/uploads/decorator_structure.png\\\"
252
+ alt=\\\"Structure of the Decorator Pattern\\\" title=\\\"Structure of the
253
+ Decorator Pattern\\\" width=\\\"570\\\" class=\\\"alignnone size-full wp-image-351\\\"></p>\\n<h2>Seeing
254
+ our JavaScript in Action</h2>\\n<p>So how do we use the code that we just
255
+ spent this entire time making? Well the actual code is below, but maybe I
256
+ should do a little explaining first. Of course, you&#x2019;re free to skip
257
+ this and jump straight to the code if you think you&#x2019;ve got it down.</p>\\n<p>First
258
+ we create a <code>Car</code> object. Then, we create the decorator for the
259
+ feature we want to add onto it and pass the <code>Car</code> into its constructor.
260
+ The object returned from the decorator&#x2019;s constructor is assigned back
261
+ to the variable that previously held the <code>Car</code> object because since
262
+ the decorators use the same interface, they too can be considered <code>Car</code>s.
263
+ We keep adding more features until we&#x2019;re satisfied and then we have
264
+ our desired car that we can do whatever we want with.</p>\\n<div class=\\\"geshi
265
+ javascript\\\">\\n<ol><li class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span
266
+ class=\\\"kw2\\\">var</span> car = <span class=\\\"kw2\\\">new</span> Car<span
267
+ class=\\\"br0\\\">(</span><span class=\\\"br0\\\">)</span>; &#xA0; &#xA0;
268
+ &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<span class=\\\"co1\\\">//
269
+ log \\\"Assemble: build frame, add core parts\\\"</span></p>\\n</li>\\n\\n<li
270
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span class=\\\"co1\\\">// give
271
+ the car some power windows</span></p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p
272
+ class=\\\"de1\\\">car = <span class=\\\"kw2\\\">new</span> PowerWindowDecorator<span
273
+ class=\\\"br0\\\">(</span>car<span class=\\\"br0\\\">)</span>; &#xA0; &#xA0;<span
274
+ class=\\\"co1\\\">// log \\\"Assemble: add power windows\\\"</span></p>\\n</li>\\n\\n<li
275
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span class=\\\"co1\\\">// now some
276
+ power locks and A/C</span></p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\">car
277
+ = <span class=\\\"kw2\\\">new</span> PowerLocksDecorator<span class=\\\"br0\\\">(</span>car<span
278
+ class=\\\"br0\\\">)</span>; &#xA0; &#xA0; <span class=\\\"co1\\\">// log \\\"Assemble:
279
+ add power locks\\\"</span></p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p class=\\\"de1\\\">car
280
+ = <span class=\\\"kw2\\\">new</span> ACDecorator<span class=\\\"br0\\\">(</span>car<span
281
+ class=\\\"br0\\\">)</span>; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; <span
282
+ class=\\\"co1\\\">// log \\\"Assemble: add A/C unit\\\"</span></p>\\n</li>\\n\\n<li
283
+ class=\\\"li1\\\">\\n<p class=\\\"de1\\\"><span class=\\\"co1\\\">// let's
284
+ start this bad boy up and take a drive!</span></p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p
285
+ class=\\\"de1\\\">car.<span class=\\\"me1\\\">start</span><span class=\\\"br0\\\">(</span><span
286
+ class=\\\"br0\\\">)</span>; <span class=\\\"co1\\\">// log 'The engine starts
287
+ with roar!' and 'The cool air starts blowing.'</span></p>\\n</li>\\n<li class=\\\"li1\\\">\\n<p
288
+ class=\\\"de1\\\">car.<span class=\\\"me1\\\">drive</span><span class=\\\"br0\\\">(</span><span
289
+ class=\\\"br0\\\">)</span>; <span class=\\\"co1\\\">// log 'Away we go!' and
290
+ 'The doors automatically lock'</span></p>\\n</li>\\n</ol></div>\\n<h2>Concluding
291
+ this Fiasco</h2>\\n<p>The Decorator proves to be a nice way of maintaining
292
+ differentiating features for an object and definitely helps improve maintainability
293
+ over the long haul. You may have noticed, though, that I didn&#x2019;t include
294
+ any code to make sure that we didn&#x2019;t accidentally add the same feature
295
+ more than once. Don&#x2019;t worry, the next post will give us a clean answer
296
+ without having to change any of the code we&#x2019;ve already written. Adding
297
+ checks into the decorators to accomplish would prove to be annoying.</p>\\n<p>If
298
+ you&#x2019;ve got something to say about the Decorator Pattern, this post,
299
+ or even just JavaScript in general, make your voice heard in the comments
300
+ section below. I&#x2019;d love to hear it, even if you&#x2019;re just letting
301
+ me know I&#x2019;m an idiot (just try to make it more constructive than &#x201C;you&#x2019;re
302
+ an idiot&#x201D;). We all have to grow somehow. Also, I&#x2019;d greatly appreciate
303
+ if you&#x2019;d use the social sharing buttons below to spread the word about
304
+ this post. Little guys like me don&#x2019;t get big without some help. Happy
305
+ Coding!</p>\\n<p id=\\\"series\\\">JavaScript Design Patterns series:</p>\\n<ol
306
+ class=\\\"yarpp-posts\\\"><li><a href=\\\"http://www.joezimjs.com/javascript/javascript-design-patterns-adapter/\\\"
307
+ rel=\\\"bookmark\\\" title=\\\"JavaScript Design Patterns: Adapter\\\">JavaScript
308
+ Design Patterns: Adapter</a></li>\\n<li><a href=\\\"http://www.joezimjs.com/javascript/javascript-design-patterns-singleton/\\\"
309
+ rel=\\\"bookmark\\\" title=\\\"JavaScript Design Patterns: Singleton\\\">JavaScript
310
+ Design Patterns: Singleton</a></li>\\n<li><a href=\\\"http://www.joezimjs.com/javascript/javascript-design-patterns-composite/\\\"
311
+ rel=\\\"bookmark\\\" title=\\\"JavaScript Design Patterns: Composite\\\">JavaScript
312
+ Design Patterns: Composite</a></li>\\n<li><a href=\\\"http://www.joezimjs.com/javascript/javascript-design-patterns-bridge/\\\"
313
+ rel=\\\"bookmark\\\" title=\\\"JavaScript Design Patterns: Bridge\\\">JavaScript
314
+ Design Patterns: Bridge</a></li>\\n<li><a href=\\\"http://www.joezimjs.com/javascript/javascript-design-patterns-facade/\\\"
315
+ rel=\\\"bookmark\\\" title=\\\"JavaScript Design Patterns: Facade\\\">JavaScript
316
+ Design Patterns: Facade</a></li>\\n</ol><br class=\\\"clear\\\"></div>\\n\\n\\t</div>\",\n
317
+ \ \"date_published\": null,\n \"dek\": null,\n \"processed\": true,\n
318
+ \ \"content_size\": 20088,\n \"short_url\": \"http://rdd.me/eg60dxbv\",\n
319
+ \ \"id\": \"eg60dxbv\"\n}"
320
+ http_version:
321
+ recorded_at: Wed, 20 Feb 2013 04:49:19 GMT
322
+ recorded_with: VCR 2.0.1