extended_her 0.5
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.
- data/.gitignore +8 -0
- data/.rspec +2 -0
- data/.travis.yml +8 -0
- data/CONTRIBUTING.md +26 -0
- data/Gemfile +2 -0
- data/LICENSE +7 -0
- data/README.md +723 -0
- data/Rakefile +11 -0
- data/UPGRADE.md +32 -0
- data/examples/twitter-oauth/Gemfile +13 -0
- data/examples/twitter-oauth/app.rb +50 -0
- data/examples/twitter-oauth/config.ru +5 -0
- data/examples/twitter-oauth/views/index.haml +9 -0
- data/examples/twitter-search/Gemfile +12 -0
- data/examples/twitter-search/app.rb +55 -0
- data/examples/twitter-search/config.ru +5 -0
- data/examples/twitter-search/views/index.haml +9 -0
- data/extended_her.gemspec +27 -0
- data/lib/her.rb +23 -0
- data/lib/her/api.rb +108 -0
- data/lib/her/base.rb +17 -0
- data/lib/her/collection.rb +12 -0
- data/lib/her/errors.rb +5 -0
- data/lib/her/exceptions/exception.rb +4 -0
- data/lib/her/exceptions/record_invalid.rb +8 -0
- data/lib/her/exceptions/record_not_found.rb +13 -0
- data/lib/her/middleware.rb +9 -0
- data/lib/her/middleware/accept_json.rb +15 -0
- data/lib/her/middleware/first_level_parse_json.rb +34 -0
- data/lib/her/middleware/second_level_parse_json.rb +28 -0
- data/lib/her/model.rb +69 -0
- data/lib/her/model/base.rb +7 -0
- data/lib/her/model/hooks.rb +114 -0
- data/lib/her/model/http.rb +284 -0
- data/lib/her/model/introspection.rb +57 -0
- data/lib/her/model/orm.rb +191 -0
- data/lib/her/model/orm/comparison_methods.rb +20 -0
- data/lib/her/model/orm/create_methods.rb +29 -0
- data/lib/her/model/orm/destroy_methods.rb +53 -0
- data/lib/her/model/orm/error_methods.rb +19 -0
- data/lib/her/model/orm/fields_definition.rb +15 -0
- data/lib/her/model/orm/find_methods.rb +46 -0
- data/lib/her/model/orm/persistance_methods.rb +22 -0
- data/lib/her/model/orm/relation_mapper.rb +21 -0
- data/lib/her/model/orm/save_methods.rb +58 -0
- data/lib/her/model/orm/serialization_methods.rb +28 -0
- data/lib/her/model/orm/update_methods.rb +31 -0
- data/lib/her/model/paths.rb +82 -0
- data/lib/her/model/relationships.rb +191 -0
- data/lib/her/paginated_collection.rb +20 -0
- data/lib/her/relation.rb +94 -0
- data/lib/her/version.rb +3 -0
- data/spec/api_spec.rb +131 -0
- data/spec/collection_spec.rb +26 -0
- data/spec/middleware/accept_json_spec.rb +10 -0
- data/spec/middleware/first_level_parse_json_spec.rb +42 -0
- data/spec/middleware/second_level_parse_json_spec.rb +25 -0
- data/spec/model/hooks_spec.rb +406 -0
- data/spec/model/http_spec.rb +184 -0
- data/spec/model/introspection_spec.rb +59 -0
- data/spec/model/orm_spec.rb +552 -0
- data/spec/model/paths_spec.rb +286 -0
- data/spec/model/relationships_spec.rb +222 -0
- data/spec/model_spec.rb +31 -0
- data/spec/spec_helper.rb +46 -0
- metadata +222 -0
| @@ -0,0 +1,286 @@ | |
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
            require File.join(File.dirname(__FILE__), "../spec_helper.rb")
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            describe Her::Model::Paths do
         | 
| 5 | 
            +
              context "building request paths" do
         | 
| 6 | 
            +
                context "simple model" do
         | 
| 7 | 
            +
                  before do
         | 
| 8 | 
            +
                    spawn_model "Foo::User"
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  describe "#build_request_path" do
         | 
| 12 | 
            +
                    it "builds paths with defaults" do
         | 
| 13 | 
            +
                      Foo::User.build_request_path(:id => "foo").should == "users/foo"
         | 
| 14 | 
            +
                      Foo::User.build_request_path(:id => nil).should == "users"
         | 
| 15 | 
            +
                      Foo::User.build_request_path.should == "users"
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    it "builds paths with custom collection path" do
         | 
| 19 | 
            +
                      Foo::User.collection_path "/utilisateurs"
         | 
| 20 | 
            +
                      Foo::User.build_request_path(:id => "foo").should == "/utilisateurs/foo"
         | 
| 21 | 
            +
                      Foo::User.build_request_path.should == "/utilisateurs"
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    it "builds paths with custom relative collection path" do
         | 
| 25 | 
            +
                      Foo::User.collection_path "utilisateurs"
         | 
| 26 | 
            +
                      Foo::User.build_request_path(:id => "foo").should == "utilisateurs/foo"
         | 
| 27 | 
            +
                      Foo::User.build_request_path.should == "utilisateurs"
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    it "builds paths with custom collection path with multiple variables" do
         | 
| 31 | 
            +
                      Foo::User.collection_path "/organizations/:organization_id/utilisateurs"
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                      Foo::User.build_request_path(:id => "foo", :_organization_id => "acme").should == "/organizations/acme/utilisateurs/foo"
         | 
| 34 | 
            +
                      Foo::User.build_request_path(:_organization_id => "acme").should == "/organizations/acme/utilisateurs"
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                      Foo::User.build_request_path(:id => "foo", :organization_id => "acme").should == "/organizations/acme/utilisateurs/foo"
         | 
| 37 | 
            +
                      Foo::User.build_request_path(:organization_id => "acme").should == "/organizations/acme/utilisateurs"
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    it "builds paths with custom relative collection path with multiple variables" do
         | 
| 41 | 
            +
                      Foo::User.collection_path "organizations/:organization_id/utilisateurs"
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                      Foo::User.build_request_path(:id => "foo", :_organization_id => "acme").should == "organizations/acme/utilisateurs/foo"
         | 
| 44 | 
            +
                      Foo::User.build_request_path(:_organization_id => "acme").should == "organizations/acme/utilisateurs"
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                      Foo::User.build_request_path(:id => "foo", :organization_id => "acme").should == "organizations/acme/utilisateurs/foo"
         | 
| 47 | 
            +
                      Foo::User.build_request_path(:organization_id => "acme").should == "organizations/acme/utilisateurs"
         | 
| 48 | 
            +
                    end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                    it "builds paths with custom item path" do
         | 
| 51 | 
            +
                      Foo::User.resource_path "/utilisateurs/:id"
         | 
| 52 | 
            +
                      Foo::User.build_request_path(:id => "foo").should == "/utilisateurs/foo"
         | 
| 53 | 
            +
                      Foo::User.build_request_path.should == "users"
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    it "builds paths with custom relative item path" do
         | 
| 57 | 
            +
                      Foo::User.resource_path "utilisateurs/:id"
         | 
| 58 | 
            +
                      Foo::User.build_request_path(:id => "foo").should == "utilisateurs/foo"
         | 
| 59 | 
            +
                      Foo::User.build_request_path.should == "users"
         | 
| 60 | 
            +
                    end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                    it "raises exceptions when building a path without required custom variables" do
         | 
| 63 | 
            +
                      Foo::User.collection_path "/organizations/:organization_id/utilisateurs"
         | 
| 64 | 
            +
                      expect { Foo::User.build_request_path(:id => "foo") }.to raise_error(Her::Errors::PathError)
         | 
| 65 | 
            +
                    end
         | 
| 66 | 
            +
                  end
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                context "simple model with multiple words" do
         | 
| 70 | 
            +
                  before do
         | 
| 71 | 
            +
                    spawn_model "Foo::AdminUser"
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                  describe "#build_request_path" do
         | 
| 75 | 
            +
                    it "builds paths with defaults" do
         | 
| 76 | 
            +
                      Foo::AdminUser.build_request_path(:id => "foo").should == "admin_users/foo"
         | 
| 77 | 
            +
                      Foo::AdminUser.build_request_path.should == "admin_users"
         | 
| 78 | 
            +
                    end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                    it "builds paths with custom collection path" do
         | 
| 81 | 
            +
                      Foo::AdminUser.collection_path "/users"
         | 
| 82 | 
            +
                      Foo::AdminUser.build_request_path(:id => "foo").should == "/users/foo"
         | 
| 83 | 
            +
                      Foo::AdminUser.build_request_path.should == "/users"
         | 
| 84 | 
            +
                    end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                    it "builds paths with custom relative collection path" do
         | 
| 87 | 
            +
                      Foo::AdminUser.collection_path "users"
         | 
| 88 | 
            +
                      Foo::AdminUser.build_request_path(:id => "foo").should == "users/foo"
         | 
| 89 | 
            +
                      Foo::AdminUser.build_request_path.should == "users"
         | 
| 90 | 
            +
                    end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                    it "builds paths with custom collection path with multiple variables" do
         | 
| 93 | 
            +
                      Foo::AdminUser.collection_path "/organizations/:organization_id/users"
         | 
| 94 | 
            +
                      Foo::AdminUser.build_request_path(:id => "foo", :_organization_id => "acme").should == "/organizations/acme/users/foo"
         | 
| 95 | 
            +
                      Foo::AdminUser.build_request_path(:_organization_id => "acme").should == "/organizations/acme/users"
         | 
| 96 | 
            +
                    end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                    it "builds paths with custom relative collection path with multiple variables" do
         | 
| 99 | 
            +
                      Foo::AdminUser.collection_path "organizations/:organization_id/users"
         | 
| 100 | 
            +
                      Foo::AdminUser.build_request_path(:id => "foo", :_organization_id => "acme").should == "organizations/acme/users/foo"
         | 
| 101 | 
            +
                      Foo::AdminUser.build_request_path(:_organization_id => "acme").should == "organizations/acme/users"
         | 
| 102 | 
            +
                    end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                    it "builds paths with custom item path" do
         | 
| 105 | 
            +
                      Foo::AdminUser.resource_path "/users/:id"
         | 
| 106 | 
            +
                      Foo::AdminUser.build_request_path(:id => "foo").should == "/users/foo"
         | 
| 107 | 
            +
                      Foo::AdminUser.build_request_path.should == "admin_users"
         | 
| 108 | 
            +
                    end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                    it "builds paths with custom relative item path" do
         | 
| 111 | 
            +
                      Foo::AdminUser.resource_path "users/:id"
         | 
| 112 | 
            +
                      Foo::AdminUser.build_request_path(:id => "foo").should == "users/foo"
         | 
| 113 | 
            +
                      Foo::AdminUser.build_request_path.should == "admin_users"
         | 
| 114 | 
            +
                    end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                    it "raises exceptions when building a path without required custom variables" do
         | 
| 117 | 
            +
                      Foo::AdminUser.collection_path "/organizations/:organization_id/users"
         | 
| 118 | 
            +
                      expect { Foo::AdminUser.build_request_path(:id => "foo") }.to raise_error(Her::Errors::PathError)
         | 
| 119 | 
            +
                    end
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                    it "raises exceptions when building a relative path without required custom variables" do
         | 
| 122 | 
            +
                      Foo::AdminUser.collection_path "organizations/:organization_id/users"
         | 
| 123 | 
            +
                      expect { Foo::AdminUser.build_request_path(:id => "foo") }.to raise_error(Her::Errors::PathError)
         | 
| 124 | 
            +
                    end
         | 
| 125 | 
            +
                  end
         | 
| 126 | 
            +
                end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                context "nested model" do
         | 
| 129 | 
            +
                  before do
         | 
| 130 | 
            +
                    spawn_model "Foo::User"
         | 
| 131 | 
            +
                  end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                  describe "#build_request_path" do
         | 
| 134 | 
            +
                    it "builds paths with defaults" do
         | 
| 135 | 
            +
                      Foo::User.build_request_path(:id => "foo").should == "users/foo"
         | 
| 136 | 
            +
                      Foo::User.build_request_path.should == "users"
         | 
| 137 | 
            +
                    end
         | 
| 138 | 
            +
                  end
         | 
| 139 | 
            +
                end
         | 
| 140 | 
            +
              end
         | 
| 141 | 
            +
             | 
| 142 | 
            +
              context "making subdomain HTTP requests" do
         | 
| 143 | 
            +
                before do
         | 
| 144 | 
            +
                  Her::API.setup :url => "https://api.example.com/" do |builder|
         | 
| 145 | 
            +
                    builder.use Her::Middleware::FirstLevelParseJSON
         | 
| 146 | 
            +
                    builder.use Faraday::Request::UrlEncoded
         | 
| 147 | 
            +
                    builder.adapter :test do |stub|
         | 
| 148 | 
            +
                      stub.get("organizations/2/users") { |env| [200, {}, [{ :id => 1, :fullname => "Tobias Fünke", :organization_id => 2 }, { :id => 2, :fullname => "Lindsay Fünke", :organization_id => 2 }].to_json] }
         | 
| 149 | 
            +
                      stub.post("organizations/2/users") { |env| [200, {}, { :id => 1, :fullname => "Tobias Fünke", :organization_id => 2 }.to_json] }
         | 
| 150 | 
            +
                      stub.put("organizations/2/users/1") { |env| [200, {}, { :id => 1, :fullname => "Lindsay Fünke", :organization_id => 2 }.to_json] }
         | 
| 151 | 
            +
                      stub.get("organizations/2/users/1") { |env| [200, {}, { :id => 1, :fullname => "Tobias Fünke", :organization_id => 2, :active => true }.to_json] }
         | 
| 152 | 
            +
                      stub.delete("organizations/2/users/1") { |env| [200, {}, { :id => 1, :fullname => "Lindsay Fünke", :organization_id => 2, :active => false }.to_json] }
         | 
| 153 | 
            +
                    end
         | 
| 154 | 
            +
                  end
         | 
| 155 | 
            +
             | 
| 156 | 
            +
                  spawn_model "Foo::User" do
         | 
| 157 | 
            +
                    collection_path "organizations/:organization_id/users"
         | 
| 158 | 
            +
                  end
         | 
| 159 | 
            +
                end
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                describe "fetching a resource" do
         | 
| 162 | 
            +
                  it "maps a single resource to a Ruby object" do
         | 
| 163 | 
            +
                    @user = Foo::User.find(1, :_organization_id => 2)
         | 
| 164 | 
            +
                    @user.id.should == 1
         | 
| 165 | 
            +
                    @user.fullname.should == "Tobias Fünke"
         | 
| 166 | 
            +
                  end
         | 
| 167 | 
            +
                end
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                describe "fetching a collection" do
         | 
| 170 | 
            +
                  it "maps a collection of resources to an array of Ruby objects" do
         | 
| 171 | 
            +
                    @users = Foo::User.all(:_organization_id => 2)
         | 
| 172 | 
            +
                    @users.length.should == 2
         | 
| 173 | 
            +
                    @users.first.fullname.should == "Tobias Fünke"
         | 
| 174 | 
            +
                  end
         | 
| 175 | 
            +
                end
         | 
| 176 | 
            +
             | 
| 177 | 
            +
                describe "handling new resource" do
         | 
| 178 | 
            +
                  it "handles new resource" do
         | 
| 179 | 
            +
                    @new_user = Foo::User.new(:fullname => "Tobias Fünke", :organization_id => 2)
         | 
| 180 | 
            +
                    @new_user.new?.should be_true
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                    @existing_user = Foo::User.find(1, :_organization_id => 2)
         | 
| 183 | 
            +
                    @existing_user.new?.should be_false
         | 
| 184 | 
            +
                  end
         | 
| 185 | 
            +
                end
         | 
| 186 | 
            +
             | 
| 187 | 
            +
                describe "creating resources" do
         | 
| 188 | 
            +
                  it "handle one-line resource creation" do
         | 
| 189 | 
            +
                    @user = Foo::User.create(:fullname => "Tobias Fünke", :organization_id => 2)
         | 
| 190 | 
            +
                    @user.id.should == 1
         | 
| 191 | 
            +
                    @user.fullname.should == "Tobias Fünke"
         | 
| 192 | 
            +
                  end
         | 
| 193 | 
            +
             | 
| 194 | 
            +
                  it "handle resource creation through Model.new + #save" do
         | 
| 195 | 
            +
                    @user = Foo::User.new(:fullname => "Tobias Fünke", :organization_id => 2)
         | 
| 196 | 
            +
                    @user.save
         | 
| 197 | 
            +
                    @user.fullname.should == "Tobias Fünke"
         | 
| 198 | 
            +
                  end
         | 
| 199 | 
            +
                end
         | 
| 200 | 
            +
             | 
| 201 | 
            +
                context "updating resources" do
         | 
| 202 | 
            +
                  it "handle resource data update without saving it" do
         | 
| 203 | 
            +
                    @user = Foo::User.find(1, :_organization_id => 2)
         | 
| 204 | 
            +
                    @user.fullname.should == "Tobias Fünke"
         | 
| 205 | 
            +
                    @user.fullname = "Kittie Sanchez"
         | 
| 206 | 
            +
                    @user.fullname.should == "Kittie Sanchez"
         | 
| 207 | 
            +
                  end
         | 
| 208 | 
            +
             | 
| 209 | 
            +
                  it "handle resource update through the .update class method" do
         | 
| 210 | 
            +
                    @user = Foo::User.save_existing(1, { :fullname => "Lindsay Fünke", :organization_id => 2 })
         | 
| 211 | 
            +
                    @user.fullname.should == "Lindsay Fünke"
         | 
| 212 | 
            +
                  end
         | 
| 213 | 
            +
             | 
| 214 | 
            +
                  it "handle resource update through #save on an existing resource" do
         | 
| 215 | 
            +
                    @user = Foo::User.find(1, :_organization_id => 2)
         | 
| 216 | 
            +
                    @user.fullname = "Lindsay Fünke"
         | 
| 217 | 
            +
                    @user.save
         | 
| 218 | 
            +
                    @user.fullname.should == "Lindsay Fünke"
         | 
| 219 | 
            +
                  end
         | 
| 220 | 
            +
                end
         | 
| 221 | 
            +
             | 
| 222 | 
            +
                context "deleting resources" do
         | 
| 223 | 
            +
                  it "handle resource deletion through the .destroy class method" do
         | 
| 224 | 
            +
                    @user = Foo::User.destroy_existing(1, :_organization_id => 2)
         | 
| 225 | 
            +
                    @user.active.should be_false
         | 
| 226 | 
            +
                  end
         | 
| 227 | 
            +
             | 
| 228 | 
            +
                  it "handle resource deletion through #destroy on an existing resource" do
         | 
| 229 | 
            +
                    @user = Foo::User.find(1, :_organization_id => 2)
         | 
| 230 | 
            +
                    @user.destroy
         | 
| 231 | 
            +
                    @user.active.should be_false
         | 
| 232 | 
            +
                  end
         | 
| 233 | 
            +
                end
         | 
| 234 | 
            +
              end
         | 
| 235 | 
            +
             | 
| 236 | 
            +
              context "making path HTTP requests" do
         | 
| 237 | 
            +
                before do
         | 
| 238 | 
            +
                  Her::API.setup :url => "https://example.com/api/" do |builder|
         | 
| 239 | 
            +
                    builder.use Her::Middleware::FirstLevelParseJSON
         | 
| 240 | 
            +
                    builder.use Faraday::Request::UrlEncoded
         | 
| 241 | 
            +
                    builder.adapter :test do |stub|
         | 
| 242 | 
            +
                      stub.get("/api/organizations/2/users") { |env| [200, {}, [{ :id => 1, :fullname => "Tobias Fünke", :organization_id => 2 }, { :id => 2, :fullname => "Lindsay Fünke", :organization_id => 2 }].to_json] }
         | 
| 243 | 
            +
                      stub.get("/api/organizations/2/users/1") { |env| [200, {}, { :id => 1, :fullname => "Tobias Fünke", :organization_id => 2, :active => true }.to_json] }
         | 
| 244 | 
            +
                    end
         | 
| 245 | 
            +
                  end
         | 
| 246 | 
            +
             | 
| 247 | 
            +
                  spawn_model "Foo::User" do
         | 
| 248 | 
            +
                    collection_path "organizations/:organization_id/users"
         | 
| 249 | 
            +
                  end
         | 
| 250 | 
            +
                end
         | 
| 251 | 
            +
             | 
| 252 | 
            +
                describe "fetching a resource" do
         | 
| 253 | 
            +
                  it "maps a single resource to a Ruby object" do
         | 
| 254 | 
            +
                    @user = Foo::User.find(1, :_organization_id => 2)
         | 
| 255 | 
            +
                    @user.id.should == 1
         | 
| 256 | 
            +
                    @user.fullname.should == "Tobias Fünke"
         | 
| 257 | 
            +
                  end
         | 
| 258 | 
            +
                end
         | 
| 259 | 
            +
             | 
| 260 | 
            +
                describe "fetching a collection" do
         | 
| 261 | 
            +
                  it "maps a collection of resources to an array of Ruby objects" do
         | 
| 262 | 
            +
                    @users = Foo::User.all(:_organization_id => 2)
         | 
| 263 | 
            +
                    @users.length.should == 2
         | 
| 264 | 
            +
                    @users.first.fullname.should == "Tobias Fünke"
         | 
| 265 | 
            +
                  end
         | 
| 266 | 
            +
                end
         | 
| 267 | 
            +
             | 
| 268 | 
            +
                describe "fetching a resource with absolute path" do
         | 
| 269 | 
            +
                  it "maps a single resource to a Ruby object" do
         | 
| 270 | 
            +
                    Foo::User.resource_path '/api/' + Foo::User.resource_path
         | 
| 271 | 
            +
                    @user = Foo::User.find(1, :_organization_id => 2)
         | 
| 272 | 
            +
                    @user.id.should == 1
         | 
| 273 | 
            +
                    @user.fullname.should == "Tobias Fünke"
         | 
| 274 | 
            +
                  end
         | 
| 275 | 
            +
                end
         | 
| 276 | 
            +
             | 
| 277 | 
            +
                describe "fetching a collection with absolute path" do
         | 
| 278 | 
            +
                  it "maps a collection of resources to an array of Ruby objects" do
         | 
| 279 | 
            +
                    Foo::User.collection_path '/api/' + Foo::User.collection_path
         | 
| 280 | 
            +
                    @users = Foo::User.all(:_organization_id => 2)
         | 
| 281 | 
            +
                    @users.length.should == 2
         | 
| 282 | 
            +
                    @users.first.fullname.should == "Tobias Fünke"
         | 
| 283 | 
            +
                  end
         | 
| 284 | 
            +
                end
         | 
| 285 | 
            +
              end
         | 
| 286 | 
            +
            end
         | 
| @@ -0,0 +1,222 @@ | |
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
            require File.join(File.dirname(__FILE__), "../spec_helper.rb")
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            describe Her::Model::Relationships do
         | 
| 5 | 
            +
              context "setting relationships without details" do
         | 
| 6 | 
            +
                before do
         | 
| 7 | 
            +
                  spawn_model "Foo::User"
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                it "handles a single 'has_many' relationship" do
         | 
| 11 | 
            +
                  Foo::User.has_many :comments
         | 
| 12 | 
            +
                  Foo::User.relationships[:has_many].should == [{ :name => :comments, :class_name => "Comment", :path => "/comments", :inverse_of => nil }]
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                it "handles multiples 'has_many' relationship" do
         | 
| 16 | 
            +
                  Foo::User.has_many :comments
         | 
| 17 | 
            +
                  Foo::User.has_many :posts
         | 
| 18 | 
            +
                  Foo::User.relationships[:has_many].should == [{ :name => :comments, :class_name => "Comment", :path => "/comments", :inverse_of => nil }, { :name => :posts, :class_name => "Post", :path => "/posts", :inverse_of => nil }]
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                it "handles a single 'has_one' relationship" do
         | 
| 22 | 
            +
                  Foo::User.has_one :category
         | 
| 23 | 
            +
                  Foo::User.relationships[:has_one].should == [{ :name => :category, :class_name => "Category", :path => "/category" }]
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                it "handles multiples 'has_one' relationship" do
         | 
| 27 | 
            +
                  Foo::User.has_one :category
         | 
| 28 | 
            +
                  Foo::User.has_one :role
         | 
| 29 | 
            +
                  Foo::User.relationships[:has_one].should == [{ :name => :category, :class_name => "Category", :path => "/category" }, { :name => :role, :class_name => "Role", :path => "/role" }]
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                it "handles a single belongs_to relationship" do
         | 
| 33 | 
            +
                  Foo::User.belongs_to :organization
         | 
| 34 | 
            +
                  Foo::User.relationships[:belongs_to].should == [{ :name => :organization, :class_name => "Organization", :foreign_key => "organization_id", :path => "/organizations/:id" }]
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                it "handles multiples 'belongs_to' relationship" do
         | 
| 38 | 
            +
                  Foo::User.belongs_to :organization
         | 
| 39 | 
            +
                  Foo::User.belongs_to :family
         | 
| 40 | 
            +
                  Foo::User.relationships[:belongs_to].should == [{ :name => :organization, :class_name => "Organization", :foreign_key => "organization_id", :path => "/organizations/:id" }, { :name => :family, :class_name => "Family", :foreign_key => "family_id", :path => "/families/:id" }]
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              context "setting relationships with details" do
         | 
| 45 | 
            +
                before do
         | 
| 46 | 
            +
                  spawn_model "Foo::User"
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                it "handles a single 'has_many' relationship" do
         | 
| 50 | 
            +
                  Foo::User.has_many :comments, :class_name => "Post", :inverse_of => :admin
         | 
| 51 | 
            +
                  Foo::User.relationships[:has_many].should == [{ :name => :comments, :class_name => "Post", :path => "/comments", :inverse_of => :admin }]
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                it "handles a single 'has_one' relationship" do
         | 
| 55 | 
            +
                  Foo::User.has_one :category, :class_name => "Topic", :foreign_key => "topic_id"
         | 
| 56 | 
            +
                  Foo::User.relationships[:has_one].should == [{ :name => :category, :class_name => "Topic", :foreign_key => "topic_id", :path => "/category" }]
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                it "handles a single belongs_to relationship" do
         | 
| 60 | 
            +
                  Foo::User.belongs_to :organization, :class_name => "Business", :foreign_key => "org_id"
         | 
| 61 | 
            +
                  Foo::User.relationships[:belongs_to].should == [{ :name => :organization, :class_name => "Business", :foreign_key => "org_id", :path => "/organizations/:id" }]
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                context "inheriting relationships from a superclass" do
         | 
| 65 | 
            +
                  it "copies relationships to the subclass" do
         | 
| 66 | 
            +
                    Foo::User.has_many :comments, :class_name => "Post"
         | 
| 67 | 
            +
                    subclass = Class.new(Foo::User)
         | 
| 68 | 
            +
                    subclass.relationships.object_id.should_not == Foo::User.relationships.object_id
         | 
| 69 | 
            +
                    subclass.relationships[:has_many].length.should == 1
         | 
| 70 | 
            +
                    subclass.relationships[:has_many].first[:class_name].should == "Post"
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
              end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
              context "handling relationships without details" do
         | 
| 76 | 
            +
                before do
         | 
| 77 | 
            +
                  Her::API.setup :url => "https://api.example.com" do |builder|
         | 
| 78 | 
            +
                    builder.use Her::Middleware::FirstLevelParseJSON
         | 
| 79 | 
            +
                    builder.use Faraday::Request::UrlEncoded
         | 
| 80 | 
            +
                    builder.adapter :test do |stub|
         | 
| 81 | 
            +
                      stub.get("/users/1") { |env| [200, {}, { :id => 1, :name => "Tobias Fünke", :comments => [{ :id => 2, :body => "Tobias, you blow hard!", :user_id => 1 }, { :id => 3, :body => "I wouldn't mind kissing that man between the cheeks, so to speak", :user_id => 1 }], :role => { :id => 1, :body => "Admin" }, :organization => { :id => 1, :name => "Bluth Company" }, :organization_id => 1 }.to_json] }
         | 
| 82 | 
            +
                      stub.get("/users/2") { |env| [200, {}, { :id => 2, :name => "Lindsay Fünke", :organization_id => 2 }.to_json] }
         | 
| 83 | 
            +
                      stub.get("/users/1/comments") { |env| [200, {}, [{ :id => 4, :body => "They're having a FIRESALE?" }].to_json] }
         | 
| 84 | 
            +
                      stub.get("/users/2/comments") { |env| [200, {}, [{ :id => 4, :body => "They're having a FIRESALE?" }, { :id => 5, :body => "Is this the tiny town from Footloose?" }].to_json] }
         | 
| 85 | 
            +
                      stub.get("/users/2/role") { |env| [200, {}, { :id => 2, :body => "User" }.to_json] }
         | 
| 86 | 
            +
                      stub.get("/users/1/role") { |env| [200, {}, { :id => 3, :body => "User" }.to_json] }
         | 
| 87 | 
            +
                      stub.get("/users/1/posts") { |env| [200, {}, {:id => 1, :body => 'blogging stuff', :admin_id => 1 }.to_json] }
         | 
| 88 | 
            +
                      stub.get("/organizations/1") { |env| [200, {}, { :id => 1, :name => "Bluth Company Foo" }.to_json] }
         | 
| 89 | 
            +
                      stub.get("/organizations/2") { |env| [200, {}, { :id => 2, :name => "Bluth Company" }.to_json] }
         | 
| 90 | 
            +
                    end
         | 
| 91 | 
            +
                  end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                  spawn_model "Foo::User" do
         | 
| 94 | 
            +
                    has_many :comments
         | 
| 95 | 
            +
                    has_one :role
         | 
| 96 | 
            +
                    belongs_to :organization
         | 
| 97 | 
            +
                    has_many :posts, :inverse_of => :admin
         | 
| 98 | 
            +
                  end
         | 
| 99 | 
            +
                  spawn_model "Foo::Comment" do
         | 
| 100 | 
            +
                    belongs_to :user
         | 
| 101 | 
            +
                  end
         | 
| 102 | 
            +
                  spawn_model "Foo::Post" do
         | 
| 103 | 
            +
                    belongs_to :admin, :class_name => 'Foo::User'
         | 
| 104 | 
            +
                  end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                  spawn_model "Foo::Organization"
         | 
| 107 | 
            +
                  spawn_model "Foo::Role"
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                  @user_with_included_data = Foo::User.find(1)
         | 
| 110 | 
            +
                  @user_without_included_data = Foo::User.find(2)
         | 
| 111 | 
            +
                end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                it "maps an array of included data through has_many" do
         | 
| 114 | 
            +
                  @user_with_included_data.comments.first.should be_a(Foo::Comment)
         | 
| 115 | 
            +
                  @user_with_included_data.comments.length.should == 2
         | 
| 116 | 
            +
                  @user_with_included_data.comments.first.id.should == 2
         | 
| 117 | 
            +
                  @user_with_included_data.comments.first.body.should == "Tobias, you blow hard!"
         | 
| 118 | 
            +
                end
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                it "does not refetch the parents models data if they have been fetched before" do
         | 
| 121 | 
            +
                  @user_with_included_data.comments.first.user.object_id.should == @user_with_included_data.object_id
         | 
| 122 | 
            +
                end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                it "uses the given inverse_of key to set the parent model" do
         | 
| 125 | 
            +
                  @user_with_included_data.posts.first.admin.object_id.should == @user_with_included_data.object_id
         | 
| 126 | 
            +
                end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                it "fetches data that was not included through has_many" do
         | 
| 129 | 
            +
                  @user_without_included_data.comments.first.should be_a(Foo::Comment)
         | 
| 130 | 
            +
                  @user_without_included_data.comments.length.should == 2
         | 
| 131 | 
            +
                  @user_without_included_data.comments.first.id.should == 4
         | 
| 132 | 
            +
                  @user_without_included_data.comments.first.body.should == "They're having a FIRESALE?"
         | 
| 133 | 
            +
                end
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                it "fetches has_many data even if it was included, only if called with parameters" do
         | 
| 136 | 
            +
                  @user_with_included_data.comments(:foo_id => 1).length.should == 1
         | 
| 137 | 
            +
                end
         | 
| 138 | 
            +
             | 
| 139 | 
            +
                it "maps an array of included data through has_one" do
         | 
| 140 | 
            +
                  @user_with_included_data.role.should be_a(Foo::Role)
         | 
| 141 | 
            +
                  @user_with_included_data.role.id.should == 1
         | 
| 142 | 
            +
                  @user_with_included_data.role.body.should == "Admin"
         | 
| 143 | 
            +
                end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                it "fetches data that was not included through has_one" do
         | 
| 146 | 
            +
                  @user_without_included_data.role.should be_a(Foo::Role)
         | 
| 147 | 
            +
                  @user_without_included_data.role.id.should == 2
         | 
| 148 | 
            +
                  @user_without_included_data.role.body.should == "User"
         | 
| 149 | 
            +
                end
         | 
| 150 | 
            +
             | 
| 151 | 
            +
                it "fetches has_one data even if it was included, only if called with parameters" do
         | 
| 152 | 
            +
                  @user_with_included_data.role(:foo_id => 2).id.should == 3
         | 
| 153 | 
            +
                end
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                it "maps an array of included data through belongs_to" do
         | 
| 156 | 
            +
                  @user_with_included_data.organization.should be_a(Foo::Organization)
         | 
| 157 | 
            +
                  @user_with_included_data.organization.id.should == 1
         | 
| 158 | 
            +
                  @user_with_included_data.organization.name.should == "Bluth Company"
         | 
| 159 | 
            +
                end
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                it "fetches data that was not included through belongs_to" do
         | 
| 162 | 
            +
                  @user_without_included_data.organization.should be_a(Foo::Organization)
         | 
| 163 | 
            +
                  @user_without_included_data.organization.id.should == 2
         | 
| 164 | 
            +
                  @user_without_included_data.organization.name.should == "Bluth Company"
         | 
| 165 | 
            +
                end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                it "fetches belongs_to data even if it was included, only if called with parameters" do
         | 
| 168 | 
            +
                  @user_with_included_data.organization(:foo_id => 1).name.should == "Bluth Company Foo"
         | 
| 169 | 
            +
                end
         | 
| 170 | 
            +
             | 
| 171 | 
            +
                it "can tell if it has a relationship" do
         | 
| 172 | 
            +
                  @user_without_included_data.has_relationship?(:unknown_relationship).should be_false
         | 
| 173 | 
            +
                  @user_without_included_data.has_relationship?(:organization).should be_true
         | 
| 174 | 
            +
                end
         | 
| 175 | 
            +
             | 
| 176 | 
            +
                it "fetches the resource corresponding to a named relationship" do
         | 
| 177 | 
            +
                  @user_without_included_data.get_relationship(:unknown_relationship).should be_nil
         | 
| 178 | 
            +
                  @user_without_included_data.get_relationship(:organization).name.should == "Bluth Company"
         | 
| 179 | 
            +
                end
         | 
| 180 | 
            +
              end
         | 
| 181 | 
            +
             | 
| 182 | 
            +
              context "handling relationships with details" do
         | 
| 183 | 
            +
                before do
         | 
| 184 | 
            +
                  Her::API.setup :url => "https://api.example.com" do |builder|
         | 
| 185 | 
            +
                    builder.use Her::Middleware::FirstLevelParseJSON
         | 
| 186 | 
            +
                    builder.use Faraday::Request::UrlEncoded
         | 
| 187 | 
            +
                    builder.adapter :test do |stub|
         | 
| 188 | 
            +
                      stub.get("/users/1") { |env| [200, {}, { :id => 1, :name => "Tobias Fünke", :organization => { :id => 1, :name => "Bluth Company" }, :organization_id => 1 }.to_json] }
         | 
| 189 | 
            +
                      stub.get("/users/2") { |env| [200, {}, { :id => 2, :name => "Lindsay Fünke", :organization_id => 1 }.to_json] }
         | 
| 190 | 
            +
                      stub.get("/users/3") { |env| [200, {}, { :id => 2, :name => "Lindsay Fünke", :organization => nil }.to_json] }
         | 
| 191 | 
            +
                      stub.get("/companies/1") { |env| [200, {}, { :id => 1, :name => "Bluth Company" }.to_json] }
         | 
| 192 | 
            +
                    end
         | 
| 193 | 
            +
                  end
         | 
| 194 | 
            +
             | 
| 195 | 
            +
                  spawn_model "Foo::User" do
         | 
| 196 | 
            +
                    belongs_to :company, :path => "/organizations/:id", :foreign_key => :organization_id
         | 
| 197 | 
            +
                  end
         | 
| 198 | 
            +
             | 
| 199 | 
            +
                  spawn_model "Foo::Company"
         | 
| 200 | 
            +
             | 
| 201 | 
            +
                  @user_with_included_data = Foo::User.find(1)
         | 
| 202 | 
            +
                  @user_without_included_data = Foo::User.find(2)
         | 
| 203 | 
            +
                  @user_with_included_nil_data = Foo::User.find(3)
         | 
| 204 | 
            +
                end
         | 
| 205 | 
            +
             | 
| 206 | 
            +
                it "maps an array of included data through belongs_to" do
         | 
| 207 | 
            +
                  @user_with_included_data.company.should be_a(Foo::Company)
         | 
| 208 | 
            +
                  @user_with_included_data.company.id.should == 1
         | 
| 209 | 
            +
                  @user_with_included_data.company.name.should == "Bluth Company"
         | 
| 210 | 
            +
                end
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                it "does not map included data if it’s nil" do
         | 
| 213 | 
            +
                  @user_with_included_nil_data.organization.should be_nil
         | 
| 214 | 
            +
                end
         | 
| 215 | 
            +
             | 
| 216 | 
            +
                it "fetches data that was not included through belongs_to" do
         | 
| 217 | 
            +
                  @user_without_included_data.company.should be_a(Foo::Company)
         | 
| 218 | 
            +
                  @user_without_included_data.company.id.should == 1
         | 
| 219 | 
            +
                  @user_without_included_data.company.name.should == "Bluth Company"
         | 
| 220 | 
            +
                end
         | 
| 221 | 
            +
              end
         | 
| 222 | 
            +
            end
         |