Coder Social home page Coder Social logo

rapidash's Introduction

Rapidash Build Status Coverage Status

Rapidash is a core for you to build a client for your API on. The goal is to define a standard way that developers can quickly write a client for the consumption of their RESTful API.

Installation

Add this line to your application's Gemfile:

gem 'rapidash'

And then execute:

$ bundle

Or install it yourself as:

$ gem install rapidash

Usage

A screencast on Rapidash is available to watch in mp4 and ogv formats.

Sample Rails app

A sample rails app is available at https://github.com/Gazler/rapidash-tester it provides a rails server and a Rapidash client. Please note that the client is also used as a form of integration test for rapidash.

Resources

Resources can be defined as follows:

class Users < Rapidash::Base
end

The URL of the resource will be inferred from the class name. In this case Users. If you want to override that, you can with the url method.

class User < Rapidash::Base
  url :members  # or url "members" is also supported
end

Resources can exist inside other resources. For example, on Github, a user has repositories. The following could be how you build the resources:

class Repo < Rapidash::Base
end

class User < Rapidash::Base
  resource :repos
end

Root elements

A root element can be set for create and post actions

class Post < Rapidash::Base
end

client.posts.create!({:post => {:name => "a post"}})

With a root element, the code would look like this:

class Post < Rapidash::Base
  root :post
end

client.posts.create!(:name => "a post")

Class Names and Classes In Different Modules

If you wish to use a class in a different module or a class with a different name as the class for your resource then you can use the :class_name option.

module MyModule
  class MyResource < Rapidash::Base
  end
end

class AnotherResource < Rapidash::Base
  resource :my_cool_resource, :class_name => "MyModule::MyResource"
end

Collections

The collection method allows you to add methods to a resource.

class Project < Rapidash::Base
  collection :archived
end

# creates the method below which performs a
# GET /projects/archived
client.projects.archived!

class Project < Rapidash::Base
  collection :delete_all, path: 'destroy', method: :post
end

# creates the method below which performs a
# POST /projects/destroy
client.projects.delete_all!

Client

The main thing a client must do is define a method, oauth and http are currently supported. You can also define resources which links a resource as defined above to the client.

class Client < Rapidash::Client
  method :oauth
  resource :users, :repos #An array can be passed through
  use_patch # This will use PATCH when updating instead of POST
  extension :json #Append the extension fo the urls
end

OAuth provides an initialize method which you can see in the Facebook client example.

Currently when using the HTTP method, you will need to define your own initialize method to set the site in use.

Making calls

client = Client.new
client.site = "http://example.com/"
client.users                                            #Returns an instance of Users
client.users!                                           #Will make a call to "http://example.com/users.json
client.users!(1)                                        #Will make a call to http://example.com/users/1.json
client.users!(params => {:page => 1}})                  #Will make a call to http://example.com/users.json?page=1
client.users.create!({:user => {:name => "Gazler"}})    #POST requst to /users.json
client.users(1).update!({:user => {:name => "Gazler"}}) #PUT or PATCH requst to /users.json
client.users(1).delete!                                 #DELETE requst to /users.json

Example Clients

Facebook

require 'rapidash'

class Me < Rapidash::Base
  url "me"
end

class Facebook < Rapidash::Client
  method :oauth
  resource :me
end

client = Facebook.new({
  :site => "https://graph.facebook.com",
  :uid => "YOUR_ID",
  :secret => "YOUR_SECRET",
  :access_token => "YOUR_TOKEN"
})
p client.me!.first_name #Gary

Github

require 'rapidash'

class Repo < Rapidash::Base
end

class User < Rapidash::Base
  resource :repos
end

class Github < Rapidash::Client
  method :http
  resource :users
  site "https://api.github.com/"
end

client = Github.new
p client.users!("Gazler").name           #Gary Rennie
p client.users("Gazler").repos![0].name  #Githug

HTTP Authentication

require 'rapidash'

class Client < Rapidash::Client
  method :http
  site "your site"
end

client = Client.new({
  :login => "your login",
  :password => "your password",
})

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Write your tests, start and check coverage: open file coverage/index.html in your browser. Must be 100.0% covered
  5. Push to the branch (git push origin my-new-feature)
  6. Create new Pull Request (into the development branch)

rapidash's People

Contributors

allavena avatar gazler avatar paulspringett avatar tonkapark avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

rapidash's Issues

Use Rails model naming convention?

Hello, I've looked your library. It can be so helpful and interesting.
But I've a bit confusing with model naming when I tried use it in my rails project.
Can you name resource classes in the singular like Rails:

class User < Rapidash::Base
  url :members  # or url "members" is also supported
end

class Client < Rapidash::Client
  method :oauth
  resource :users, :repos 
end

And your library is not supported resources with some words like this

class AdminUser
end

class SuperAdminUser
end

class Client < Rapidash::Client
  resource :admin_users, :super_admin_users 
end

LoadError: Expected 
super_admin_users.rb to define Super_admin_users

And I propose to add method resources and resources! for client. It could be used for access to any resources

client.users                       #Returns an instance of Users
client.resources(:users)

client.users!                      #Will make a call to "http://example.com/users.json
client.resources!(:users)

client.users!(1)                   #Will make a call to http://example.com/users/1.json
cliend.resources!(:users, 1)

"Namespaced" resources

I have a resource that I want to namespace under FilterData, is there any way to do that?

I am currently running on development branch.

I have tried the following:

module MyApi
  module FilterData
    class BlacklistedEmail < Rapidash::Base
      url 'filter_data/blacklisted_emails'
    end
  end

  class Users < Rapidash::Base
    url 'users'
  end

  class Client < Rapidash::Client
    method :http
    extension :json

    resource :users, 'filter_data/blacklisted_emails'
  end
end

I then have the following class: MyApi::FilterData::BlacklistedEmail

I am not sure what the most suitable approach is, but right now it will try to lookup MyApi.const_defined?('FilterData::BlacklistedEmail') which is not allowed.

Support for nested resources

Sometimes server response can contains nested resources like this

{"projects":{"foo":"bar","users":{"foo":"bar"}}}

I propose to add hash to resource method

class Project < Rapidash::Base
  resource :projects => :users
  resource "projects" => "users"
end

We will support only one level of nesting.
I think, value may be single or array for many resources.

class Project < Rapidash::Base
  resource :projects => [:users, :issues,...]
end

@Gazler What do you think about it?

Exception for nested resource: `const_get': wrong constant name (NameError)

I'm trying to nest resources as in the example below and getting the following exception

/Users/paul/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/rapidash-0.2.0/lib/rapidash/resourceable.rb:27:in `const_get': wrong constant name Acme::Resources (NameError)
  from /Users/paul/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/rapidash-0.2.0/lib/rapidash/resourceable.rb:27:in `resource'
  from example.rb:16:in `<class:Project>'
  from example.rb:13:in `<module:Resources>'
  from example.rb:12:in `<module:Acme>'
  from example.rb:11:in `<main>'

This is the example code:

require 'rapidash'

module Acme
  module Resources
    class Todo < Rapidash::Base
      root :todo
    end
  end
end

module Acme
  module Resources
    class Project < Rapidash::Base
      root :project

      resource :todo # exception thrown here

      # also tried setting the class name, to no avail
      # resource :todo, class_name: '::Acme::Resources::Todo'
      # resource :todo, class_name: 'Resources::Todo'
      # resource :todo, class_name: Todo'

    end
  end
end

module Acme
  class Client < Rapidash::Client
    method :http
    site "https://acme.com/api/v1/"
    extension :json

    resource :project, class_name: 'Resources::Project'
  end
end

client = Acme::Client.new(login: 'user', password: 'secret')

Am I configuring Rapidash wrong?

It looks like the option to use modules / namespaces was added in pull request #12 but the const_get call was added before that?

Any idea why this isn't working? Or if it would be possible to change these lines https://github.com/mli-max/rapidash/blob/master/lib/rapidash/resourceable.rb#L11-L16 to fix the issue?

Idea: Access subresources on a resource call

I find that sometimes I have a resource call (client.user!(:user_id) and want all the user data. But I also want to call a subresource on the user (client.user(:user_id).favorites)

It would be nice if you could do something like this:

class Client < Rapidash::Client
  method :http
  extension :json
  site 'http://myapi.url/api'

  resource :users, :favorites
end

class User < Rapidash::Base
  url :users
  resource :favorites
end

class Favorite < Rapidash::Base
  url :favorites
end

Then I want to do this:

client = Client.new
user = client.users!(:user_id)

p user.name
p user.favorites

Right now you have to do this:

client = Client.new
user = client.users!(:user_id)
favorites = client.users(:user_id).favorites!

p user.name
p favorites

It doesn't seem so bad, but if you have a few subresources you would like to work with, it quickly gets cumbersome.

Unable to use with an api that returns as javascript content type

I thought this looked interesting and wanted to try it out. First api I tried with failed because the extension is js instead of json and responds with javascript content type even though the data is formatted in json.

Anyways gem looks great but need to consider options for allowed content type responses.

rapidash-0.1.0/lib/rapidash/response.rb:23:in `new': Cannot parse content type: text/javascript; charset=utf-8 (Rapidash::ParseError)

Worked nicely with API that responded with json content type.

Old dependencies

Hello,

Rapidash is pulling in what are now old dependencies.
Using hashie 1.2.0 (now 3.4.2)
Using oauth2 0.9.4 (now 1.0.0)
Using rspec 2.99.0 (now 3.3.0)

The code still works with the updated gem. Tried to make it into a pull request, though I haven't figured out how to get the dependencies to still work for Ruby 1.8.7. I can give a look if you are interested in the PR.

André

Covert this to Elixir

Hi,
Do you think It's possible to use this idea in Elixir? If yes, I could try do this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.