, [">= 1.6.1"])
170 | end
171 | end
172 |
173 |
--------------------------------------------------------------------------------
/app/helpers/apify_helper.rb:
--------------------------------------------------------------------------------
1 | module ApifyHelper
2 |
3 | def api_docs_artifact(action, artifact, nature)
4 | show_id = "#{nature}_#{artifact}_for_#{action.uid}"
5 | show_link = link_to_function('show', "document.getElementById('#{show_id}').style.display = 'block';")
6 | download_url = url_for(:action => action.name, artifact.to_sym => nature.to_s)
7 | download_tooltip = "#{action.method.to_s.upcase} #{download_url} to download"
8 | download_link = link_to('download', download_url, :method => action.method, :title => download_tooltip)
9 | json = JSON.pretty_generate(action.send(artifact, nature))
10 | embedded = "#{json}
"
11 | "#{artifact.to_s.humanize} (#{show_link}, #{download_link})#{embedded}".html_safe
12 | end
13 |
14 | end
15 |
--------------------------------------------------------------------------------
/app/views/apify/api/_actions.html.erb:
--------------------------------------------------------------------------------
1 | Available actions
2 |
3 | <% api.actions.each do |action| %>
4 |
5 |
6 |
7 |
<%= action.method.to_s.upcase %> <%= action.name %>
8 |
9 | <% if action.description %>
10 |
<%= action.description.html_safe %>
11 | <% end %>
12 |
13 |
14 | - Arguments
15 | -
16 | <% if action.takes_args? %>
17 | <%= api_docs_artifact(action, :schema, :args) %>
18 |
19 | <%= api_docs_artifact(action, :example, :args) %>
20 | <% else %>
21 | none
22 | <% end %>
23 |
24 | - Return value
25 | -
26 | <% if action.returns_value? %>
27 | <%= api_docs_artifact(action, :schema, :value) %>
28 |
29 | <%= api_docs_artifact(action, :example, :value) %>
30 | <% else %>
31 | none
32 | <% end %>
33 |
34 |
35 |
36 |
37 |
38 | <% end %>
39 |
--------------------------------------------------------------------------------
/app/views/apify/api/_client.html.erb:
--------------------------------------------------------------------------------
1 | Using the Ruby client
2 |
3 |
4 | An easy way to use the API is to use the Apify::Client
class.
5 | It takes care of the protocol details and lets you focus on exchanging data.
6 |
7 |
8 | Installation
9 |
10 | First install the Apify gem:
11 |
12 | sudo gem install apify
13 |
14 | If your client code is not a Rails application:
15 |
16 | require 'rubygems'
17 | gem 'apify'
18 | require 'apify/client'
19 |
20 | In Rails 2, add the following to your environment.rb:
21 |
22 | config.gem 'apify'
23 |
24 | In Rails 3, add the following to your Gemfile:
25 |
26 | gem 'apify'
27 |
28 | Usage
29 |
30 | client = Apify::Client.new(:host => 'localhost:3000', :user => 'api', :password => 'secret')
31 | client.post('/api/hello', :name => 'Jack') # { 'message' => 'Hello Jack' }
32 |
33 |
34 | Errors can be caught and inspected like this:
35 |
36 |
37 | begin
38 | client.get('/api/hello', :name => 'Jack') # { 'message' => 'Hello Jack' }
39 | rescue Apify::RequestFailed => e
40 | puts "Oh no! The API request failed."
41 | puts "Message: #{e.message}"
42 | puts "Response: #{e.response_body}"
43 | end
44 |
45 |
--------------------------------------------------------------------------------
/app/views/apify/api/_overview.html.erb:
--------------------------------------------------------------------------------
1 | Overview
2 |
3 |
4 | - The API works by exchanging messages encoded in JSON.
5 | - There are no fancy message formats, it's all just sending arbitrary JSON objects back and forth.
6 | - Building a lient cthat consumes the API is very straightforward. Also if you use Ruby, there is a helpful client class available.
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/views/apify/api/_protocol.html.erb:
--------------------------------------------------------------------------------
1 | Protocol
2 |
3 | Requests
4 |
5 |
6 | - The API is accessed over HTTP.
7 | <% if authentication_configured? %>
8 | - HTTP basic authentication is used.
9 | <% end %>
10 | - Take care to use the correct HTTP method (
GET, POST, PUT, DELETE
) as documented for each action.
11 | - Some (but not all) actions take arguments.
12 | - Action arguments are serialized into a single HTTP parameter
args
as JSON.
13 | - You can download an example for a request's arguments by appending
?example=args
to the action URL.
14 | - You can download a JSON schema for a valid request by appending
?schema=args
to the action URL. Using the schema and a library like jasonschema you can validate your requests before sending them. The API will only process requests that conform to this schema.
15 |
16 |
17 | Responses
18 |
19 |
20 | - Successful requests are returned with a status of 200 (OK).
21 | - The body of a successful response is always a hash, serialized as JSON.
22 | - Requests that have errors are returned with a status that is not 200. The body of a error response is an error message in the response's content type (won't be JSON in most cases).
23 | - You can download an example for a successful response value by appending
?example=value
to the action URL.
24 | - You can download a JSON schema for a successful response by appending
?schema=value
to the URL. The API guarantees that all responses conform to this schema.
25 |
26 |
27 | Example for a request/response exchange
28 |
29 |
30 | -
31 | API client sends to API host:
POST http://api-host/api/hello?args=JSON
32 |
33 | where JSON is a serialized JSON object: '{ "name": "Jack" }'
34 |
35 | -
36 | API host returns a response with a status of 200 (OK) and a serialized JSON object as its body:
'{ "message": "Hello Jack" }'
37 |
38 |
39 |
--------------------------------------------------------------------------------
/app/views/apify/api/docs.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | API documentation
6 |
56 |
57 |
58 |
59 |
API documentation
60 | <%= render :partial => 'apify/api/overview' %>
61 | <%= render :partial => 'apify/api/protocol' %>
62 | <%= render :partial => 'apify/api/client' %>
63 | <%= render :partial => 'apify/api/actions' %>
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/examples/client/client.rb:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 | gem 'apify'
3 |
4 | require 'apify/client'
5 |
6 | client = Apify::Client.new(:host => 'localhost', :port => 3000, :user => 'api', :password => 'secret')
7 | puts client.post('/api/hello', :name => 'Jack')
8 |
--------------------------------------------------------------------------------
/examples/host/README:
--------------------------------------------------------------------------------
1 | == Welcome to Rails
2 |
3 | Rails is a web-application framework that includes everything needed to create
4 | database-backed web applications according to the Model-View-Control pattern.
5 |
6 | This pattern splits the view (also called the presentation) into "dumb" templates
7 | that are primarily responsible for inserting pre-built data in between HTML tags.
8 | The model contains the "smart" domain objects (such as Account, Product, Person,
9 | Post) that holds all the business logic and knows how to persist themselves to
10 | a database. The controller handles the incoming requests (such as Save New Account,
11 | Update Product, Show Post) by manipulating the model and directing data to the view.
12 |
13 | In Rails, the model is handled by what's called an object-relational mapping
14 | layer entitled Active Record. This layer allows you to present the data from
15 | database rows as objects and embellish these data objects with business logic
16 | methods. You can read more about Active Record in
17 | link:files/vendor/rails/activerecord/README.html.
18 |
19 | The controller and view are handled by the Action Pack, which handles both
20 | layers by its two parts: Action View and Action Controller. These two layers
21 | are bundled in a single package due to their heavy interdependence. This is
22 | unlike the relationship between the Active Record and Action Pack that is much
23 | more separate. Each of these packages can be used independently outside of
24 | Rails. You can read more about Action Pack in
25 | link:files/vendor/rails/actionpack/README.html.
26 |
27 |
28 | == Getting Started
29 |
30 | 1. At the command prompt, start a new Rails application using the rails command
31 | and your application name. Ex: rails myapp
32 | 2. Change directory into myapp and start the web server: script/server (run with --help for options)
33 | 3. Go to http://localhost:3000/ and get "Welcome aboard: You're riding the Rails!"
34 | 4. Follow the guidelines to start developing your application
35 |
36 |
37 | == Web Servers
38 |
39 | By default, Rails will try to use Mongrel if it's are installed when started with script/server, otherwise Rails will use WEBrick, the webserver that ships with Ruby. But you can also use Rails
40 | with a variety of other web servers.
41 |
42 | Mongrel is a Ruby-based webserver with a C component (which requires compilation) that is
43 | suitable for development and deployment of Rails applications. If you have Ruby Gems installed,
44 | getting up and running with mongrel is as easy as: gem install mongrel.
45 | More info at: http://mongrel.rubyforge.org
46 |
47 | Say other Ruby web servers like Thin and Ebb or regular web servers like Apache or LiteSpeed or
48 | Lighttpd or IIS. The Ruby web servers are run through Rack and the latter can either be setup to use
49 | FCGI or proxy to a pack of Mongrels/Thin/Ebb servers.
50 |
51 | == Apache .htaccess example for FCGI/CGI
52 |
53 | # General Apache options
54 | AddHandler fastcgi-script .fcgi
55 | AddHandler cgi-script .cgi
56 | Options +FollowSymLinks +ExecCGI
57 |
58 | # If you don't want Rails to look in certain directories,
59 | # use the following rewrite rules so that Apache won't rewrite certain requests
60 | #
61 | # Example:
62 | # RewriteCond %{REQUEST_URI} ^/notrails.*
63 | # RewriteRule .* - [L]
64 |
65 | # Redirect all requests not available on the filesystem to Rails
66 | # By default the cgi dispatcher is used which is very slow
67 | #
68 | # For better performance replace the dispatcher with the fastcgi one
69 | #
70 | # Example:
71 | # RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
72 | RewriteEngine On
73 |
74 | # If your Rails application is accessed via an Alias directive,
75 | # then you MUST also set the RewriteBase in this htaccess file.
76 | #
77 | # Example:
78 | # Alias /myrailsapp /path/to/myrailsapp/public
79 | # RewriteBase /myrailsapp
80 |
81 | RewriteRule ^$ index.html [QSA]
82 | RewriteRule ^([^.]+)$ $1.html [QSA]
83 | RewriteCond %{REQUEST_FILENAME} !-f
84 | RewriteRule ^(.*)$ dispatch.cgi [QSA,L]
85 |
86 | # In case Rails experiences terminal errors
87 | # Instead of displaying this message you can supply a file here which will be rendered instead
88 | #
89 | # Example:
90 | # ErrorDocument 500 /500.html
91 |
92 | ErrorDocument 500 "Application error
Rails application failed to start properly"
93 |
94 |
95 | == Debugging Rails
96 |
97 | Sometimes your application goes wrong. Fortunately there are a lot of tools that
98 | will help you debug it and get it back on the rails.
99 |
100 | First area to check is the application log files. Have "tail -f" commands running
101 | on the server.log and development.log. Rails will automatically display debugging
102 | and runtime information to these files. Debugging info will also be shown in the
103 | browser on requests from 127.0.0.1.
104 |
105 | You can also log your own messages directly into the log file from your code using
106 | the Ruby logger class from inside your controllers. Example:
107 |
108 | class WeblogController < ActionController::Base
109 | def destroy
110 | @weblog = Weblog.find(params[:id])
111 | @weblog.destroy
112 | logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
113 | end
114 | end
115 |
116 | The result will be a message in your log file along the lines of:
117 |
118 | Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1
119 |
120 | More information on how to use the logger is at http://www.ruby-doc.org/core/
121 |
122 | Also, Ruby documentation can be found at http://www.ruby-lang.org/ including:
123 |
124 | * The Learning Ruby (Pickaxe) Book: http://www.ruby-doc.org/docs/ProgrammingRuby/
125 | * Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
126 |
127 | These two online (and free) books will bring you up to speed on the Ruby language
128 | and also on programming in general.
129 |
130 |
131 | == Debugger
132 |
133 | Debugger support is available through the debugger command when you start your Mongrel or
134 | Webrick server with --debugger. This means that you can break out of execution at any point
135 | in the code, investigate and change the model, AND then resume execution!
136 | You need to install ruby-debug to run the server in debugging mode. With gems, use 'gem install ruby-debug'
137 | Example:
138 |
139 | class WeblogController < ActionController::Base
140 | def index
141 | @posts = Post.find(:all)
142 | debugger
143 | end
144 | end
145 |
146 | So the controller will accept the action, run the first line, then present you
147 | with a IRB prompt in the server window. Here you can do things like:
148 |
149 | >> @posts.inspect
150 | => "[#nil, \"body\"=>nil, \"id\"=>\"1\"}>,
151 | #\"Rails you know!\", \"body\"=>\"Only ten..\", \"id\"=>\"2\"}>]"
152 | >> @posts.first.title = "hello from a debugger"
153 | => "hello from a debugger"
154 |
155 | ...and even better is that you can examine how your runtime objects actually work:
156 |
157 | >> f = @posts.first
158 | => #nil, "body"=>nil, "id"=>"1"}>
159 | >> f.
160 | Display all 152 possibilities? (y or n)
161 |
162 | Finally, when you're ready to resume execution, you enter "cont"
163 |
164 |
165 | == Console
166 |
167 | You can interact with the domain model by starting the console through script/console.
168 | Here you'll have all parts of the application configured, just like it is when the
169 | application is running. You can inspect domain models, change values, and save to the
170 | database. Starting the script without arguments will launch it in the development environment.
171 | Passing an argument will specify a different environment, like script/console production.
172 |
173 | To reload your controllers and models after launching the console run reload!
174 |
175 | == dbconsole
176 |
177 | You can go to the command line of your database directly through script/dbconsole.
178 | You would be connected to the database with the credentials defined in database.yml.
179 | Starting the script without arguments will connect you to the development database. Passing an
180 | argument will connect you to a different database, like script/dbconsole production.
181 | Currently works for mysql, postgresql and sqlite.
182 |
183 | == Description of Contents
184 |
185 | app
186 | Holds all the code that's specific to this particular application.
187 |
188 | app/controllers
189 | Holds controllers that should be named like weblogs_controller.rb for
190 | automated URL mapping. All controllers should descend from ApplicationController
191 | which itself descends from ActionController::Base.
192 |
193 | app/models
194 | Holds models that should be named like post.rb.
195 | Most models will descend from ActiveRecord::Base.
196 |
197 | app/views
198 | Holds the template files for the view that should be named like
199 | weblogs/index.html.erb for the WeblogsController#index action. All views use eRuby
200 | syntax.
201 |
202 | app/views/layouts
203 | Holds the template files for layouts to be used with views. This models the common
204 | header/footer method of wrapping views. In your views, define a layout using the
205 | layout :default and create a file named default.html.erb. Inside default.html.erb,
206 | call <% yield %> to render the view using this layout.
207 |
208 | app/helpers
209 | Holds view helpers that should be named like weblogs_helper.rb. These are generated
210 | for you automatically when using script/generate for controllers. Helpers can be used to
211 | wrap functionality for your views into methods.
212 |
213 | config
214 | Configuration files for the Rails environment, the routing map, the database, and other dependencies.
215 |
216 | db
217 | Contains the database schema in schema.rb. db/migrate contains all
218 | the sequence of Migrations for your schema.
219 |
220 | doc
221 | This directory is where your application documentation will be stored when generated
222 | using rake doc:app
223 |
224 | lib
225 | Application specific libraries. Basically, any kind of custom code that doesn't
226 | belong under controllers, models, or helpers. This directory is in the load path.
227 |
228 | public
229 | The directory available for the web server. Contains subdirectories for images, stylesheets,
230 | and javascripts. Also contains the dispatchers and the default HTML files. This should be
231 | set as the DOCUMENT_ROOT of your web server.
232 |
233 | script
234 | Helper scripts for automation and generation.
235 |
236 | test
237 | Unit and functional tests along with fixtures. When using the script/generate scripts, template
238 | test files will be generated for you and placed in this directory.
239 |
240 | vendor
241 | External libraries that the application depends on. Also includes the plugins subdirectory.
242 | If the app has frozen rails, those gems also go here, under vendor/rails/.
243 | This directory is in the load path.
244 |
--------------------------------------------------------------------------------
/examples/host/Rakefile:
--------------------------------------------------------------------------------
1 | # Add your own tasks in files placed in lib/tasks ending in .rake,
2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3 |
4 | require(File.join(File.dirname(__FILE__), 'config', 'boot'))
5 |
6 | require 'rake'
7 | require 'rake/testtask'
8 | require 'rake/rdoctask'
9 |
10 | require 'tasks/rails'
11 |
--------------------------------------------------------------------------------
/examples/host/app/controllers/api_controller.rb:
--------------------------------------------------------------------------------
1 | class ApiController < Apify::ApiController
2 |
3 | authenticate :user => 'api', :password => 'secret'
4 |
5 | end
6 |
--------------------------------------------------------------------------------
/examples/host/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | # Filters added to this controller apply to all controllers in the application.
2 | # Likewise, all the methods added will be available for all controllers.
3 |
4 | class ApplicationController < ActionController::Base
5 | helper :all # include all helpers, all the time
6 | protect_from_forgery # See ActionController::RequestForgeryProtection for details
7 |
8 | # Scrub sensitive parameters from your log
9 | # filter_parameter_logging :password
10 | end
11 |
--------------------------------------------------------------------------------
/examples/host/app/helpers/api_helper.rb:
--------------------------------------------------------------------------------
1 | module ApiHelper
2 | end
3 |
--------------------------------------------------------------------------------
/examples/host/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | # Methods added to this helper will be available to all templates in the application.
2 | module ApplicationHelper
3 | end
4 |
--------------------------------------------------------------------------------
/examples/host/app/models/api.rb:
--------------------------------------------------------------------------------
1 | class Api < Apify::Api
2 |
3 | post :hello do
4 |
5 | description 'Greets the given name.'
6 |
7 | schema :args do
8 | object('name' => string)
9 | end
10 |
11 | schema :value do
12 | object('message' => string)
13 | end
14 |
15 | respond do
16 | { 'message' => "Hello, #{args['name']}"}
17 | end
18 |
19 | end
20 |
21 | end
22 |
--------------------------------------------------------------------------------
/examples/host/config/boot.rb:
--------------------------------------------------------------------------------
1 | # Don't change this file!
2 | # Configure your app in config/environment.rb and config/environments/*.rb
3 |
4 | RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
5 |
6 | module Rails
7 | class << self
8 | def boot!
9 | unless booted?
10 | preinitialize
11 | pick_boot.run
12 | end
13 | end
14 |
15 | def booted?
16 | defined? Rails::Initializer
17 | end
18 |
19 | def pick_boot
20 | (vendor_rails? ? VendorBoot : GemBoot).new
21 | end
22 |
23 | def vendor_rails?
24 | File.exist?("#{RAILS_ROOT}/vendor/rails")
25 | end
26 |
27 | def preinitialize
28 | load(preinitializer_path) if File.exist?(preinitializer_path)
29 | end
30 |
31 | def preinitializer_path
32 | "#{RAILS_ROOT}/config/preinitializer.rb"
33 | end
34 | end
35 |
36 | class Boot
37 | def run
38 | load_initializer
39 | Rails::Initializer.run(:set_load_path)
40 | end
41 | end
42 |
43 | class VendorBoot < Boot
44 | def load_initializer
45 | require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
46 | Rails::Initializer.run(:install_gem_spec_stubs)
47 | Rails::GemDependency.add_frozen_gem_path
48 | end
49 | end
50 |
51 | class GemBoot < Boot
52 | def load_initializer
53 | self.class.load_rubygems
54 | load_rails_gem
55 | require 'initializer'
56 | end
57 |
58 | def load_rails_gem
59 | if version = self.class.gem_version
60 | gem 'rails', version
61 | else
62 | gem 'rails'
63 | end
64 | rescue Gem::LoadError => load_error
65 | $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
66 | exit 1
67 | end
68 |
69 | class << self
70 | def rubygems_version
71 | Gem::RubyGemsVersion rescue nil
72 | end
73 |
74 | def gem_version
75 | if defined? RAILS_GEM_VERSION
76 | RAILS_GEM_VERSION
77 | elsif ENV.include?('RAILS_GEM_VERSION')
78 | ENV['RAILS_GEM_VERSION']
79 | else
80 | parse_gem_version(read_environment_rb)
81 | end
82 | end
83 |
84 | def load_rubygems
85 | min_version = '1.3.2'
86 | require 'rubygems'
87 | unless rubygems_version >= min_version
88 | $stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
89 | exit 1
90 | end
91 |
92 | rescue LoadError
93 | $stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
94 | exit 1
95 | end
96 |
97 | def parse_gem_version(text)
98 | $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
99 | end
100 |
101 | private
102 | def read_environment_rb
103 | File.read("#{RAILS_ROOT}/config/environment.rb")
104 | end
105 | end
106 | end
107 | end
108 |
109 | # All that for this:
110 | Rails.boot!
111 |
--------------------------------------------------------------------------------
/examples/host/config/database.yml:
--------------------------------------------------------------------------------
1 | # SQLite version 3.x
2 | # gem install sqlite3-ruby (not necessary on OS X Leopard)
3 | development:
4 | adapter: sqlite3
5 | database: db/development.sqlite3
6 | pool: 5
7 | timeout: 5000
8 |
9 | # Warning: The database defined as "test" will be erased and
10 | # re-generated from your development database when you run "rake".
11 | # Do not set this db to the same as development or production.
12 | test:
13 | adapter: sqlite3
14 | database: db/test.sqlite3
15 | pool: 5
16 | timeout: 5000
17 |
18 | production:
19 | adapter: sqlite3
20 | database: db/production.sqlite3
21 | pool: 5
22 | timeout: 5000
23 |
--------------------------------------------------------------------------------
/examples/host/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file
2 |
3 | # Specifies gem version of Rails to use when vendor/rails is not present
4 | RAILS_GEM_VERSION = '2.3.8' unless defined? RAILS_GEM_VERSION
5 |
6 | # Bootstrap the Rails environment, frameworks, and default configuration
7 | require File.join(File.dirname(__FILE__), 'boot')
8 |
9 | Rails::Initializer.run do |config|
10 | # Settings in config/environments/* take precedence over those specified here.
11 | # Application configuration should go into files in config/initializers
12 | # -- all .rb files in that directory are automatically loaded.
13 |
14 | # Add additional load paths for your own custom dirs
15 | # config.load_paths += %W( #{RAILS_ROOT}/extras )
16 |
17 | # Specify gems that this application depends on and have them installed with rake gems:install
18 | # config.gem "bj"
19 | # config.gem "hpricot", :version => '0.6', :source => "http://code.whytheluckystiff.net"
20 | # config.gem "sqlite3-ruby", :lib => "sqlite3"
21 | # config.gem "aws-s3", :lib => "aws/s3"
22 |
23 | # Only load the plugins named here, in the order given (default is alphabetical).
24 | # :all can be used as a placeholder for all plugins not explicitly named
25 | # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
26 |
27 | # Skip frameworks you're not going to use. To use Rails without a database,
28 | # you must remove the Active Record framework.
29 | # config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
30 |
31 | # Activate observers that should always be running
32 | # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
33 |
34 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
35 | # Run "rake -D time" for a list of tasks for finding time zone names.
36 | config.time_zone = 'UTC'
37 | config.gem 'apify'
38 |
39 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
40 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')]
41 | # config.i18n.default_locale = :de
42 | end
--------------------------------------------------------------------------------
/examples/host/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | # Settings specified here will take precedence over those in config/environment.rb
2 |
3 | # In the development environment your application's code is reloaded on
4 | # every request. This slows down response time but is perfect for development
5 | # since you don't have to restart the webserver when you make code changes.
6 | config.cache_classes = false
7 |
8 | # Log error messages when you accidentally call methods on nil.
9 | config.whiny_nils = true
10 |
11 | # Show full error reports and disable caching
12 | config.action_controller.consider_all_requests_local = true
13 | config.action_view.debug_rjs = true
14 | config.action_controller.perform_caching = false
15 |
16 | # Don't care if the mailer can't send
17 | config.action_mailer.raise_delivery_errors = false
--------------------------------------------------------------------------------
/examples/host/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | # Settings specified here will take precedence over those in config/environment.rb
2 |
3 | # The production environment is meant for finished, "live" apps.
4 | # Code is not reloaded between requests
5 | config.cache_classes = true
6 |
7 | # Full error reports are disabled and caching is turned on
8 | config.action_controller.consider_all_requests_local = false
9 | config.action_controller.perform_caching = true
10 | config.action_view.cache_template_loading = true
11 |
12 | # See everything in the log (default is :info)
13 | # config.log_level = :debug
14 |
15 | # Use a different logger for distributed setups
16 | # config.logger = SyslogLogger.new
17 |
18 | # Use a different cache store in production
19 | # config.cache_store = :mem_cache_store
20 |
21 | # Enable serving of images, stylesheets, and javascripts from an asset server
22 | # config.action_controller.asset_host = "http://assets.example.com"
23 |
24 | # Disable delivery errors, bad email addresses will be ignored
25 | # config.action_mailer.raise_delivery_errors = false
26 |
27 | # Enable threaded mode
28 | # config.threadsafe!
--------------------------------------------------------------------------------
/examples/host/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | # Settings specified here will take precedence over those in config/environment.rb
2 |
3 | # The test environment is used exclusively to run your application's
4 | # test suite. You never need to work with it otherwise. Remember that
5 | # your test database is "scratch space" for the test suite and is wiped
6 | # and recreated between test runs. Don't rely on the data there!
7 | config.cache_classes = true
8 |
9 | # Log error messages when you accidentally call methods on nil.
10 | config.whiny_nils = true
11 |
12 | # Show full error reports and disable caching
13 | config.action_controller.consider_all_requests_local = true
14 | config.action_controller.perform_caching = false
15 | config.action_view.cache_template_loading = true
16 |
17 | # Disable request forgery protection in test environment
18 | config.action_controller.allow_forgery_protection = false
19 |
20 | # Tell Action Mailer not to deliver emails to the real world.
21 | # The :test delivery method accumulates sent emails in the
22 | # ActionMailer::Base.deliveries array.
23 | config.action_mailer.delivery_method = :test
24 |
25 | # Use SQL instead of Active Record's schema dumper when creating the test database.
26 | # This is necessary if your schema can't be completely dumped by the schema dumper,
27 | # like if you have constraints or database-specific column types
28 | # config.active_record.schema_format = :sql
--------------------------------------------------------------------------------
/examples/host/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5 |
6 | # You can also remove all the silencers if you're trying do debug a problem that might steem from framework code.
7 | # Rails.backtrace_cleaner.remove_silencers!
--------------------------------------------------------------------------------
/examples/host/config/initializers/cookie_verification_secret.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Your secret key for verifying the integrity of signed cookies.
4 | # If you change this key, all old signed cookies will become invalid!
5 | # Make sure the secret is at least 30 characters and all random,
6 | # no regular words or you'll be exposed to dictionary attacks.
7 | ActionController::Base.cookie_verifier_secret = '7705dd1c649fa8754fbfa473f251976cbb2021a359e94f9e4a5cbd39c1fa6fdff61fd85e501de515760da8245a2fcce8b1b682aadbe5edd6290107ac3aa6796d';
8 |
--------------------------------------------------------------------------------
/examples/host/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format
4 | # (all these examples are active by default):
5 | # ActiveSupport::Inflector.inflections do |inflect|
6 | # inflect.plural /^(ox)$/i, '\1en'
7 | # inflect.singular /^(ox)en/i, '\1'
8 | # inflect.irregular 'person', 'people'
9 | # inflect.uncountable %w( fish sheep )
10 | # end
11 |
--------------------------------------------------------------------------------
/examples/host/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 | # Mime::Type.register_alias "text/html", :iphone
6 |
--------------------------------------------------------------------------------
/examples/host/config/initializers/new_rails_defaults.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # These settings change the behavior of Rails 2 apps and will be defaults
4 | # for Rails 3. You can remove this initializer when Rails 3 is released.
5 |
6 | if defined?(ActiveRecord)
7 | # Include Active Record class name as root for JSON serialized output.
8 | ActiveRecord::Base.include_root_in_json = true
9 |
10 | # Store the full class name (including module namespace) in STI type column.
11 | ActiveRecord::Base.store_full_sti_class = true
12 | end
13 |
14 | ActionController::Routing.generate_best_match = false
15 |
16 | # Use ISO 8601 format for JSON serialized times and dates.
17 | ActiveSupport.use_standard_json_time_format = true
18 |
19 | # Don't escape HTML entities in JSON, leave that for the #json_escape helper.
20 | # if you're including raw json in an HTML page.
21 | ActiveSupport.escape_html_entities_in_json = false
--------------------------------------------------------------------------------
/examples/host/config/initializers/session_store.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Your secret key for verifying cookie session data integrity.
4 | # If you change this key, all old sessions will become invalid!
5 | # Make sure the secret is at least 30 characters and all random,
6 | # no regular words or you'll be exposed to dictionary attacks.
7 | ActionController::Base.session = {
8 | :key => '_apify-test_session',
9 | :secret => 'bddecc0f5cf89605f636b60d93fc7afe99a1c98025b0349dd98e75728fcda44eea74b349d86af242509cccfd09481fc4f145eb100460c60678feb2a74444f131'
10 | }
11 |
12 | # Use the database for sessions instead of the cookie-based default,
13 | # which shouldn't be used to store highly confidential information
14 | # (create the session table with "rake db:sessions:create")
15 | # ActionController::Base.session_store = :active_record_store
16 |
--------------------------------------------------------------------------------
/examples/host/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Sample localization file for English. Add more files in this directory for other locales.
2 | # See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3 |
4 | en:
5 | hello: "Hello world"
--------------------------------------------------------------------------------
/examples/host/config/routes.rb:
--------------------------------------------------------------------------------
1 | ActionController::Routing::Routes.draw do |map|
2 | Api.draw_routes(map)
3 | end
4 |
--------------------------------------------------------------------------------
/examples/host/db/development.sqlite3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makandra/apify/76bf424f72a223fa93f230529a4a4c9a251a3a67/examples/host/db/development.sqlite3
--------------------------------------------------------------------------------
/examples/host/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # This file should contain all the record creation needed to seed the database with its default values.
2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
3 | #
4 | # Examples:
5 | #
6 | # cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }])
7 | # Major.create(:name => 'Daley', :city => cities.first)
8 |
--------------------------------------------------------------------------------
/examples/host/log/development.log:
--------------------------------------------------------------------------------
1 |
2 |
3 | Processing ApplicationController#index (for 127.0.0.1 at 2010-08-28 14:35:50) [GET]
4 |
5 | ActionController::RoutingError (No route matches "/api/docs" with {:method=>:get}):
6 | /usr/lib/ruby/1.8/mongrel.rb:159:in `process_client'
7 | /usr/lib/ruby/1.8/mongrel.rb:158:in `each'
8 | /usr/lib/ruby/1.8/mongrel.rb:158:in `process_client'
9 | /usr/lib/ruby/1.8/mongrel.rb:285:in `run'
10 | /usr/lib/ruby/1.8/mongrel.rb:285:in `initialize'
11 | /usr/lib/ruby/1.8/mongrel.rb:285:in `new'
12 | /usr/lib/ruby/1.8/mongrel.rb:285:in `run'
13 | /usr/lib/ruby/1.8/mongrel.rb:268:in `initialize'
14 | /usr/lib/ruby/1.8/mongrel.rb:268:in `new'
15 | /usr/lib/ruby/1.8/mongrel.rb:268:in `run'
16 | -e:1:in `load'
17 | -e:1
18 |
19 | Rendering rescues/layout (not_found)
20 |
21 |
22 | Processing ApplicationController#docs (for 127.0.0.1 at 2010-08-28 14:36:02) [GET]
23 |
24 | NameError (uninitialized constant ApiController):
25 | /usr/lib/ruby/1.8/mongrel.rb:159:in `process_client'
26 | /usr/lib/ruby/1.8/mongrel.rb:158:in `each'
27 | /usr/lib/ruby/1.8/mongrel.rb:158:in `process_client'
28 | /usr/lib/ruby/1.8/mongrel.rb:285:in `run'
29 | /usr/lib/ruby/1.8/mongrel.rb:285:in `initialize'
30 | /usr/lib/ruby/1.8/mongrel.rb:285:in `new'
31 | /usr/lib/ruby/1.8/mongrel.rb:285:in `run'
32 | /usr/lib/ruby/1.8/mongrel.rb:268:in `initialize'
33 | /usr/lib/ruby/1.8/mongrel.rb:268:in `new'
34 | /usr/lib/ruby/1.8/mongrel.rb:268:in `run'
35 | -e:1:in `load'
36 | -e:1
37 |
38 | Rendered rescues/_trace (27.3ms)
39 | Rendered rescues/_request_and_response (1.2ms)
40 | Rendering rescues/layout (internal_server_error)
41 |
42 |
43 | Processing ApiController#docs (for 127.0.0.1 at 2010-08-28 14:36:30) [GET]
44 | Rendering apify/api/docs
45 | Rendered apify/api/_overview (0.5ms)
46 | Rendered apify/api/_protocol (1.1ms)
47 | Rendered apify/api/_client (0.7ms)
48 | Rendered apify/api/_actions (18.1ms)
49 | Completed in 44ms (View: 42, DB: 0) | 200 OK [http://localhost/api/docs]
50 |
51 |
52 | Processing ApiController#docs (for 127.0.0.1 at 2010-08-28 14:36:50) [GET]
53 | Rendering apify/api/docs
54 | Rendered apify/api/_overview (0.1ms)
55 | Rendered apify/api/_protocol (0.1ms)
56 | Rendered apify/api/_client (0.1ms)
57 | Rendered apify/api/_actions (12.4ms)
58 | Completed in 16ms (View: 14, DB: 0) | 200 OK [http://localhost/api/docs]
59 |
60 |
61 | Processing ApplicationController#index (for 127.0.0.1 at 2010-08-28 14:36:55) [GET]
62 |
63 | ActionController::MethodNotAllowed (Only post requests are allowed.):
64 | /usr/lib/ruby/1.8/mongrel.rb:159:in `process_client'
65 | /usr/lib/ruby/1.8/mongrel.rb:158:in `each'
66 | /usr/lib/ruby/1.8/mongrel.rb:158:in `process_client'
67 | /usr/lib/ruby/1.8/mongrel.rb:285:in `run'
68 | /usr/lib/ruby/1.8/mongrel.rb:285:in `initialize'
69 | /usr/lib/ruby/1.8/mongrel.rb:285:in `new'
70 | /usr/lib/ruby/1.8/mongrel.rb:285:in `run'
71 | /usr/lib/ruby/1.8/mongrel.rb:268:in `initialize'
72 | /usr/lib/ruby/1.8/mongrel.rb:268:in `new'
73 | /usr/lib/ruby/1.8/mongrel.rb:268:in `run'
74 | -e:1:in `load'
75 | -e:1
76 |
77 | Rendered rescues/_trace (22.7ms)
78 | Rendered rescues/_request_and_response (0.3ms)
79 | Rendering rescues/layout (method_not_allowed)
80 |
81 |
82 | Processing ApplicationController#index (for 127.0.0.1 at 2010-08-28 14:42:54) [GET]
83 |
84 | ActionController::RoutingError (No route matches "/" with {:method=>:get}):
85 | /usr/lib/ruby/1.8/mongrel.rb:159:in `process_client'
86 | /usr/lib/ruby/1.8/mongrel.rb:158:in `each'
87 | /usr/lib/ruby/1.8/mongrel.rb:158:in `process_client'
88 | /usr/lib/ruby/1.8/mongrel.rb:285:in `run'
89 | /usr/lib/ruby/1.8/mongrel.rb:285:in `initialize'
90 | /usr/lib/ruby/1.8/mongrel.rb:285:in `new'
91 | /usr/lib/ruby/1.8/mongrel.rb:285:in `run'
92 | /usr/lib/ruby/1.8/mongrel.rb:268:in `initialize'
93 | /usr/lib/ruby/1.8/mongrel.rb:268:in `new'
94 | /usr/lib/ruby/1.8/mongrel.rb:268:in `run'
95 | -e:1:in `load'
96 | -e:1
97 |
98 | Rendering rescues/layout (not_found)
99 |
100 |
101 | Processing ApiController#docs (for 127.0.0.1 at 2010-08-28 14:42:58) [GET]
102 | Filter chain halted as [:require_api_authentication] rendered_or_redirected.
103 | Completed in 1ms (View: 1, DB: 0) | 401 Unauthorized [http://localhost/api/docs]
104 |
105 |
106 | Processing ApiController#docs (for 127.0.0.1 at 2010-08-28 14:43:01) [GET]
107 | Filter chain halted as [:require_api_authentication] rendered_or_redirected.
108 | Completed in 1ms (View: 1, DB: 0) | 401 Unauthorized [http://localhost/api/docs]
109 |
110 |
111 | Processing ApiController#docs (for 127.0.0.1 at 2010-08-28 14:43:06) [GET]
112 | Rendering apify/api/docs
113 | Rendered apify/api/_overview (0.5ms)
114 | Rendered apify/api/_protocol (1.2ms)
115 | Rendered apify/api/_client (0.8ms)
116 | Rendered apify/api/_actions (16.1ms)
117 | Completed in 92ms (View: 90, DB: 0) | 200 OK [http://localhost/api/docs]
118 |
119 |
120 | Processing ApiController#hello (for 127.0.0.1 at 2010-08-28 15:10:04) [POST]
121 | Parameters: {"args"=>"{\"name\":\"Jack\"}"}
122 | Filter chain halted as [:require_api_authentication] rendered_or_redirected.
123 | Completed in 1ms (View: 1, DB: 0) | 401 Unauthorized [http://localhost/api/hello]
124 |
125 |
126 | Processing ApiController#hello (for 127.0.0.1 at 2010-08-28 15:11:31) [POST]
127 | Parameters: {"args"=>"{\"name\":\"Jack\"}"}
128 | Filter chain halted as [:require_api_authentication] rendered_or_redirected.
129 | Completed in 1ms (View: 1, DB: 0) | 401 Unauthorized [http://localhost/api/hello]
130 |
131 |
132 | Processing ApiController#hello (for 127.0.0.1 at 2010-08-28 15:11:55) [POST]
133 | Parameters: {"args"=>"{\"name\":\"Jack\"}"}
134 |
135 | ActionController::UnknownAction (No action responded to hello. Actions: api, authentication_configured?, and docs):
136 | /usr/lib/ruby/1.8/mongrel.rb:159:in `process_client'
137 | /usr/lib/ruby/1.8/mongrel.rb:158:in `each'
138 | /usr/lib/ruby/1.8/mongrel.rb:158:in `process_client'
139 | /usr/lib/ruby/1.8/mongrel.rb:285:in `run'
140 | /usr/lib/ruby/1.8/mongrel.rb:285:in `initialize'
141 | /usr/lib/ruby/1.8/mongrel.rb:285:in `new'
142 | /usr/lib/ruby/1.8/mongrel.rb:285:in `run'
143 | /usr/lib/ruby/1.8/mongrel.rb:268:in `initialize'
144 | /usr/lib/ruby/1.8/mongrel.rb:268:in `new'
145 | /usr/lib/ruby/1.8/mongrel.rb:268:in `run'
146 | -e:1:in `load'
147 | -e:1
148 |
149 | Rendering rescues/layout (not_found)
150 |
151 |
152 | Processing ApiController#hello (for 127.0.0.1 at 2010-08-28 15:13:09) [POST]
153 | Parameters: {"args"=>"{\"name\":\"Jack\"}"}
154 | Sending data hello.json
155 | Completed in 5ms (View: 1, DB: 0) | 200 [http://localhost/api/hello]
156 |
157 |
158 | Processing ApiController#hello (for 127.0.0.1 at 2010-08-28 15:13:17) [POST]
159 | Parameters: {"args"=>"{\"name\":\"Jack\"}"}
160 |
161 | ActionController::UnknownAction (No action responded to hello. Actions: api, authentication_configured?, and docs):
162 | /usr/lib/ruby/1.8/mongrel.rb:159:in `process_client'
163 | /usr/lib/ruby/1.8/mongrel.rb:158:in `each'
164 | /usr/lib/ruby/1.8/mongrel.rb:158:in `process_client'
165 | /usr/lib/ruby/1.8/mongrel.rb:285:in `run'
166 | /usr/lib/ruby/1.8/mongrel.rb:285:in `initialize'
167 | /usr/lib/ruby/1.8/mongrel.rb:285:in `new'
168 | /usr/lib/ruby/1.8/mongrel.rb:285:in `run'
169 | /usr/lib/ruby/1.8/mongrel.rb:268:in `initialize'
170 | /usr/lib/ruby/1.8/mongrel.rb:268:in `new'
171 | /usr/lib/ruby/1.8/mongrel.rb:268:in `run'
172 | -e:1:in `load'
173 | -e:1
174 |
175 | Rendering rescues/layout (not_found)
176 |
--------------------------------------------------------------------------------
/examples/host/log/production.log:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makandra/apify/76bf424f72a223fa93f230529a4a4c9a251a3a67/examples/host/log/production.log
--------------------------------------------------------------------------------
/examples/host/log/server.log:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makandra/apify/76bf424f72a223fa93f230529a4a4c9a251a3a67/examples/host/log/server.log
--------------------------------------------------------------------------------
/examples/host/log/test.log:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makandra/apify/76bf424f72a223fa93f230529a4a4c9a251a3a67/examples/host/log/test.log
--------------------------------------------------------------------------------
/examples/host/public/404.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 | The page you were looking for doesn't exist (404)
9 |
21 |
22 |
23 |
24 |
25 |
26 |
The page you were looking for doesn't exist.
27 |
You may have mistyped the address or the page may have moved.
28 |
29 |
30 |
--------------------------------------------------------------------------------
/examples/host/public/422.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 | The change you wanted was rejected (422)
9 |
21 |
22 |
23 |
24 |
25 |
26 |
The change you wanted was rejected.
27 |
Maybe you tried to change something you didn't have access to.
28 |
29 |
30 |
--------------------------------------------------------------------------------
/examples/host/public/500.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 | We're sorry, but something went wrong (500)
9 |
21 |
22 |
23 |
24 |
25 |
26 |
We're sorry, but something went wrong.
27 |
We've been notified about this issue and we'll take a look at it shortly.
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/examples/host/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makandra/apify/76bf424f72a223fa93f230529a4a4c9a251a3a67/examples/host/public/favicon.ico
--------------------------------------------------------------------------------
/examples/host/public/javascripts/application.js:
--------------------------------------------------------------------------------
1 | // Place your application-specific JavaScript functions and classes here
2 | // This file is automatically included by javascript_include_tag :defaults
3 |
--------------------------------------------------------------------------------
/examples/host/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2 | #
3 | # To ban all spiders from the entire site uncomment the next two lines:
4 | # User-Agent: *
5 | # Disallow: /
6 |
--------------------------------------------------------------------------------
/examples/host/script/about:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require File.expand_path('../../config/boot', __FILE__)
3 | $LOAD_PATH.unshift "#{RAILTIES_PATH}/builtin/rails_info"
4 | require 'commands/about'
5 |
--------------------------------------------------------------------------------
/examples/host/script/console:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require File.expand_path('../../config/boot', __FILE__)
3 | require 'commands/console'
4 |
--------------------------------------------------------------------------------
/examples/host/script/dbconsole:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require File.expand_path('../../config/boot', __FILE__)
3 | require 'commands/dbconsole'
4 |
--------------------------------------------------------------------------------
/examples/host/script/destroy:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require File.expand_path('../../config/boot', __FILE__)
3 | require 'commands/destroy'
4 |
--------------------------------------------------------------------------------
/examples/host/script/generate:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require File.expand_path('../../config/boot', __FILE__)
3 | require 'commands/generate'
4 |
--------------------------------------------------------------------------------
/examples/host/script/performance/benchmarker:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require File.expand_path('../../../config/boot', __FILE__)
3 | require 'commands/performance/benchmarker'
4 |
--------------------------------------------------------------------------------
/examples/host/script/performance/profiler:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require File.expand_path('../../../config/boot', __FILE__)
3 | require 'commands/performance/profiler'
4 |
--------------------------------------------------------------------------------
/examples/host/script/plugin:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require File.expand_path('../../config/boot', __FILE__)
3 | require 'commands/plugin'
4 |
--------------------------------------------------------------------------------
/examples/host/script/runner:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require File.expand_path('../../config/boot', __FILE__)
3 | require 'commands/runner'
4 |
--------------------------------------------------------------------------------
/examples/host/script/server:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require File.expand_path('../../config/boot', __FILE__)
3 | require 'commands/server'
4 |
--------------------------------------------------------------------------------
/lib/apify.rb:
--------------------------------------------------------------------------------
1 | require 'json'
2 | require 'jsonschema'
3 |
4 | require 'apify/errors'
5 | require 'apify/patterns'
6 | require 'apify/action'
7 | require 'apify/exchange'
8 | require 'apify/api'
9 | require 'apify/schema_helper'
10 | require 'apify/api_controller'
11 | require 'apify/client'
12 |
--------------------------------------------------------------------------------
/lib/apify/action.rb:
--------------------------------------------------------------------------------
1 | module Apify
2 | class Action
3 |
4 | attr_reader :name, :description, :method
5 |
6 | def initialize(method, name, &block)
7 | @method = method
8 | @name = name
9 | @schemas = Hash.new({}.freeze)
10 | instance_eval(&block)
11 | end
12 |
13 | def schema(nature, &block)
14 | nature = nature.to_sym
15 | if block
16 | @schemas[nature] = eval_schema(block)
17 | else
18 | @schemas[nature]
19 | end
20 | end
21 |
22 | def respond(args = nil, &block)
23 | if block
24 | @responder = block
25 | else
26 | Apify::Exchange.new.respond(args, self)
27 | end
28 | end
29 |
30 | def description(description = nil, &block)
31 | if description || block
32 | @description = description ? description : block.call
33 | else
34 | @description
35 | end
36 | end
37 |
38 | def takes_args?
39 | schema(:args) != {}
40 | end
41 |
42 | def returns_value?
43 | schema(:value) != {}
44 | end
45 |
46 | def responder
47 | @responder || lambda {}
48 | end
49 |
50 | def example(schema_nature)
51 | example_for_schema(schema(schema_nature))
52 | end
53 |
54 | def uid
55 | "#{method}_#{name}"
56 | end
57 |
58 | private
59 |
60 | def example_for_schema(schema)
61 | case schema['type']
62 | when 'object'
63 | {}.tap do |object|
64 | if properties = schema['properties']
65 | properties.each do |key, value|
66 | object[key] = example_for_schema(value)
67 | end
68 | end
69 | end
70 | when 'array'
71 | [].tap do |array|
72 | if items = schema['items']
73 | array.concat [example_for_schema(items)] * 2
74 | end
75 | end
76 | when 'boolean'
77 | true
78 | when 'number'
79 | 2.5
80 | when 'integer'
81 | 123
82 | when 'string'
83 | 'string'
84 | else
85 | raise "Unknown schema type: #{schema['type']}"
86 | end
87 | end
88 |
89 | def eval_schema(schema)
90 | lathe = Object.new
91 | lathe.extend Apify::SchemaHelper
92 | lathe.instance_eval(&schema)
93 | end
94 |
95 | end
96 | end
97 |
--------------------------------------------------------------------------------
/lib/apify/api.rb:
--------------------------------------------------------------------------------
1 | module Apify
2 | class Api
3 | class << self
4 |
5 | def action(method, name, args = {}, &block)
6 | method = method.to_sym
7 | name = name.to_sym
8 | if block
9 | action = Apify::Action.new(method, name, &block)
10 | indexed_actions[name][method] = action
11 | actions << action
12 | else
13 | action = indexed_actions[name][method] or raise "Unknown API action: #{name}"
14 | action.respond(args)
15 | end
16 | end
17 |
18 | def get(*args, &block)
19 | action(:get, *args, &block)
20 | end
21 |
22 | def post(*args, &block)
23 | action(:post, *args, &block)
24 | end
25 |
26 | def put(*args, &block)
27 | action(:put, *args, &block)
28 | end
29 |
30 | def delete(*args, &block)
31 | action(:delete, *args, &block)
32 | end
33 |
34 | def actions
35 | @actions ||= []
36 | end
37 |
38 | def indexed_actions
39 | @indexed_actions ||= Hash.new { |hash, k| hash[k] = {} }
40 | end
41 |
42 | def draw_routes(map, options = {})
43 | options[:base_path] ||= 'api'
44 | options[:controller] ||= 'api'
45 | indexed_actions.each do |name, methods|
46 | methods.each do |method, action|
47 | connect_route(map, name, method, options)
48 | end
49 | end
50 | connect_route(map, 'docs', :get, options)
51 | end
52 |
53 | private
54 |
55 | def connect_route(map, name, method, options)
56 | options = options.dup
57 | base_path = options.delete :base_path
58 | map.connect(
59 | base_path ? "#{base_path}/#{name}" : name,
60 | options.merge(:action => name.to_s, :conditions => { :method => method })
61 | )
62 | end
63 |
64 | end
65 | end
66 | end
67 |
--------------------------------------------------------------------------------
/lib/apify/api_controller.rb:
--------------------------------------------------------------------------------
1 | module Apify
2 | class ApiController < ActionController::Base
3 |
4 | helper ApifyHelper
5 |
6 | class << self
7 |
8 | def authenticate(options)
9 | @user = options[:user] or raise "Missing user for authentication"
10 | @password = options[:password] or raise "Missing password for authentication"
11 | @authenticate_condition = options[:if] || lambda { true }
12 | end
13 |
14 | def api(api)
15 | @api = api
16 | @api.indexed_actions.each do |name, methods|
17 | define_method name do
18 | if action = methods[request.method]
19 | if params[:schema].present?
20 | render_schema(params[:schema], action)
21 | elsif params[:example].present?
22 | render_example(params[:example], action)
23 | else
24 | respond_with_action(action)
25 | end
26 | else
27 | render_method_not_allowed(request.method)
28 | end
29 | end
30 | end
31 | @api
32 | end
33 |
34 | end
35 |
36 | skip_before_filter :verify_authenticity_token
37 |
38 | before_filter :require_api_authentication
39 |
40 | def docs
41 | render 'apify/api/docs', :layout => false
42 | end
43 |
44 | def api
45 | configuration(:api)
46 | end
47 |
48 | def authentication_configured?
49 | !!@authenticate_condition
50 | end
51 |
52 | helper_method :api, :authentication_configured?
53 |
54 | private
55 |
56 | def configuration(symb)
57 | self.class.instance_variable_get("@#{symb}")
58 | end
59 |
60 | def respond_with_action(action)
61 | args = params[:args].present? ? JSON.parse(params[:args]) : {}
62 | render_successful_request(action.respond(args), "#{action.name}.json")
63 | rescue Exception => e
64 | render_failed_request(e.message)
65 | end
66 |
67 | def render_successful_request(value, filename)
68 | send_data value.to_json, :status => '200', :type => 'application/json', :filename => filename
69 | end
70 |
71 | def render_failed_request(message)
72 | send_data message, :status => '500', :type => 'text/plain'
73 | end
74 |
75 | def render_method_not_allowed(method)
76 | send_data "Method not allowed: #{method}", :status => 405, :type => 'text/plain'
77 | end
78 |
79 | def render_schema(nature, action)
80 | send_data JSON.pretty_generate(action.schema(nature)), :status => 200, :type => "application/schema+json", :filename => "#{action.name}.schema.json"
81 | end
82 |
83 | def render_example(nature, action)
84 | send_data JSON.pretty_generate(action.example(nature)), :status => 200, :type => "application/json", :filename => "#{action.name}.example.json"
85 | end
86 |
87 | def require_api_authentication
88 | condition = configuration(:authenticate_condition)
89 | if condition && instance_eval(&condition)
90 | authenticate_or_request_with_http_basic do |user, password|
91 | required_user = configuration(:user)
92 | required_password = configuration(:password)
93 | required_user.present? && required_password.present? && user.strip == required_user && password.strip == required_password
94 | end
95 | end
96 | end
97 |
98 | end
99 | end
100 |
--------------------------------------------------------------------------------
/lib/apify/client.rb:
--------------------------------------------------------------------------------
1 | # Require these dependencies here, so code that just uses the client
2 | # can just require 'apify/client' and is not dependent on Rails.
3 | require 'json'
4 | require 'restclient'
5 | require 'apify/errors'
6 | require 'cgi'
7 |
8 | module Apify
9 | class Client
10 |
11 | def initialize(options)
12 | @host = options[:host] or raise "Missing :host parameter"
13 | @port = options[:port]
14 | @protocol = options[:protocol] || 'http'
15 | @user = options[:user]
16 | @password = options[:password]
17 | end
18 |
19 | def get(*args)
20 | request(:get, *args)
21 | end
22 |
23 | def post(*args)
24 | request(:post, *args)
25 | end
26 |
27 | def put(*args)
28 | request(:put, *args)
29 | end
30 |
31 | def delete(*args)
32 | request(:delete, *args)
33 | end
34 |
35 | private
36 |
37 | def request(method, path, args = nil)
38 | params = args ? { :args => args.to_json } : {}
39 | if [:get, :delete].include?(method)
40 | url = build_url(path, params)
41 | params = {}
42 | else
43 | url = build_url(path)
44 | end
45 | json = RestClient.send(method, url, params)
46 | JSON.parse(json)
47 | rescue RestClient::Unauthorized => e
48 | raise Apify::Unauthorized.new("Unauthorized")
49 | rescue RestClient::ExceptionWithResponse => e
50 | raise Apify::RequestFailed.new("API request failed with status #{e.http_code}", e.http_body)
51 | end
52 |
53 | def build_url(path, params = {})
54 | url = ""
55 | url << @protocol
56 | url << '://'
57 | url << "#{@user}:#{@password}@" if @user
58 | url << @host
59 | url << ":#{@port}" if @port
60 | url << path
61 | unless params.empty?
62 | url << '?'
63 | url << params.collect { |k, v| "#{k}=#{CGI::escape(v.to_s)}" }.join('&')
64 | end
65 | url
66 | end
67 |
68 | end
69 | end
70 |
--------------------------------------------------------------------------------
/lib/apify/errors.rb:
--------------------------------------------------------------------------------
1 | module Apify
2 |
3 | class RequestFailed < StandardError
4 |
5 | attr_reader :response_body
6 |
7 | def initialize(message, response_body = nil)
8 | super(message)
9 | @response_body = response_body
10 | end
11 |
12 | end
13 |
14 | class Unauthorized < Apify::RequestFailed
15 | end
16 |
17 | class Invalid < Apify::RequestFailed
18 | end
19 |
20 | end
21 |
--------------------------------------------------------------------------------
/lib/apify/exchange.rb:
--------------------------------------------------------------------------------
1 |
2 | module Apify
3 | class Exchange
4 |
5 | attr_reader :args, :value
6 |
7 | def initialize
8 | @value = nil
9 | @args = nil
10 | end
11 |
12 | def respond(args, action)
13 | # hash_class = defined?(HashWithIndifferentAccess) ? HashWithIndifferentAccess : ActiveSupport::HashWithIndifferentAccess
14 | @args = args.stringify_keys
15 | validate(@args, action.schema(:args), 'Invalid request args')
16 | @value = instance_eval(&action.responder) || {}
17 | @value.stringify_keys!
18 | validate(@value, action.schema(:value), 'Invalid response value')
19 | @value
20 | end
21 |
22 | private
23 |
24 | attr_writer :value
25 |
26 | def validate(object, schema, message_prefix)
27 | JSON::Schema.validate(object, schema) if schema
28 | rescue JSON::Schema::ValueError => e
29 | @value = nil
30 | raise Apify::Invalid.new("#{message_prefix}: #{e.message}")
31 | end
32 |
33 | def sql_datetime(time)
34 | time.present? ? time.strftime("%Y-%m-%d %H:%M:%S") : nil
35 | end
36 |
37 | def sql_date(date)
38 | date.present? ? date.strftime("%Y-%m-%d") : nil
39 | end
40 |
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/lib/apify/patterns.rb:
--------------------------------------------------------------------------------
1 | module Apify
2 | class Patterns
3 |
4 | EMAIL = /\A[a-z0-9\+\-_\.]+@[a-z0-9]+[a-z0-9\-\.]*[a-z0-9]+\z/i
5 | URL = /(http|https):\/\/[\w\-_]+(\.[\w\-_]+)*([\w\-\.,@?^=%&:\/~\+#]*[\w\-\@?^=%&\/~\+#])?/
6 | SQL_DATE = /\A\d{4}-\d{2}-\d{2}\z/
7 | SQL_DATETIME = /\A\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\z/
8 |
9 | end
10 | end
--------------------------------------------------------------------------------
/lib/apify/schema_helper.rb:
--------------------------------------------------------------------------------
1 | module Apify
2 | module SchemaHelper
3 |
4 | def optional(schema)
5 | schema.merge('optional' => true)
6 | end
7 |
8 | def object(properties = nil)
9 | { 'type' => 'object' }.tap do |schema|
10 | schema['properties'] = properties if properties
11 | end
12 | end
13 |
14 | def array(items = nil)
15 | { 'type' => 'array' }.tap do |schema|
16 | schema['items'] = items if items
17 | end
18 | end
19 |
20 | def string
21 | { 'type' => 'string' }
22 | end
23 |
24 | def boolean
25 | { 'type' => 'boolean' }
26 | end
27 |
28 | def enum(schema, allowed_values)
29 | schema.merge('enum' => allowed_values)
30 | end
31 |
32 | def number
33 | { 'type' => 'number' }
34 | end
35 |
36 | def integer
37 | { 'type' => 'integer' }
38 | end
39 |
40 | def sql_date
41 | { 'type' => 'string',
42 | 'pattern' => Apify::Patterns::SQL_DATE.source }
43 | end
44 |
45 | def sql_datetime
46 | { 'type' => 'string',
47 | 'pattern' => Apify::Patterns::SQL_DATETIME.source }
48 | end
49 |
50 | def email
51 | { 'type' => 'string',
52 | 'pattern' => Apify::Patterns::EMAIL.source }
53 | end
54 |
55 | def url
56 | { 'type' => 'string',
57 | 'pattern' => Apify::Patterns::URL.source }
58 | end
59 |
60 | end
61 | end
62 |
--------------------------------------------------------------------------------
/rails/init.rb:
--------------------------------------------------------------------------------
1 | require File.join(File.dirname(__FILE__), '..', 'app', 'helpers', 'apify_helper')
--------------------------------------------------------------------------------
/spec/apify/action_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Apify::Action do
4 |
5 | describe '#uid' do
6 |
7 | it "should return a string uniquely describing the action within an API" do
8 | action = Apify::Action.new(:post, :hello_world) {}
9 | action.uid.should == 'post_hello_world'
10 | end
11 |
12 | end
13 |
14 | describe '#example' do
15 |
16 | it "should return an example for a JSON object matching the schema" do
17 | action = Apify::Action.new(:post, :hello_world) do
18 | schema :value do
19 | object(
20 | 'string_property' => string,
21 | 'integer_property' => integer
22 | )
23 | end
24 | end
25 |
26 | action.example(:value).should == {
27 | 'string_property' => 'string',
28 | 'integer_property' => 123
29 | }
30 |
31 | end
32 |
33 | end
34 |
35 | end
--------------------------------------------------------------------------------
/spec/apify/client_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Apify::Client do
4 |
5 | it "raise an exception if authorization is missing" do
6 | client = Apify::Client.new(:host => 'host')
7 | stub_request(:post, 'http://host/api/method').to_return(:status => 401, :body => 'the body')
8 | expect { client.post '/api/method' }.to raise_error(Apify::RequestFailed)
9 | end
10 |
11 | it "raise an exception if there is a server error" do
12 | client = Apify::Client.new(:host => 'host')
13 | stub_request(:post, 'http://host/api/method').to_return(:status => 500, :body => 'the body')
14 | expect { client.post '/api/method' }.to raise_error(Apify::RequestFailed)
15 | end
16 |
17 | it "should return the parsed JSON object if the request went through" do
18 | client = Apify::Client.new(:host => 'host')
19 | stub_request(:post, 'http://host/api/method').to_return(:status => 200, :body => '{ "key": "value" }')
20 | client.post('/api/method').should == { 'key' => 'value' }
21 | end
22 |
23 | it "should call API methods with arguments" do
24 | client = Apify::Client.new(:host => 'host')
25 | stub_request(:post, 'http://host/api/hello').to_return(:body => '{}')
26 | args = { :name => 'Jack' }
27 | client.post('/api/hello', args)
28 | WebMock.should have_requested(:post, "http://host/api/hello").with(:body => { :args => args.to_json })
29 | end
30 |
31 | it 'should not transmit an args parameter if the arguments are blank' do
32 | client = Apify::Client.new(:host => 'host')
33 | stub_request(:get, 'http://host/api/ping').to_return(:body => '{}')
34 | client.get('/api/ping')
35 | WebMock.should have_requested(:get, "http://host/api/ping")
36 | end
37 |
38 | it "should serialize params into the URL for GET requests" do
39 | client = Apify::Client.new(:host => 'host')
40 | args = { :name => 'Jack' }
41 | stub_request(:get, 'http://host/api/hello').with(:query => { :args => args.to_json }).to_return(:body => '{}')
42 | client.get('/api/hello', args)
43 | WebMock.should have_requested(:get, "http://host/api/hello").with(:query => { :args => args.to_json })
44 | end
45 |
46 | it "should serialize params into the URL for DELETE requests" do
47 | client = Apify::Client.new(:host => 'host')
48 | args = { :name => 'Jack' }
49 | stub_request(:delete, 'http://host/api/terminate').with(:query => { :args => args.to_json }).to_return(:body => '{}')
50 | client.delete('/api/terminate', args)
51 | WebMock.should have_requested(:delete, "http://host/api/terminate").with(:query => { :args => args.to_json })
52 | end
53 |
54 | it "should connect using SSL" do
55 | client = Apify::Client.new(:host => 'host', :protocol => 'https')
56 | stub_request(:get, 'https://host/api/ping').to_return(:body => '{}')
57 | client.get('/api/ping')
58 | WebMock.should have_requested(:get, "https://host/api/ping")
59 | end
60 |
61 | it 'should allow to use a non-standard port' do
62 | client = Apify::Client.new(:host => 'host', :port => '8080')
63 | stub_request(:get, 'http://host:8080/api/ping').to_return(:body => '{}')
64 | client.get('/api/ping')
65 | WebMock.should have_requested(:get, "http://host:8080/api/ping")
66 | end
67 |
68 | end
69 |
70 |
--------------------------------------------------------------------------------
/spec/app_root/app/controllers/api_controller.rb:
--------------------------------------------------------------------------------
1 | class ApiController < Apify::ApiController
2 |
3 | attr_accessor :skip_authentication
4 |
5 | api Api
6 | authenticate :user => 'user', :password => 'password', :if => lambda { !skip_authentication }
7 |
8 | end
9 |
--------------------------------------------------------------------------------
/spec/app_root/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::Base
2 |
3 | end
4 |
--------------------------------------------------------------------------------
/spec/app_root/app/models/api.rb:
--------------------------------------------------------------------------------
1 | class Api < Apify::Api
2 |
3 | post :ping do
4 | respond do
5 | { 'message' => 'pong' }
6 | end
7 | end
8 |
9 | post :fail do
10 | respond do
11 | raise "error message"
12 | end
13 | end
14 |
15 | post :hello do
16 | schema :args do
17 | object('name' => string)
18 | end
19 | schema :value do
20 | object('message' => string)
21 | end
22 | respond do
23 | { 'message' => "Hello #{args['name']}" }
24 | end
25 | end
26 |
27 | post :echo_args do
28 | respond do
29 | args
30 | end
31 | end
32 |
33 | post :with_args_schema do
34 | schema :args do
35 | object("string_arg" => string)
36 | end
37 | end
38 |
39 | post :with_value_schema do
40 | schema :value do
41 | object("string_value" => string)
42 | end
43 | respond do
44 | args
45 | end
46 | end
47 |
48 | get :schema_with_sql_date do
49 | schema :args do
50 | object('date' => sql_date)
51 | end
52 | end
53 |
54 | get :schema_with_sql_datetime do
55 | schema :args do
56 | object('datetime' => sql_datetime)
57 | end
58 | end
59 |
60 | get :schema_with_email do
61 | schema :args do
62 | object('email' => email)
63 | end
64 | end
65 |
66 | get :schema_with_url do
67 | schema :args do
68 | object('url' => url)
69 | end
70 | end
71 |
72 | end
73 |
--------------------------------------------------------------------------------
/spec/app_root/config/boot.rb:
--------------------------------------------------------------------------------
1 | # Allow customization of the rails framework path
2 | RAILS_FRAMEWORK_ROOT = (ENV['RAILS_FRAMEWORK_ROOT'] || "#{File.dirname(__FILE__)}/../../../../../../vendor/rails") unless defined?(RAILS_FRAMEWORK_ROOT)
3 |
4 | # Don't change this file!
5 | # Configure your app in config/environment.rb and config/environments/*.rb
6 |
7 | RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
8 |
9 | module Rails
10 | class << self
11 | def boot!
12 | unless booted?
13 | preinitialize
14 | pick_boot.run
15 | end
16 | end
17 |
18 | def booted?
19 | defined? Rails::Initializer
20 | end
21 |
22 | def pick_boot
23 | (vendor_rails? ? VendorBoot : GemBoot).new
24 | end
25 |
26 | def vendor_rails?
27 | File.exist?(RAILS_FRAMEWORK_ROOT)
28 | end
29 |
30 | def preinitialize
31 | load(preinitializer_path) if File.exist?(preinitializer_path)
32 | end
33 |
34 | def preinitializer_path
35 | "#{RAILS_ROOT}/config/preinitializer.rb"
36 | end
37 | end
38 |
39 | class Boot
40 | def run
41 | load_initializer
42 | Rails::Initializer.run(:set_load_path)
43 | end
44 | end
45 |
46 | class VendorBoot < Boot
47 | def load_initializer
48 | require "#{RAILS_FRAMEWORK_ROOT}/railties/lib/initializer"
49 | Rails::Initializer.run(:install_gem_spec_stubs)
50 | end
51 | end
52 |
53 | class GemBoot < Boot
54 | def load_initializer
55 | self.class.load_rubygems
56 | load_rails_gem
57 | require 'initializer'
58 | end
59 |
60 | def load_rails_gem
61 | if version = self.class.gem_version
62 | gem 'rails', version
63 | else
64 | gem 'rails'
65 | end
66 | rescue Gem::LoadError => load_error
67 | $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
68 | exit 1
69 | end
70 |
71 | class << self
72 | def rubygems_version
73 | Gem::RubyGemsVersion rescue nil
74 | end
75 |
76 | def gem_version
77 | if defined? RAILS_GEM_VERSION
78 | RAILS_GEM_VERSION
79 | elsif ENV.include?('RAILS_GEM_VERSION')
80 | ENV['RAILS_GEM_VERSION']
81 | else
82 | parse_gem_version(read_environment_rb)
83 | end
84 | end
85 |
86 | def load_rubygems
87 | require 'rubygems'
88 | min_version = '1.1.1'
89 | unless rubygems_version >= min_version
90 | $stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
91 | exit 1
92 | end
93 |
94 | rescue LoadError
95 | $stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
96 | exit 1
97 | end
98 |
99 | def parse_gem_version(text)
100 | $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
101 | end
102 |
103 | private
104 | def read_environment_rb
105 | environment_rb = "#{RAILS_ROOT}/config/environment.rb"
106 | environment_rb = "#{HELPER_RAILS_ROOT}/config/environment.rb" unless File.exists?(environment_rb)
107 | File.read(environment_rb)
108 | end
109 | end
110 | end
111 | end
112 |
113 | # All that for this:
114 | Rails.boot!
115 |
--------------------------------------------------------------------------------
/spec/app_root/config/database.yml:
--------------------------------------------------------------------------------
1 | in_memory:
2 | adapter: sqlite3
3 | database: ":memory:"
4 | verbosity: quiet
5 | sqlite:
6 | adapter: sqlite
7 | dbfile: plugin_test.sqlite.db
8 | sqlite3:
9 | adapter: sqlite3
10 | dbfile: plugin_test.sqlite3.db
11 | postgresql:
12 | adapter: postgresql
13 | username: postgres
14 | password: postgres
15 | database: plugin_test
16 | mysql:
17 | adapter: mysql
18 | host: localhost
19 | username: root
20 | password:
21 | database: plugin_test
22 |
--------------------------------------------------------------------------------
/spec/app_root/config/environment.rb:
--------------------------------------------------------------------------------
1 | require File.join(File.dirname(__FILE__), 'boot')
2 |
3 | Rails::Initializer.run do |config|
4 | config.cache_classes = false
5 | config.whiny_nils = true
6 | config.action_controller.session = { :key => "_myapp_session", :secret => "gwirofjweroijger8924rt2zfwehfuiwehb1378rifowenfoqwphf23" }
7 | config.plugin_locators.unshift(
8 | Class.new(Rails::Plugin::Locator) do
9 | def plugins
10 | [Rails::Plugin.new(File.expand_path('.'))]
11 | end
12 | end
13 | ) unless defined?(PluginTestHelper::PluginLocator)
14 | end
15 |
--------------------------------------------------------------------------------
/spec/app_root/config/environments/in_memory.rb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makandra/apify/76bf424f72a223fa93f230529a4a4c9a251a3a67/spec/app_root/config/environments/in_memory.rb
--------------------------------------------------------------------------------
/spec/app_root/config/environments/mysql.rb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makandra/apify/76bf424f72a223fa93f230529a4a4c9a251a3a67/spec/app_root/config/environments/mysql.rb
--------------------------------------------------------------------------------
/spec/app_root/config/environments/postgresql.rb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makandra/apify/76bf424f72a223fa93f230529a4a4c9a251a3a67/spec/app_root/config/environments/postgresql.rb
--------------------------------------------------------------------------------
/spec/app_root/config/environments/sqlite.rb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makandra/apify/76bf424f72a223fa93f230529a4a4c9a251a3a67/spec/app_root/config/environments/sqlite.rb
--------------------------------------------------------------------------------
/spec/app_root/config/environments/sqlite3.rb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makandra/apify/76bf424f72a223fa93f230529a4a4c9a251a3a67/spec/app_root/config/environments/sqlite3.rb
--------------------------------------------------------------------------------
/spec/app_root/config/routes.rb:
--------------------------------------------------------------------------------
1 | ActionController::Routing::Routes.draw do |map|
2 |
3 | Api.draw_routes(map)
4 |
5 | # map.connect 'api/hello', :controller => 'api', :action => 'hello', :conditions => { :method => :get }
6 | # map.connect 'api/fail', :controller => 'api', :action => 'fail', :conditions => { :method => :get }
7 | # map.connect 'api/echo_args', :controller => 'api', :action => 'echo_args', :conditions => { :method => :get }
8 | # map.connect 'api/with_args_schema', :controller => 'api', :action => 'with_args_schema', :conditions => { :method => :get }
9 | # map.connect 'api/with_value_schema', :controller => 'api', :action => 'with_value_schema', :conditions => { :method => :get }
10 | # map.connect 'api/songs', :controller => 'api', :action => 'index_songs', :conditions => { :method => :get }
11 |
12 | end
13 |
--------------------------------------------------------------------------------
/spec/app_root/lib/console_with_fixtures.rb:
--------------------------------------------------------------------------------
1 | # Loads fixtures into the database when running the test app via the console
2 | (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(Rails.root, '../fixtures/*.{yml,csv}'))).each do |fixture_file|
3 | Fixtures.create_fixtures(File.join(Rails.root, '../fixtures'), File.basename(fixture_file, '.*'))
4 | end
5 |
--------------------------------------------------------------------------------
/spec/app_root/script/console:
--------------------------------------------------------------------------------
1 | irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
2 | libs = " -r irb/completion"
3 | libs << " -r test/test_helper"
4 | libs << " -r console_app"
5 | libs << " -r console_with_helpers"
6 | libs << " -r console_with_fixtures"
7 | exec "#{irb} #{libs} --simple-prompt"
8 |
--------------------------------------------------------------------------------
/spec/controllers/api_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe ApiController do
4 |
5 | authenticate = lambda do |*args|
6 | user = args[0] || 'user'
7 | password = args[1] || 'password'
8 | request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(user, password)
9 | end
10 |
11 | describe 'authentication' do
12 |
13 | it "should deny access with the wrong user" do
14 | instance_exec('wrong-user', 'password', &authenticate)
15 | post :ping
16 | response.code.should == '401'
17 | end
18 |
19 | it "should deny access with the wrong password" do
20 | instance_exec('user', 'wrong-password', &authenticate)
21 | post :ping
22 | response.code.should == '401'
23 | end
24 |
25 | it "should grant access with the correct user and password" do
26 | instance_exec('user', 'password', &authenticate)
27 | post :ping
28 | response.code.should == '200'
29 | end
30 |
31 | it "should allow an option to skip authentication" do
32 | controller.skip_authentication = true
33 | post :ping
34 | response.code.should == '200'
35 | controller.skip_authentication = false
36 | post :ping
37 | response.code.should == '401'
38 | end
39 |
40 | end
41 |
42 | describe 'error handling' do
43 |
44 | it 'should fill exception messages into the response body and return a 500 error code' do
45 | instance_exec(&authenticate)
46 | post :fail
47 | response.code.should == '500'
48 | response.body == 'error message'
49 | end
50 |
51 | end
52 |
53 | describe 'args' do
54 |
55 | it 'should have access to the args' do
56 | instance_exec(&authenticate)
57 | args = {'foo' => 'bar'}
58 | post :echo_args, :args => args.to_json
59 | response.code.should == '200'
60 | JSON.parse(response.body).should == args
61 | end
62 |
63 | end
64 |
65 | describe 'argument schemas' do
66 |
67 | before :each do
68 | instance_exec(&authenticate)
69 | end
70 |
71 | it "should validate the presence of a property" do
72 | post :with_args_schema, :args => {}.to_json
73 | response.code.should == '500'
74 | response.body.should include('Invalid request args')
75 | response.body.should include('string_arg is missing')
76 | end
77 |
78 | it "should validate value types" do
79 | post :with_args_schema, :args => {'string_arg' => 123}.to_json
80 | response.code.should == '500'
81 | response.body.should include('Invalid request args')
82 | response.body.should include('a string is required')
83 | end
84 |
85 | it "should allow requests that fit the schema" do
86 | post :with_args_schema, :args => {'string_arg' => 'a string'}.to_json
87 | response.code.should == '200'
88 | end
89 |
90 | it "should render the schema if requested" do
91 | post :with_args_schema, :schema => 'args'
92 | response.code.should == '200'
93 | JSON.parse(response.body).should == {
94 | "type" => "object",
95 | "properties" => {
96 | "string_arg" => { "type" => "string" }
97 | }}
98 | end
99 |
100 | end
101 |
102 | describe 'value schemas' do
103 |
104 | before :each do
105 | instance_exec(&authenticate)
106 | end
107 |
108 | it "should validate the presence of a property" do
109 | post :with_value_schema, :args => {}.to_json
110 | response.code.should == '500'
111 | response.body.should include('Invalid response value')
112 | response.body.should include('string_value is missing')
113 | end
114 |
115 | it "should validate value types" do
116 | post :with_value_schema, :args => {'string_value' => 123}.to_json
117 | response.code.should == '500'
118 | response.body.should include('Invalid response value')
119 | response.body.should include('a string is required')
120 | end
121 |
122 | it "should return responses that fit the schema" do
123 | post :with_value_schema, :args => {'string_value' => 'a string'}.to_json
124 | response.code.should == '200'
125 | JSON.parse(response.body).should == {'string_value' => 'a string'}
126 | end
127 |
128 | it "should render the schema if requested" do
129 | post :with_value_schema, :schema => 'value'
130 | response.code.should == '200'
131 | JSON.parse(response.body).should == {
132 | "type" => "object",
133 | "properties" => {
134 | "string_value" => { "type" => "string" }
135 | }}
136 | end
137 |
138 | end
139 |
140 | describe 'schema helpers' do
141 |
142 | before :each do
143 | instance_exec(&authenticate)
144 | end
145 |
146 | describe '#sql_date helper' do
147 |
148 | it 'should match a date as seen in SQL' do
149 | get :schema_with_sql_date, :args => {'date' => '2011-05-01'}.to_json
150 | response.code.should == '200'
151 | end
152 |
153 | it 'should not match an invalid string' do
154 | get :schema_with_sql_date, :args => {'date' => '01.05.2011'}.to_json
155 | response.code.should == '500'
156 | end
157 |
158 | end
159 |
160 | describe '#sql_datetime helper' do
161 |
162 | it 'should match a timestamp as seen in SQL' do
163 | get :schema_with_sql_datetime, :args => {'datetime' => '2011-05-01 12:10:59'}.to_json
164 | response.code.should == '200'
165 | end
166 |
167 | it 'should not match an invalid string' do
168 | get :schema_with_sql_datetime, :args => {'datetime' => '2011-05-01'}.to_json
169 | response.code.should == '500'
170 | end
171 |
172 | end
173 |
174 | describe '#email helper' do
175 |
176 | it 'should match an email address' do
177 | get :schema_with_email, :args => {'email' => 'some.guy@some.domain.tld'}.to_json
178 | response.code.should == '200'
179 | end
180 |
181 | it 'should not match an invalid string' do
182 | get :schema_with_email, :args => {'email' => 'some.guy'}.to_json
183 | response.code.should == '500'
184 | end
185 |
186 | end
187 |
188 | describe '#url_helper' do
189 |
190 | it 'should match a http address' do
191 | get :schema_with_url, :args => {'url' => 'http://some.domain.tld/path/to?query=value'}.to_json
192 | response.code.should == '200'
193 | end
194 |
195 | it 'should match a https address' do
196 | get :schema_with_url, :args => {'url' => 'https://some.domain.tld/path/to?query=value'}.to_json
197 | response.code.should == '200'
198 | end
199 |
200 | it 'should not match an invalid string' do
201 | get :schema_with_url, :args => {'url' => 'foo:bar:bam'}.to_json
202 | response.code.should == '500'
203 | end
204 |
205 | end
206 |
207 | end
208 |
209 | describe 'auto-generated documentation' do
210 | integrate_views
211 |
212 | it 'should render auto-generated API documentation' do
213 | instance_exec(&authenticate)
214 | get :docs
215 | response.code.should == '200'
216 | response.body.should include('ping')
217 | response.body.should include('fail')
218 | response.body.should include('echo_args')
219 | end
220 |
221 | end
222 |
223 | end
224 |
225 |
--------------------------------------------------------------------------------
/spec/models/api_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe 'Convenient testing of Api models' do
4 |
5 | it 'should allow to test response objects directly' do
6 | Api.post(:hello, :name => 'Jack').should == { 'message' => 'Hello Jack' }
7 | end
8 |
9 | it 'should raise an exception on errors' do
10 | expect { Api.post(:hello) }.to raise_error(Apify::Invalid)
11 | expect { Api.post(:fail) }.to raise_error(StandardError)
12 | end
13 |
14 | end
15 |
--------------------------------------------------------------------------------
/spec/rcov.opts:
--------------------------------------------------------------------------------
1 | --exclude "spec/*,gems/*"
2 | --rails
--------------------------------------------------------------------------------
/spec/spec.opts:
--------------------------------------------------------------------------------
1 | --colour
2 | --format progress
3 | --loadby mtime
4 | --reverse
5 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | $: << File.join(File.dirname(__FILE__), "/../lib" )
2 |
3 | # Set the default environment to sqlite3's in_memory database
4 | ENV['RAILS_ENV'] ||= 'in_memory'
5 |
6 | # Load the Rails environment and testing framework
7 | require "#{File.dirname(__FILE__)}/app_root/config/environment"
8 | require "#{File.dirname(__FILE__)}/../lib/apify"
9 |
10 | require 'spec/rails'
11 | require 'webmock/rspec'
12 |
13 | # Undo changes to RAILS_ENV
14 | silence_warnings {RAILS_ENV = ENV['RAILS_ENV']}
15 |
16 | # Run the migrations
17 | ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate")
18 |
19 | Spec::Runner.configure do |config|
20 | config.use_transactional_fixtures = true
21 | config.use_instantiated_fixtures = false
22 | config.include WebMock::API
23 | end
24 |
--------------------------------------------------------------------------------