her 0.5.3 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +8 -8
  2. data/.gitignore +2 -2
  3. data/.rspec +1 -2
  4. data/.travis.yml +2 -2
  5. data/README.md +10 -16
  6. data/UPGRADE.md +4 -0
  7. data/examples/grape-and-her/.env.default +3 -0
  8. data/examples/grape-and-her/Procfile +2 -0
  9. data/examples/grape-and-her/README.md +27 -0
  10. data/examples/grape-and-her/api/Gemfile +11 -0
  11. data/examples/grape-and-her/api/Rakefile +14 -0
  12. data/examples/grape-and-her/api/app/api.rb +49 -0
  13. data/examples/grape-and-her/api/app/models/organization.rb +7 -0
  14. data/examples/grape-and-her/api/app/models/user.rb +9 -0
  15. data/examples/grape-and-her/api/app/views/organizations/_base.rabl +2 -0
  16. data/examples/grape-and-her/api/app/views/organizations/index.rabl +3 -0
  17. data/examples/grape-and-her/api/app/views/organizations/show.rabl +3 -0
  18. data/examples/grape-and-her/api/app/views/users/_base.rabl +8 -0
  19. data/examples/grape-and-her/api/app/views/users/index.rabl +3 -0
  20. data/examples/grape-and-her/api/app/views/users/show.rabl +3 -0
  21. data/examples/grape-and-her/api/config.ru +5 -0
  22. data/examples/grape-and-her/api/config/boot.rb +17 -0
  23. data/examples/grape-and-her/api/config/unicorn.rb +7 -0
  24. data/examples/grape-and-her/api/db/migrations/001_create_users.rb +11 -0
  25. data/examples/grape-and-her/api/db/migrations/002_create_organizations.rb +8 -0
  26. data/examples/grape-and-her/consumer/Gemfile +23 -0
  27. data/examples/grape-and-her/consumer/app/assets/stylesheets/application.scss +190 -0
  28. data/examples/grape-and-her/consumer/app/assets/stylesheets/reset.scss +53 -0
  29. data/examples/grape-and-her/consumer/app/consumer.rb +74 -0
  30. data/examples/grape-and-her/consumer/app/models/organization.rb +13 -0
  31. data/examples/grape-and-her/consumer/app/models/user.rb +13 -0
  32. data/examples/grape-and-her/consumer/app/views/index.haml +9 -0
  33. data/examples/grape-and-her/consumer/app/views/layout.haml +20 -0
  34. data/examples/grape-and-her/consumer/app/views/organizations/index.haml +25 -0
  35. data/examples/grape-and-her/consumer/app/views/organizations/show.haml +11 -0
  36. data/examples/grape-and-her/consumer/app/views/users/index.haml +33 -0
  37. data/examples/grape-and-her/consumer/app/views/users/show.haml +9 -0
  38. data/examples/grape-and-her/consumer/config.ru +20 -0
  39. data/examples/grape-and-her/consumer/config/boot.rb +30 -0
  40. data/examples/grape-and-her/consumer/config/unicorn.rb +7 -0
  41. data/examples/grape-and-her/consumer/lib/response_logger.rb +18 -0
  42. data/her.gemspec +2 -2
  43. data/lib/her/model.rb +22 -26
  44. data/lib/her/model/associations.rb +19 -19
  45. data/lib/her/model/attributes.rb +173 -0
  46. data/lib/her/model/base.rb +17 -0
  47. data/lib/her/model/http.rb +58 -242
  48. data/lib/her/model/introspection.rb +7 -8
  49. data/lib/her/model/nested_attributes.rb +3 -3
  50. data/lib/her/model/orm.rb +15 -205
  51. data/lib/her/model/parse.rb +86 -0
  52. data/lib/her/model/paths.rb +54 -14
  53. data/lib/her/version.rb +1 -1
  54. data/spec/model/attributes_spec.rb +139 -0
  55. data/spec/model/dirty_spec.rb +40 -0
  56. data/spec/model/introspection_spec.rb +5 -5
  57. data/spec/model/orm_spec.rb +14 -128
  58. data/spec/model/paths_spec.rb +26 -0
  59. data/spec/model/validations_spec.rb +17 -0
  60. data/spec/spec_helper.rb +7 -32
  61. data/spec/support/extensions/array.rb +5 -0
  62. data/spec/support/extensions/hash.rb +5 -0
  63. data/spec/support/macros/model_macros.rb +29 -0
  64. metadata +52 -15
  65. data/examples/twitter-oauth/Gemfile +0 -13
  66. data/examples/twitter-oauth/app.rb +0 -50
  67. data/examples/twitter-oauth/config.ru +0 -5
  68. data/examples/twitter-oauth/views/index.haml +0 -9
  69. data/examples/twitter-search/Gemfile +0 -12
  70. data/examples/twitter-search/app.rb +0 -55
  71. data/examples/twitter-search/config.ru +0 -5
  72. data/examples/twitter-search/views/index.haml +0 -9
data/spec/spec_helper.rb CHANGED
@@ -1,46 +1,21 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
2
2
 
3
3
  require "rspec"
4
- require "mocha/api"
5
4
  require "her"
6
5
 
6
+ # Require everything in `spec/support`
7
+ Dir[File.expand_path('../../spec/support/**/*.rb', __FILE__)].map(&method(:require))
8
+
7
9
  RSpec.configure do |config|
8
- config.mock_with :mocha
10
+ config.include Her::Testing::Macros::ModelMacros
9
11
 
10
12
  config.before :each do
11
- @globals = []
13
+ @spawned_models = []
12
14
  end
13
15
 
14
16
  config.after :each do
15
- @globals.each do |global|
16
- Object.instance_eval { remove_const global } if Object.const_defined?(global)
17
- end
18
- end
19
- end
20
-
21
- class Hash
22
- def to_json; MultiJson.dump(self); end
23
- end
24
-
25
- class Array
26
- def to_json; MultiJson.dump(self); end
27
- end
28
-
29
- def spawn_model(klass, &block)
30
- if klass =~ /::/
31
- base, submodel = klass.split(/::/).map{ |s| s.to_sym }
32
- Object.const_set(base, Module.new) unless Object.const_defined?(base)
33
- Object.const_get(base).module_eval do
34
- remove_const submodel if constants.include?(submodel)
35
- submodel = const_set(submodel, Class.new)
36
- submodel.send(:include, Her::Model)
37
- submodel.class_eval(&block) if block_given?
17
+ @spawned_models.each do |model|
18
+ Object.instance_eval { remove_const model } if Object.const_defined?(model)
38
19
  end
39
- @globals << base
40
- else
41
- Object.instance_eval { remove_const klass } if Object.const_defined?(klass)
42
- Object.const_set(klass, Class.new).send(:include, Her::Model)
43
- Object.const_get(klass).class_eval(&block) if block_given?
44
- @globals << klass.to_sym
45
20
  end
46
21
  end
@@ -0,0 +1,5 @@
1
+ class Array
2
+ def to_json
3
+ MultiJson.dump(self)
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class Hash
2
+ def to_json
3
+ MultiJson.dump(self)
4
+ end
5
+ end
@@ -0,0 +1,29 @@
1
+ module Her
2
+ module Testing
3
+ module Macros
4
+ module ModelMacros
5
+ # Create a class and automatically inject Her::Model into it
6
+ def spawn_model(klass, &block)
7
+ if klass =~ /::/
8
+ base, submodel = klass.split(/::/).map{ |s| s.to_sym }
9
+ Object.const_set(base, Module.new) unless Object.const_defined?(base)
10
+ Object.const_get(base).module_eval do
11
+ remove_const submodel if constants.include?(submodel)
12
+ submodel = const_set(submodel, Class.new)
13
+ submodel.send(:include, Her::Model)
14
+ submodel.class_eval(&block) if block_given?
15
+ end
16
+
17
+ @spawned_models << base
18
+ else
19
+ Object.instance_eval { remove_const klass } if Object.const_defined?(klass)
20
+ Object.const_set(klass, Class.new).send(:include, Her::Model)
21
+ Object.const_get(klass).class_eval(&block) if block_given?
22
+
23
+ @spawned_models << klass.to_sym
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: her
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rémi Prévost
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-04-04 00:00:00.000000000 Z
11
+ date: 2013-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -39,19 +39,19 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '2.13'
41
41
  - !ruby/object:Gem::Dependency
42
- name: mocha
42
+ name: fivemat
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ~>
46
46
  - !ruby/object:Gem::Version
47
- version: '0.13'
47
+ version: '1.2'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
- version: '0.13'
54
+ version: '1.2'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: activemodel
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -100,14 +100,14 @@ dependencies:
100
100
  requirements:
101
101
  - - ~>
102
102
  - !ruby/object:Gem::Version
103
- version: '1.5'
103
+ version: '1.7'
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - ~>
109
109
  - !ruby/object:Gem::Version
110
- version: '1.5'
110
+ version: '1.7'
111
111
  description: Her is an ORM that maps REST resources and collections to Ruby objects
112
112
  email:
113
113
  - remi@exomel.com
@@ -124,14 +124,41 @@ files:
124
124
  - README.md
125
125
  - Rakefile
126
126
  - UPGRADE.md
127
- - examples/twitter-oauth/Gemfile
128
- - examples/twitter-oauth/app.rb
129
- - examples/twitter-oauth/config.ru
130
- - examples/twitter-oauth/views/index.haml
131
- - examples/twitter-search/Gemfile
132
- - examples/twitter-search/app.rb
133
- - examples/twitter-search/config.ru
134
- - examples/twitter-search/views/index.haml
127
+ - examples/grape-and-her/.env.default
128
+ - examples/grape-and-her/Procfile
129
+ - examples/grape-and-her/README.md
130
+ - examples/grape-and-her/api/Gemfile
131
+ - examples/grape-and-her/api/Rakefile
132
+ - examples/grape-and-her/api/app/api.rb
133
+ - examples/grape-and-her/api/app/models/organization.rb
134
+ - examples/grape-and-her/api/app/models/user.rb
135
+ - examples/grape-and-her/api/app/views/organizations/_base.rabl
136
+ - examples/grape-and-her/api/app/views/organizations/index.rabl
137
+ - examples/grape-and-her/api/app/views/organizations/show.rabl
138
+ - examples/grape-and-her/api/app/views/users/_base.rabl
139
+ - examples/grape-and-her/api/app/views/users/index.rabl
140
+ - examples/grape-and-her/api/app/views/users/show.rabl
141
+ - examples/grape-and-her/api/config.ru
142
+ - examples/grape-and-her/api/config/boot.rb
143
+ - examples/grape-and-her/api/config/unicorn.rb
144
+ - examples/grape-and-her/api/db/migrations/001_create_users.rb
145
+ - examples/grape-and-her/api/db/migrations/002_create_organizations.rb
146
+ - examples/grape-and-her/consumer/Gemfile
147
+ - examples/grape-and-her/consumer/app/assets/stylesheets/application.scss
148
+ - examples/grape-and-her/consumer/app/assets/stylesheets/reset.scss
149
+ - examples/grape-and-her/consumer/app/consumer.rb
150
+ - examples/grape-and-her/consumer/app/models/organization.rb
151
+ - examples/grape-and-her/consumer/app/models/user.rb
152
+ - examples/grape-and-her/consumer/app/views/index.haml
153
+ - examples/grape-and-her/consumer/app/views/layout.haml
154
+ - examples/grape-and-her/consumer/app/views/organizations/index.haml
155
+ - examples/grape-and-her/consumer/app/views/organizations/show.haml
156
+ - examples/grape-and-her/consumer/app/views/users/index.haml
157
+ - examples/grape-and-her/consumer/app/views/users/show.haml
158
+ - examples/grape-and-her/consumer/config.ru
159
+ - examples/grape-and-her/consumer/config/boot.rb
160
+ - examples/grape-and-her/consumer/config/unicorn.rb
161
+ - examples/grape-and-her/consumer/lib/response_logger.rb
135
162
  - her.gemspec
136
163
  - lib/her.rb
137
164
  - lib/her/api.rb
@@ -144,11 +171,13 @@ files:
144
171
  - lib/her/middleware/second_level_parse_json.rb
145
172
  - lib/her/model.rb
146
173
  - lib/her/model/associations.rb
174
+ - lib/her/model/attributes.rb
147
175
  - lib/her/model/base.rb
148
176
  - lib/her/model/http.rb
149
177
  - lib/her/model/introspection.rb
150
178
  - lib/her/model/nested_attributes.rb
151
179
  - lib/her/model/orm.rb
180
+ - lib/her/model/parse.rb
152
181
  - lib/her/model/paths.rb
153
182
  - lib/her/version.rb
154
183
  - spec/api_spec.rb
@@ -157,6 +186,7 @@ files:
157
186
  - spec/middleware/first_level_parse_json_spec.rb
158
187
  - spec/middleware/second_level_parse_json_spec.rb
159
188
  - spec/model/associations_spec.rb
189
+ - spec/model/attributes_spec.rb
160
190
  - spec/model/callbacks_spec.rb
161
191
  - spec/model/dirty_spec.rb
162
192
  - spec/model/http_spec.rb
@@ -167,6 +197,9 @@ files:
167
197
  - spec/model/validations_spec.rb
168
198
  - spec/model_spec.rb
169
199
  - spec/spec_helper.rb
200
+ - spec/support/extensions/array.rb
201
+ - spec/support/extensions/hash.rb
202
+ - spec/support/macros/model_macros.rb
170
203
  homepage: http://remiprev.github.com/her
171
204
  licenses:
172
205
  - MIT
@@ -199,6 +232,7 @@ test_files:
199
232
  - spec/middleware/first_level_parse_json_spec.rb
200
233
  - spec/middleware/second_level_parse_json_spec.rb
201
234
  - spec/model/associations_spec.rb
235
+ - spec/model/attributes_spec.rb
202
236
  - spec/model/callbacks_spec.rb
203
237
  - spec/model/dirty_spec.rb
204
238
  - spec/model/http_spec.rb
@@ -209,3 +243,6 @@ test_files:
209
243
  - spec/model/validations_spec.rb
210
244
  - spec/model_spec.rb
211
245
  - spec/spec_helper.rb
246
+ - spec/support/extensions/array.rb
247
+ - spec/support/extensions/hash.rb
248
+ - spec/support/macros/model_macros.rb
@@ -1,13 +0,0 @@
1
- source :rubygems
2
-
3
- gem "sinatra"
4
- gem "haml"
5
- gem "thin", :require => false
6
- gem "faraday_middleware"
7
- gem "simple_oauth"
8
-
9
- gem "her", :path => File.join(File.dirname(__FILE__),"../..")
10
-
11
- group :development do
12
- gem "shotgun"
13
- end
@@ -1,50 +0,0 @@
1
- # Create custom parser
2
- class TwitterParser < Faraday::Response::Middleware
3
- def on_complete(env)
4
- json = MultiJson.load(env[:body], :symbolize_keys => true)
5
- errors = [json.delete(:error)]
6
- env[:body] = {
7
- :data => json,
8
- :errors => errors,
9
- :metadata => {},
10
- }
11
- end
12
- end
13
-
14
- # See https://dev.twitter.com/apps
15
- TWITTER_CREDENTIALS = {
16
- :consumer_key => "",
17
- :consumer_secret => "",
18
- :token => "",
19
- :token_secret => ""
20
- }
21
-
22
- # Initialize API
23
- Her::API.setup :url => "https://api.twitter.com/1/" do |builder|
24
- builder.use FaradayMiddleware::OAuth, TWITTER_CREDENTIALS
25
- builder.use Faraday::Request::UrlEncoded
26
- builder.use TwitterParser
27
- builder.use Faraday::Adapter::NetHttp
28
- end
29
-
30
- # Define classes
31
- class Tweet
32
- include Her::Model
33
-
34
- def self.timeline
35
- get "/statuses/home_timeline.json"
36
- end
37
-
38
- def self.mentions
39
- get "/statuses/mentions.json"
40
- end
41
-
42
- def username
43
- user[:screen_name]
44
- end
45
- end
46
-
47
- get "/" do
48
- @tweets = Tweet.mentions
49
- haml :index
50
- end
@@ -1,5 +0,0 @@
1
- require "bundler"
2
- Bundler.require
3
-
4
- require "./app"
5
- run Sinatra::Application
@@ -1,9 +0,0 @@
1
- !!!
2
- %html
3
- %body
4
- %ul
5
- - @tweets.each do |tweet|
6
- %li{ :style => "margin: 0 0 10px" }
7
- %span= tweet.text
8
- %br
9
- %strong= tweet.username
@@ -1,12 +0,0 @@
1
- source :rubygems
2
-
3
- gem "sinatra"
4
- gem "haml"
5
- gem "thin", :require => false
6
- gem "faraday_middleware"
7
-
8
- gem "her", :path => File.join(File.dirname(__FILE__),"../..")
9
-
10
- group :development do
11
- gem "shotgun"
12
- end
@@ -1,55 +0,0 @@
1
- # Create custom parser
2
- class TwitterSearchParser < Faraday::Response::Middleware
3
- METADATA_KEYS = [:completed_in, :max_id, :max_id_str, :next_page, :page, :query, :refresh_url, :results_per_page, :since_id, :since_id_str]
4
-
5
- def on_complete(env)
6
- json = MultiJson.load(env[:body], :symbolize_keys => true)
7
- data = json.delete(:results)
8
- errors = [json.delete(:error)].compact
9
- env[:body] = {
10
- :data => data,
11
- :errors => errors,
12
- :metadata => json
13
- }
14
- end
15
- end
16
-
17
- class MyCache < Hash
18
- def read(key)
19
- if cached = self[key]
20
- Marshal.load(cached)
21
- end
22
- end
23
-
24
- def write(key, data)
25
- self[key] = Marshal.dump(data)
26
- end
27
-
28
- def fetch(key)
29
- read(key) || yield.tap { |data| write(key, data) }
30
- end
31
- end
32
-
33
- $cache = MyCache.new
34
-
35
- # Initialize API
36
- Her::API.setup :url => "http://search.twitter.com" do |connection|
37
- connection.use Faraday::Request::UrlEncoded
38
- connection.use FaradayMiddleware::Caching, $cache
39
- connection.use TwitterSearchParser
40
- connection.use Faraday::Adapter::NetHttp
41
- end
42
-
43
- # Define classes
44
- class Tweet
45
- include Her::Model
46
-
47
- def self.search(query, attrs={})
48
- get("/search.json", attrs.merge(:q => query))
49
- end
50
- end
51
-
52
- get "/" do
53
- @tweets = Tweet.search("justin bieber", :rpp => 30)
54
- haml :index
55
- end
@@ -1,5 +0,0 @@
1
- require "bundler"
2
- Bundler.require
3
-
4
- require "./app"
5
- run Sinatra::Application
@@ -1,9 +0,0 @@
1
- !!!
2
- %html
3
- %body
4
- %ul
5
- - @tweets.each do |tweet|
6
- %li{ :style => "margin: 0 0 10px" }
7
- %span= tweet.text
8
- %br
9
- %strong= tweet.from_user