parsable 0.1.4 → 0.2.0
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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/fixtures/vcr_cassettes/Parsable_Remote/_method_missing/url/cant_connect/bad_response_code/returns_nil.yml +138 -0
- data/fixtures/vcr_cassettes/Parsable_Remote/_method_missing/url/cant_connect/returns_nil.yml +138 -0
- data/fixtures/vcr_cassettes/Parsable_Remote/_method_missing/url/returns_the_body.yml +50 -0
- data/fixtures/vcr_cassettes/Parsable_Remote/_method_missing/url/with_query_params/uses_them_in_the_request.yml +46 -0
- data/lib/parsable/context.rb +9 -8
- data/lib/parsable/parsed_item.rb +1 -2
- data/lib/parsable/parser.rb +11 -20
- data/lib/parsable/remote.rb +46 -0
- data/lib/parsable/version.rb +1 -1
- data/lib/parsable.rb +2 -1
- data/parsable.gemspec +4 -0
- data/spec/context_spec.rb +1 -1
- data/spec/parsable_spec.rb +6 -6
- data/spec/parser_spec.rb +23 -34
- data/spec/remote_spec.rb +50 -0
- data/spec/spec_helper.rb +9 -1
- metadata +51 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3647c899ec5e6def562f04586513c86e474abf84
|
4
|
+
data.tar.gz: 8bba282b7f3b95fc81df04c3e743ba41a2c6e454
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b58d2729bfe483afa34a9328cc955d8f10bdb49592146cc6eb0bafd4bfb9eb46b9f665324933496095b320c209406e59a2f91cc9acafa2620f1777b5e730a4f9
|
7
|
+
data.tar.gz: 182c30d0c82e7a69b6a8ff9e8ec5b54b4b0bf6dc7cbca2c9076872116598f6410e0d15be4d872419ceec9ec53bdf7bdd22545b6ff8ec88b17da3011c473cae76
|
data/README.md
CHANGED
@@ -51,7 +51,7 @@ Parsable.crunch(\
|
|
51
51
|
# note: {{random.integer}} is implemented by Time.now.to_i, so not really random at all.
|
52
52
|
|
53
53
|
Parsable.crunch(:string => "{{date.today}} {{date.year}} {{time.now}}")
|
54
|
-
# "2014-02-19 2014 2014-02-19 17:35:35 -0500"
|
54
|
+
# "2014-02-19 2014 2014-02-19 17:35:35 -0500"
|
55
55
|
```
|
56
56
|
|
57
57
|
## Contributing
|
@@ -0,0 +1,138 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://httpstat.us/500
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept-Encoding:
|
11
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
12
|
+
Accept:
|
13
|
+
- '*/*'
|
14
|
+
User-Agent:
|
15
|
+
- Ruby
|
16
|
+
Host:
|
17
|
+
- httpstat.us
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 500
|
21
|
+
message: Internal Server Error
|
22
|
+
headers:
|
23
|
+
Cache-Control:
|
24
|
+
- private
|
25
|
+
Content-Length:
|
26
|
+
- '25'
|
27
|
+
Content-Type:
|
28
|
+
- text/plain; charset=utf-8
|
29
|
+
Server:
|
30
|
+
- Microsoft-IIS/8.0
|
31
|
+
X-Aspnetmvc-Version:
|
32
|
+
- '5.1'
|
33
|
+
X-Aspnet-Version:
|
34
|
+
- 4.0.30319
|
35
|
+
X-Powered-By:
|
36
|
+
- ASP.NET
|
37
|
+
Access-Control-Allow-Origin:
|
38
|
+
- '*'
|
39
|
+
Set-Cookie:
|
40
|
+
- ARRAffinity=ce89bc5d89e3eae7a38e90a2582b973f890225b3bddc47e95c77a1d7831a8a71;Path=/;Domain=httpstat.us
|
41
|
+
Date:
|
42
|
+
- Fri, 11 Dec 2015 22:52:19 GMT
|
43
|
+
body:
|
44
|
+
encoding: UTF-8
|
45
|
+
string: 500 Internal Server Error
|
46
|
+
http_version:
|
47
|
+
recorded_at: Fri, 11 Dec 2015 22:52:19 GMT
|
48
|
+
- request:
|
49
|
+
method: get
|
50
|
+
uri: http://httpstat.us/500
|
51
|
+
body:
|
52
|
+
encoding: US-ASCII
|
53
|
+
string: ''
|
54
|
+
headers:
|
55
|
+
Accept-Encoding:
|
56
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
57
|
+
Accept:
|
58
|
+
- '*/*'
|
59
|
+
User-Agent:
|
60
|
+
- Ruby
|
61
|
+
Host:
|
62
|
+
- httpstat.us
|
63
|
+
response:
|
64
|
+
status:
|
65
|
+
code: 500
|
66
|
+
message: Internal Server Error
|
67
|
+
headers:
|
68
|
+
Cache-Control:
|
69
|
+
- private
|
70
|
+
Content-Length:
|
71
|
+
- '25'
|
72
|
+
Content-Type:
|
73
|
+
- text/plain; charset=utf-8
|
74
|
+
Server:
|
75
|
+
- Microsoft-IIS/8.0
|
76
|
+
X-Aspnetmvc-Version:
|
77
|
+
- '5.1'
|
78
|
+
X-Aspnet-Version:
|
79
|
+
- 4.0.30319
|
80
|
+
X-Powered-By:
|
81
|
+
- ASP.NET
|
82
|
+
Access-Control-Allow-Origin:
|
83
|
+
- '*'
|
84
|
+
Set-Cookie:
|
85
|
+
- ARRAffinity=ce89bc5d89e3eae7a38e90a2582b973f890225b3bddc47e95c77a1d7831a8a71;Path=/;Domain=httpstat.us
|
86
|
+
Date:
|
87
|
+
- Fri, 11 Dec 2015 22:52:19 GMT
|
88
|
+
body:
|
89
|
+
encoding: UTF-8
|
90
|
+
string: 500 Internal Server Error
|
91
|
+
http_version:
|
92
|
+
recorded_at: Fri, 11 Dec 2015 22:52:19 GMT
|
93
|
+
- request:
|
94
|
+
method: get
|
95
|
+
uri: http://httpstat.us/500
|
96
|
+
body:
|
97
|
+
encoding: US-ASCII
|
98
|
+
string: ''
|
99
|
+
headers:
|
100
|
+
Accept-Encoding:
|
101
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
102
|
+
Accept:
|
103
|
+
- '*/*'
|
104
|
+
User-Agent:
|
105
|
+
- Ruby
|
106
|
+
Host:
|
107
|
+
- httpstat.us
|
108
|
+
response:
|
109
|
+
status:
|
110
|
+
code: 500
|
111
|
+
message: Internal Server Error
|
112
|
+
headers:
|
113
|
+
Cache-Control:
|
114
|
+
- private
|
115
|
+
Content-Length:
|
116
|
+
- '25'
|
117
|
+
Content-Type:
|
118
|
+
- text/plain; charset=utf-8
|
119
|
+
Server:
|
120
|
+
- Microsoft-IIS/8.0
|
121
|
+
X-Aspnetmvc-Version:
|
122
|
+
- '5.1'
|
123
|
+
X-Aspnet-Version:
|
124
|
+
- 4.0.30319
|
125
|
+
X-Powered-By:
|
126
|
+
- ASP.NET
|
127
|
+
Access-Control-Allow-Origin:
|
128
|
+
- '*'
|
129
|
+
Set-Cookie:
|
130
|
+
- ARRAffinity=ce89bc5d89e3eae7a38e90a2582b973f890225b3bddc47e95c77a1d7831a8a71;Path=/;Domain=httpstat.us
|
131
|
+
Date:
|
132
|
+
- Fri, 11 Dec 2015 22:52:19 GMT
|
133
|
+
body:
|
134
|
+
encoding: UTF-8
|
135
|
+
string: 500 Internal Server Error
|
136
|
+
http_version:
|
137
|
+
recorded_at: Fri, 11 Dec 2015 22:52:19 GMT
|
138
|
+
recorded_with: VCR 3.0.0
|
@@ -0,0 +1,138 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://httpstat.us/500
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept-Encoding:
|
11
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
12
|
+
Accept:
|
13
|
+
- '*/*'
|
14
|
+
User-Agent:
|
15
|
+
- Ruby
|
16
|
+
Host:
|
17
|
+
- httpstat.us
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 500
|
21
|
+
message: Internal Server Error
|
22
|
+
headers:
|
23
|
+
Cache-Control:
|
24
|
+
- private
|
25
|
+
Content-Length:
|
26
|
+
- '25'
|
27
|
+
Content-Type:
|
28
|
+
- text/plain; charset=utf-8
|
29
|
+
Server:
|
30
|
+
- Microsoft-IIS/8.0
|
31
|
+
X-Aspnetmvc-Version:
|
32
|
+
- '5.1'
|
33
|
+
X-Aspnet-Version:
|
34
|
+
- 4.0.30319
|
35
|
+
X-Powered-By:
|
36
|
+
- ASP.NET
|
37
|
+
Access-Control-Allow-Origin:
|
38
|
+
- '*'
|
39
|
+
Set-Cookie:
|
40
|
+
- ARRAffinity=ce89bc5d89e3eae7a38e90a2582b973f890225b3bddc47e95c77a1d7831a8a71;Path=/;Domain=httpstat.us
|
41
|
+
Date:
|
42
|
+
- Fri, 11 Dec 2015 22:46:56 GMT
|
43
|
+
body:
|
44
|
+
encoding: UTF-8
|
45
|
+
string: 500 Internal Server Error
|
46
|
+
http_version:
|
47
|
+
recorded_at: Fri, 11 Dec 2015 22:46:56 GMT
|
48
|
+
- request:
|
49
|
+
method: get
|
50
|
+
uri: http://httpstat.us/500
|
51
|
+
body:
|
52
|
+
encoding: US-ASCII
|
53
|
+
string: ''
|
54
|
+
headers:
|
55
|
+
Accept-Encoding:
|
56
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
57
|
+
Accept:
|
58
|
+
- '*/*'
|
59
|
+
User-Agent:
|
60
|
+
- Ruby
|
61
|
+
Host:
|
62
|
+
- httpstat.us
|
63
|
+
response:
|
64
|
+
status:
|
65
|
+
code: 500
|
66
|
+
message: Internal Server Error
|
67
|
+
headers:
|
68
|
+
Cache-Control:
|
69
|
+
- private
|
70
|
+
Content-Length:
|
71
|
+
- '25'
|
72
|
+
Content-Type:
|
73
|
+
- text/plain; charset=utf-8
|
74
|
+
Server:
|
75
|
+
- Microsoft-IIS/8.0
|
76
|
+
X-Aspnetmvc-Version:
|
77
|
+
- '5.1'
|
78
|
+
X-Aspnet-Version:
|
79
|
+
- 4.0.30319
|
80
|
+
X-Powered-By:
|
81
|
+
- ASP.NET
|
82
|
+
Access-Control-Allow-Origin:
|
83
|
+
- '*'
|
84
|
+
Set-Cookie:
|
85
|
+
- ARRAffinity=ce89bc5d89e3eae7a38e90a2582b973f890225b3bddc47e95c77a1d7831a8a71;Path=/;Domain=httpstat.us
|
86
|
+
Date:
|
87
|
+
- Fri, 11 Dec 2015 22:46:55 GMT
|
88
|
+
body:
|
89
|
+
encoding: UTF-8
|
90
|
+
string: 500 Internal Server Error
|
91
|
+
http_version:
|
92
|
+
recorded_at: Fri, 11 Dec 2015 22:46:56 GMT
|
93
|
+
- request:
|
94
|
+
method: get
|
95
|
+
uri: http://httpstat.us/500
|
96
|
+
body:
|
97
|
+
encoding: US-ASCII
|
98
|
+
string: ''
|
99
|
+
headers:
|
100
|
+
Accept-Encoding:
|
101
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
102
|
+
Accept:
|
103
|
+
- '*/*'
|
104
|
+
User-Agent:
|
105
|
+
- Ruby
|
106
|
+
Host:
|
107
|
+
- httpstat.us
|
108
|
+
response:
|
109
|
+
status:
|
110
|
+
code: 500
|
111
|
+
message: Internal Server Error
|
112
|
+
headers:
|
113
|
+
Cache-Control:
|
114
|
+
- private
|
115
|
+
Content-Length:
|
116
|
+
- '25'
|
117
|
+
Content-Type:
|
118
|
+
- text/plain; charset=utf-8
|
119
|
+
Server:
|
120
|
+
- Microsoft-IIS/8.0
|
121
|
+
X-Aspnetmvc-Version:
|
122
|
+
- '5.1'
|
123
|
+
X-Aspnet-Version:
|
124
|
+
- 4.0.30319
|
125
|
+
X-Powered-By:
|
126
|
+
- ASP.NET
|
127
|
+
Access-Control-Allow-Origin:
|
128
|
+
- '*'
|
129
|
+
Set-Cookie:
|
130
|
+
- ARRAffinity=ce89bc5d89e3eae7a38e90a2582b973f890225b3bddc47e95c77a1d7831a8a71;Path=/;Domain=httpstat.us
|
131
|
+
Date:
|
132
|
+
- Fri, 11 Dec 2015 22:46:56 GMT
|
133
|
+
body:
|
134
|
+
encoding: UTF-8
|
135
|
+
string: 500 Internal Server Error
|
136
|
+
http_version:
|
137
|
+
recorded_at: Fri, 11 Dec 2015 22:46:56 GMT
|
138
|
+
recorded_with: VCR 3.0.0
|
@@ -0,0 +1,50 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://httpstat.us/200
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept-Encoding:
|
11
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
12
|
+
Accept:
|
13
|
+
- '*/*'
|
14
|
+
User-Agent:
|
15
|
+
- Ruby
|
16
|
+
Host:
|
17
|
+
- httpstat.us
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 200
|
21
|
+
message: OK
|
22
|
+
headers:
|
23
|
+
Cache-Control:
|
24
|
+
- private
|
25
|
+
Content-Length:
|
26
|
+
- '126'
|
27
|
+
Content-Type:
|
28
|
+
- text/plain; charset=utf-8
|
29
|
+
Vary:
|
30
|
+
- Accept-Encoding
|
31
|
+
Server:
|
32
|
+
- Microsoft-IIS/8.0
|
33
|
+
X-Aspnetmvc-Version:
|
34
|
+
- '5.1'
|
35
|
+
X-Aspnet-Version:
|
36
|
+
- 4.0.30319
|
37
|
+
X-Powered-By:
|
38
|
+
- ASP.NET
|
39
|
+
Access-Control-Allow-Origin:
|
40
|
+
- '*'
|
41
|
+
Set-Cookie:
|
42
|
+
- ARRAffinity=ce89bc5d89e3eae7a38e90a2582b973f890225b3bddc47e95c77a1d7831a8a71;Path=/;Domain=httpstat.us
|
43
|
+
Date:
|
44
|
+
- Fri, 11 Dec 2015 22:46:56 GMT
|
45
|
+
body:
|
46
|
+
encoding: UTF-8
|
47
|
+
string: 200 OK
|
48
|
+
http_version:
|
49
|
+
recorded_at: Fri, 11 Dec 2015 22:46:56 GMT
|
50
|
+
recorded_with: VCR 3.0.0
|
@@ -0,0 +1,46 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://httpbin.org/get?query1=q1&query2=q2
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept-Encoding:
|
11
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
12
|
+
Accept:
|
13
|
+
- '*/*'
|
14
|
+
User-Agent:
|
15
|
+
- Ruby
|
16
|
+
Host:
|
17
|
+
- httpbin.org
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 200
|
21
|
+
message: OK
|
22
|
+
headers:
|
23
|
+
Server:
|
24
|
+
- nginx
|
25
|
+
Date:
|
26
|
+
- Fri, 11 Dec 2015 22:46:56 GMT
|
27
|
+
Content-Type:
|
28
|
+
- application/json
|
29
|
+
Content-Length:
|
30
|
+
- '311'
|
31
|
+
Connection:
|
32
|
+
- keep-alive
|
33
|
+
Access-Control-Allow-Origin:
|
34
|
+
- '*'
|
35
|
+
Access-Control-Allow-Credentials:
|
36
|
+
- 'true'
|
37
|
+
body:
|
38
|
+
encoding: UTF-8
|
39
|
+
string: "{\n \"args\": {\n \"query1\": \"q1\", \n \"query2\": \"q2\"\n
|
40
|
+
\ }, \n \"headers\": {\n \"Accept\": \"*/*\", \n \"Accept-Encoding\":
|
41
|
+
\"gzip;q=1.0,deflate;q=0.6,identity;q=0.3\", \n \"Host\": \"httpbin.org\",
|
42
|
+
\n \"User-Agent\": \"Ruby\"\n }, \n \"origin\": \"104.200.143.243\",
|
43
|
+
\n \"url\": \"http://httpbin.org/get?query1=q1&query2=q2\"\n}\n"
|
44
|
+
http_version:
|
45
|
+
recorded_at: Fri, 11 Dec 2015 22:46:56 GMT
|
46
|
+
recorded_with: VCR 3.0.0
|
data/lib/parsable/context.rb
CHANGED
@@ -14,30 +14,31 @@ module Parsable
|
|
14
14
|
:date => OpenStruct.new(:today => Date.today.to_s, :year => Date.today.year.to_s),
|
15
15
|
:time => OpenStruct.new(:now => Time.now.to_s),
|
16
16
|
:custom => OpenStruct.new
|
17
|
-
})
|
18
|
-
|
17
|
+
})
|
18
|
+
|
19
|
+
@variables.store(:remote, Parsable::Remote.new)
|
19
20
|
end
|
20
21
|
|
21
22
|
def custom_store attribute, value
|
22
|
-
|
23
|
+
store :custom, attribute, value
|
23
24
|
end
|
24
25
|
|
25
26
|
def system_store object_key, attribute, value
|
26
|
-
|
27
|
+
store object_key, attribute, value
|
27
28
|
end
|
28
29
|
|
29
30
|
def read object_key, attribute
|
30
|
-
|
31
|
+
object(object_key).send(attribute.to_sym)
|
31
32
|
end
|
32
33
|
|
33
34
|
private
|
34
35
|
|
35
|
-
def
|
36
|
+
def object object_key
|
36
37
|
variables[object_key.to_sym] ||= OpenStruct.new
|
37
38
|
end
|
38
39
|
|
39
|
-
def
|
40
|
-
|
40
|
+
def store object_key, attribute, value
|
41
|
+
object(object_key).send("#{attribute}=".to_sym, value)
|
41
42
|
end
|
42
43
|
|
43
44
|
end
|
data/lib/parsable/parsed_item.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
module Parsable
|
2
2
|
class ParsedItem
|
3
|
-
attr_accessor :original, :
|
3
|
+
attr_accessor :original, :object, :attribute
|
4
4
|
|
5
5
|
def initialize args={}
|
6
6
|
@original = args[:original]
|
7
|
-
@function = args[:function]
|
8
7
|
@object = args[:object]
|
9
8
|
@attribute = args[:attribute]
|
10
9
|
end
|
data/lib/parsable/parser.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
module Parsable
|
2
2
|
class Parser
|
3
3
|
|
4
|
+
REGEX = /\{{2}(\w*\.?\S[^\{\{]*)\}{2}/
|
5
|
+
|
4
6
|
attr_accessor :original_string, :strings
|
5
7
|
|
6
8
|
def initialize args={}
|
7
9
|
@original_string = args.fetch(:string).to_s
|
8
|
-
@strings = all_captures(@original_string)
|
9
10
|
end
|
10
11
|
|
11
12
|
def parse
|
12
|
-
strings.
|
13
|
-
|
13
|
+
strings.map do |string|
|
14
|
+
object, attribute = capture(string)
|
14
15
|
|
15
16
|
Parsable::ParsedItem.new(\
|
16
|
-
:original => string,
|
17
|
-
:function => function,
|
17
|
+
:original => string,
|
18
18
|
:object => object,
|
19
19
|
:attribute => attribute
|
20
20
|
)
|
@@ -24,28 +24,19 @@ module Parsable
|
|
24
24
|
private
|
25
25
|
|
26
26
|
def capture string
|
27
|
-
[
|
28
|
-
end
|
29
|
-
|
30
|
-
def all_captures string
|
31
|
-
string.to_s.scan(/\{\{(\w*\(?\w*\.?\w*\)?)\}\}/).flatten
|
27
|
+
[capture_object(string), capture_attribute(string)]
|
32
28
|
end
|
33
29
|
|
34
|
-
def
|
35
|
-
|
36
|
-
match[1] if match
|
37
|
-
end
|
38
|
-
|
39
|
-
def capture_attribute string
|
40
|
-
object_attribute(string).last
|
30
|
+
def strings
|
31
|
+
@strings ||= original_string.to_s.scan(REGEX).flatten
|
41
32
|
end
|
42
33
|
|
43
34
|
def capture_object string
|
44
|
-
|
35
|
+
string[/(\w*)\.?\S*/, 1]
|
45
36
|
end
|
46
37
|
|
47
|
-
def
|
48
|
-
string[
|
38
|
+
def capture_attribute string
|
39
|
+
string[/\w*\.?(\S*)/, 1]
|
49
40
|
end
|
50
41
|
|
51
42
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'curb'
|
3
|
+
|
4
|
+
module Parsable
|
5
|
+
class Remote
|
6
|
+
# uses the response from a remote location
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
end
|
10
|
+
|
11
|
+
def method_missing(method_sym, *arguments, &block)
|
12
|
+
if uri = uri?(method_sym)
|
13
|
+
get_response(uri)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def get_response uri
|
20
|
+
0.upto(2) do |i|
|
21
|
+
begin
|
22
|
+
Curl::Easy.perform(uri.to_s) do |http|
|
23
|
+
http.connect_timeout = 2
|
24
|
+
http.on_success { |easy| @body = easy.body_str }
|
25
|
+
end
|
26
|
+
rescue Curl::Err::CurlError
|
27
|
+
end
|
28
|
+
|
29
|
+
break if @body
|
30
|
+
end
|
31
|
+
@body
|
32
|
+
end
|
33
|
+
|
34
|
+
def uri? string
|
35
|
+
uri = URI.parse(string)
|
36
|
+
if uri && uri.kind_of?(URI::HTTP)
|
37
|
+
uri
|
38
|
+
else
|
39
|
+
false
|
40
|
+
end
|
41
|
+
rescue URI::InvalidURIError
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
data/lib/parsable/version.rb
CHANGED
data/lib/parsable.rb
CHANGED
@@ -2,9 +2,10 @@ require "parsable/version"
|
|
2
2
|
require 'parsable/parser'
|
3
3
|
require 'parsable/context'
|
4
4
|
require 'parsable/parsed_item'
|
5
|
+
require 'parsable/remote'
|
5
6
|
|
6
7
|
module Parsable
|
7
|
-
|
8
|
+
|
8
9
|
def self.crunch args={}
|
9
10
|
original = args.fetch(:string).to_s
|
10
11
|
parsed_parts = Parsable::Parser.new(args).parse
|
data/parsable.gemspec
CHANGED
@@ -22,4 +22,8 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_development_dependency "rake"
|
23
23
|
spec.add_development_dependency "rspec"
|
24
24
|
spec.add_development_dependency "pry"
|
25
|
+
spec.add_development_dependency "vcr"
|
26
|
+
spec.add_development_dependency "webmock"
|
27
|
+
|
28
|
+
spec.add_runtime_dependency "curb"
|
25
29
|
end
|
data/spec/context_spec.rb
CHANGED
data/spec/parsable_spec.rb
CHANGED
@@ -12,7 +12,7 @@ describe Parsable do
|
|
12
12
|
it "outputs string with crunched values" do
|
13
13
|
|
14
14
|
output = Parsable.crunch(\
|
15
|
-
:string => %(my+{{location.name}}@email.com),
|
15
|
+
:string => %(my+{{location.name}}@email.com),
|
16
16
|
:context => context
|
17
17
|
)
|
18
18
|
|
@@ -23,7 +23,7 @@ describe Parsable do
|
|
23
23
|
it "does nothing" do
|
24
24
|
|
25
25
|
output = Parsable.crunch(\
|
26
|
-
:string => nil,
|
26
|
+
:string => nil,
|
27
27
|
:context => context
|
28
28
|
)
|
29
29
|
|
@@ -35,7 +35,7 @@ describe Parsable do
|
|
35
35
|
it "returns the original" do
|
36
36
|
string = %(my@email.com)
|
37
37
|
output = Parsable.crunch(\
|
38
|
-
:string => string,
|
38
|
+
:string => string,
|
39
39
|
:context => context
|
40
40
|
)
|
41
41
|
|
@@ -47,7 +47,7 @@ describe Parsable do
|
|
47
47
|
it "replaces both strings" do
|
48
48
|
string = %(my{{location.name}}@email.com{{location.name}})
|
49
49
|
output = Parsable.crunch(\
|
50
|
-
:string => string,
|
50
|
+
:string => string,
|
51
51
|
:context => context
|
52
52
|
)
|
53
53
|
|
@@ -59,7 +59,7 @@ describe Parsable do
|
|
59
59
|
it "replaces with empty" do
|
60
60
|
|
61
61
|
output = Parsable.crunch(\
|
62
|
-
:string => %(my+{{location.not_name}}@email.com),
|
62
|
+
:string => %(my+{{location.not_name}}@email.com),
|
63
63
|
:context => context
|
64
64
|
)
|
65
65
|
|
@@ -71,7 +71,7 @@ describe Parsable do
|
|
71
71
|
it "replaces with empty" do
|
72
72
|
|
73
73
|
output = Parsable.crunch(\
|
74
|
-
:string => %(my+{{wrong_key.name}}@email.com),
|
74
|
+
:string => %(my+{{wrong_key.name}}@email.com),
|
75
75
|
:context => context
|
76
76
|
)
|
77
77
|
|
data/spec/parser_spec.rb
CHANGED
@@ -19,26 +19,15 @@ describe Parsable::Parser do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
context 'when one variable' do
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
it "parses object name" do
|
28
|
-
expect(@parsed.object).to eql('location')
|
29
|
-
end
|
30
|
-
|
31
|
-
it "parses attribute" do
|
32
|
-
expect(@parsed.attribute).to eql('name')
|
33
|
-
end
|
22
|
+
before :each do
|
23
|
+
@parsed = Parsable::Parser.new(:string => %(my+{{location.name}}@email.com)).parse.first
|
24
|
+
end
|
25
|
+
it "parses object name" do
|
26
|
+
expect(@parsed.object).to eql('location')
|
34
27
|
end
|
35
28
|
|
36
|
-
|
37
|
-
|
38
|
-
string = %(my+{{url_safe(location.name)}}@email.com)
|
39
|
-
parsed = Parsable::Parser.new(:string => string).parse.first
|
40
|
-
expect(parsed.function).to eql('url_safe')
|
41
|
-
end
|
29
|
+
it "parses attribute" do
|
30
|
+
expect(@parsed.attribute).to eql('name')
|
42
31
|
end
|
43
32
|
end
|
44
33
|
|
@@ -51,26 +40,26 @@ describe Parsable::Parser do
|
|
51
40
|
expect(@parsed.size).to eql(2)
|
52
41
|
end
|
53
42
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
end
|
43
|
+
it "parses object names" do
|
44
|
+
expect(@parsed.first.object).to eql('location')
|
45
|
+
expect(@parsed.last.object).to eql('email')
|
46
|
+
end
|
59
47
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
end
|
48
|
+
it "parses attributes" do
|
49
|
+
expect(@parsed.first.attribute).to eql('name')
|
50
|
+
expect(@parsed.last.attribute).to eql('domain')
|
64
51
|
end
|
52
|
+
end
|
65
53
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
54
|
+
context 'when remote object' do
|
55
|
+
subject { Parsable::Parser.new(:string => %({{remote.http://google.com?query1=q1&query2=q2}}@email.com)).parse.first }
|
56
|
+
|
57
|
+
it "parses object name" do
|
58
|
+
expect(subject.object).to eql('remote')
|
59
|
+
end
|
70
60
|
|
71
|
-
|
72
|
-
|
73
|
-
end
|
61
|
+
it "parses attribute" do
|
62
|
+
expect(subject.attribute).to eql('http://google.com?query1=q1&query2=q2')
|
74
63
|
end
|
75
64
|
end
|
76
65
|
end
|
data/spec/remote_spec.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
describe Parsable::Remote do
|
5
|
+
|
6
|
+
subject { described_class.new }
|
7
|
+
|
8
|
+
describe '.method_missing', :vcr => true do
|
9
|
+
context "url" do
|
10
|
+
it "returns the body" do
|
11
|
+
expect(subject.send("http://httpstat.us/200")).to eql "200 OK"
|
12
|
+
end
|
13
|
+
|
14
|
+
context "with query params" do
|
15
|
+
it "uses them in the request" do
|
16
|
+
query = {"args" => {"query1" => "q1", "query2" => "q2"}}
|
17
|
+
expect(JSON.parse(subject.send("http://httpbin.org/get?query1=q1&query2=q2"))).to include(query)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "cant connect" do
|
22
|
+
context "bad response code" do
|
23
|
+
it "returns nil" do
|
24
|
+
expect(subject.send("http://httpstat.us/500")).to be_nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "bad dns" do
|
29
|
+
it "returns nil" do
|
30
|
+
expect(subject.send("http://blahblahblahblahblahdoesntexist.com")).to be_nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "blackhole" do
|
35
|
+
it "returns nil" do
|
36
|
+
expect(subject.send("http://blackhole.webpagetest.org")).to be_nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "not a url" do
|
43
|
+
it "returns nil" do
|
44
|
+
expect(subject.send("notaurl")).to be_nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
require "parsable"
|
2
2
|
require 'pry'
|
3
|
+
require 'vcr'
|
4
|
+
require 'webmock'
|
3
5
|
|
4
6
|
RSpec.configure do |config|
|
5
7
|
# Use color in STDOUT
|
6
|
-
config.
|
8
|
+
config.color = true
|
9
|
+
end
|
10
|
+
|
11
|
+
VCR.configure do |config|
|
12
|
+
config.cassette_library_dir = "fixtures/vcr_cassettes"
|
13
|
+
config.hook_into :webmock # or :fakeweb
|
14
|
+
config.configure_rspec_metadata!
|
7
15
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: parsable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hubert Liu
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,6 +66,48 @@ dependencies:
|
|
66
66
|
- - '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: vcr
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: webmock
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: curb
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
69
111
|
description: 'Replace inline variables in strings with their values '
|
70
112
|
email:
|
71
113
|
- hubert.liu@rigor.com
|
@@ -79,15 +121,21 @@ files:
|
|
79
121
|
- LICENSE.txt
|
80
122
|
- README.md
|
81
123
|
- Rakefile
|
124
|
+
- fixtures/vcr_cassettes/Parsable_Remote/_method_missing/url/cant_connect/bad_response_code/returns_nil.yml
|
125
|
+
- fixtures/vcr_cassettes/Parsable_Remote/_method_missing/url/cant_connect/returns_nil.yml
|
126
|
+
- fixtures/vcr_cassettes/Parsable_Remote/_method_missing/url/returns_the_body.yml
|
127
|
+
- fixtures/vcr_cassettes/Parsable_Remote/_method_missing/url/with_query_params/uses_them_in_the_request.yml
|
82
128
|
- lib/parsable.rb
|
83
129
|
- lib/parsable/context.rb
|
84
130
|
- lib/parsable/parsed_item.rb
|
85
131
|
- lib/parsable/parser.rb
|
132
|
+
- lib/parsable/remote.rb
|
86
133
|
- lib/parsable/version.rb
|
87
134
|
- parsable.gemspec
|
88
135
|
- spec/context_spec.rb
|
89
136
|
- spec/parsable_spec.rb
|
90
137
|
- spec/parser_spec.rb
|
138
|
+
- spec/remote_spec.rb
|
91
139
|
- spec/spec_helper.rb
|
92
140
|
homepage: ''
|
93
141
|
licenses:
|
@@ -117,4 +165,5 @@ test_files:
|
|
117
165
|
- spec/context_spec.rb
|
118
166
|
- spec/parsable_spec.rb
|
119
167
|
- spec/parser_spec.rb
|
168
|
+
- spec/remote_spec.rb
|
120
169
|
- spec/spec_helper.rb
|