readit 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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