motion-resource 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -17,7 +17,13 @@ module MotionResource
17
17
  end
18
18
  end
19
19
 
20
- def has_many(name, params = lambda { |o| Hash.new })
20
+ def has_many(name, options = {})
21
+ default_options = {
22
+ :params => lambda { |o| Hash.new },
23
+ :class_name => name.to_s.classify
24
+ }
25
+ options = default_options.merge(options)
26
+
21
27
  backwards_association = self.name.underscore
22
28
 
23
29
  define_method name do |&block|
@@ -29,8 +35,10 @@ module MotionResource
29
35
  MotionResource::Base.request_block_call(block, cached, cached_response)
30
36
  return
31
37
  end
38
+
39
+ klass = options[:class_name].constantize
32
40
 
33
- Object.const_get(name.to_s.classify).find_all(params.call(self)) do |results, response|
41
+ klass.find_all(options[:params].call(self)) do |results, response|
34
42
  if results && results.first && results.first.respond_to?("#{backwards_association}=")
35
43
  results.each do |result|
36
44
  result.send("#{backwards_association}=", self)
@@ -44,7 +52,8 @@ module MotionResource
44
52
  end
45
53
 
46
54
  define_method "#{name}=" do |array|
47
- klass = Object.const_get(name.to_s.classify)
55
+ klass = options[:class_name].constantize
56
+
48
57
  instance_variable_set("@#{name}", [])
49
58
 
50
59
  array.each do |value|
@@ -2,6 +2,9 @@ module MotionResource
2
2
  class Base
3
3
  include MotionSupport::DescendantsTracker
4
4
 
5
+ class_attribute :primary_key
6
+ self.primary_key = :id
7
+
5
8
  attr_accessor :id
6
9
 
7
10
  def initialize(params = {})
@@ -16,7 +19,7 @@ module MotionResource
16
19
  class << self
17
20
  def instantiate(json)
18
21
  json = json.symbolize_keys
19
- raise ArgumentError, "No :id parameter given for #{self.name}.instantiate" unless json[:id]
22
+ raise ArgumentError, "No :#{primary_key} parameter given for #{self.name}.instantiate" unless json[primary_key]
20
23
 
21
24
  klass = if json[:type]
22
25
  begin
@@ -28,11 +31,11 @@ module MotionResource
28
31
  self
29
32
  end
30
33
 
31
- if result = klass.recall(json[:id])
34
+ if result = klass.recall(json[primary_key])
32
35
  result.update_attributes(json)
33
36
  else
34
37
  result = klass.new(json)
35
- klass.remember(result.id, result)
38
+ klass.remember(result.send(result.primary_key), result)
36
39
  end
37
40
  result.send(:instance_variable_set, "@new_record", false)
38
41
  result
@@ -2,11 +2,11 @@ module MotionResource
2
2
  class Base
3
3
  class << self
4
4
  def find(id, params = {}, &block)
5
- fetch_member(member_url.fill_url_params(params.merge(id: id)), &block)
5
+ fetch_member(member_url_or_default.fill_url_params(params.merge(id: id)), &block)
6
6
  end
7
7
 
8
8
  def find_all(params = {}, &block)
9
- fetch_collection(collection_url.fill_url_params(params), &block)
9
+ fetch_collection(collection_url_or_default.fill_url_params(params), &block)
10
10
  end
11
11
 
12
12
  def fetch_member(url, &block)
@@ -27,7 +27,7 @@ class String
27
27
  # fake a url so we avoid regex nastiness with URL's
28
28
  url = NSURL.URLWithString("http://blah.com/#{self}")
29
29
  # build our query string (needs encoding support!)
30
- query_string = params.map{|k,v| "#{k}=#{v}"}.join('&')
30
+ query_string = params.to_query
31
31
  if url.query.nil? || url.query.empty?
32
32
  # strip the beginning / and add the query
33
33
  self.replace "#{url.path[1..-1]}?#{query_string}"
@@ -16,14 +16,22 @@ module MotionResource
16
16
  end
17
17
  end
18
18
  end
19
+
20
+ def collection_url_or_default
21
+ collection_url || name.underscore.pluralize
22
+ end
23
+
24
+ def member_url_or_default
25
+ member_url || "#{name.underscore.pluralize}/:#{primary_key}"
26
+ end
19
27
  end
20
28
 
21
29
  def collection_url(params = {})
22
- self.class.collection_url.fill_url_params(params, self)
30
+ self.class.collection_url_or_default.fill_url_params(params, self)
23
31
  end
24
32
 
25
33
  def member_url(params = {})
26
- self.class.member_url.fill_url_params(params, self)
34
+ self.class.member_url_or_default.fill_url_params(params, self)
27
35
  end
28
36
  end
29
37
  end
@@ -1,3 +1,3 @@
1
1
  module MotionResource
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
data/spec/env.rb CHANGED
@@ -6,6 +6,7 @@ class Post < MotionResource::Base
6
6
  self.member_url = 'posts/:id'
7
7
 
8
8
  has_many :comments
9
+ has_many :parent_posts, :class_name => 'Post'
9
10
  end
10
11
 
11
12
  class Comment < MotionResource::Base
@@ -39,3 +40,8 @@ end
39
40
  class Rectangle < Shape
40
41
  attribute :size
41
42
  end
43
+
44
+ class Membership < MotionResource::Base
45
+ self.primary_key = :membership_id
46
+ attr_accessor :membership_id
47
+ end
@@ -20,6 +20,27 @@ describe "has_many" do
20
20
  post.comments.should == []
21
21
  end
22
22
 
23
+ describe "custom class name" do
24
+ extend WebStub::SpecHelpers
25
+
26
+ before do
27
+ stub_request(:get, "http://example.com/posts.json").to_return(json: [{ id: 1, text: 'Whats up?' }])
28
+ end
29
+
30
+ it "should fetch resources when called with a block" do
31
+ @post = Post.new
32
+ @post.parent_posts do |results|
33
+ @results = results
34
+ resume
35
+ end
36
+
37
+ wait_max 1.0 do
38
+ @results.size.should == 1
39
+ @results.first.text.should == 'Whats up?'
40
+ end
41
+ end
42
+ end
43
+
23
44
  describe "reader" do
24
45
  extend WebStub::SpecHelpers
25
46
 
@@ -1,6 +1,16 @@
1
1
  describe "base" do
2
- it "should define the id method" do
3
- Post.new.should.respond_to :id
2
+ describe "primary key" do
3
+ it "should have a default primary key" do
4
+ Post.primary_key.should == :id
5
+ end
6
+
7
+ it "should be overridable" do
8
+ Membership.primary_key.should == :membership_id
9
+ end
10
+
11
+ it "should define the id method" do
12
+ Post.new.should.respond_to :id
13
+ end
4
14
  end
5
15
 
6
16
  it "should set new_record to true when calling new" do
@@ -22,6 +32,11 @@ describe "base" do
22
32
  shape.should.is_a Rectangle
23
33
  end
24
34
 
35
+ it "should instantiate with non-standard primary key" do
36
+ membership = Membership.instantiate(:membership_id => 1)
37
+ membership.should.is_a Membership
38
+ end
39
+
25
40
  it "should instantiate base type if concrete type does not exist" do
26
41
  shape = Shape.instantiate(:id => 2, :type => 'FuzzyCircle')
27
42
  shape.should.is_a Shape
@@ -19,6 +19,18 @@ describe "urls" do
19
19
  MotionResource::Base.extension.should == '.json'
20
20
  end
21
21
 
22
+ it "should have a default collection URL" do
23
+ Rectangle.collection_url_or_default.should == "rectangles"
24
+ end
25
+
26
+ it "should have a default member URL" do
27
+ Rectangle.member_url_or_default.should == "rectangles/:id"
28
+ end
29
+
30
+ it "should have a default member URL with custom primary key" do
31
+ Membership.member_url_or_default.should == "memberships/:membership_id"
32
+ end
33
+
22
34
  it "should define custom url method" do
23
35
  comment = Comment.new
24
36
  comment.should.respond_to :by_user_url
@@ -43,10 +55,25 @@ describe "urls" do
43
55
  comment.collection_url.should == 'comments'
44
56
  end
45
57
 
58
+ it "should fall back to default URL in collection_url method" do
59
+ rectangle = Rectangle.new
60
+ rectangle.collection_url.should == 'rectangles'
61
+ end
62
+
46
63
  it "should define convenience member_url method" do
47
64
  comment = Comment.new
48
65
  comment.should.respond_to :member_url
49
66
  comment.member_url.should.is_a String
50
67
  comment.member_url(id: 10).should == 'comments/10'
51
68
  end
69
+
70
+ it "should fall back to default URL in collection_url method" do
71
+ rectangle = Rectangle.new
72
+ rectangle.member_url(:id => 10).should == 'rectangles/10'
73
+ end
74
+
75
+ it "should fall back to default URL in collection_url method with custom primary key" do
76
+ membership = Membership.new
77
+ membership.member_url(:membership_id => 10).should == 'memberships/10'
78
+ end
52
79
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motion-resource
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-12 00:00:00.000000000 Z
12
+ date: 2013-05-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bubble-wrap
@@ -121,7 +121,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
121
121
  version: '0'
122
122
  segments:
123
123
  - 0
124
- hash: 4144364702470032416
124
+ hash: -3993476988303272926
125
125
  required_rubygems_version: !ruby/object:Gem::Requirement
126
126
  none: false
127
127
  requirements:
@@ -130,7 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
130
130
  version: '0'
131
131
  segments:
132
132
  - 0
133
- hash: 4144364702470032416
133
+ hash: -3993476988303272926
134
134
  requirements: []
135
135
  rubyforge_project:
136
136
  rubygems_version: 1.8.25