her 0.5.3 → 0.5.4

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 (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