Security News
Fluent Assertions Faces Backlash After Abandoning Open Source Licensing
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
The building blocks for building a Sport Ngin Back-end API service:
suppress_response_codes
to params will force a 200 and will only show errors
in the error object of the response bodyAdd this line to your application's Gemfile:
source 'https://D9W5miiTyaf8EzrkWdTy@gem.fury.io/me/' # BELOW THE `source rubygems`
gem 'axel'
Then execute:
$ bundle
In your app/controllers/application_controller.rb
(or wherever your base class is that will
use these helpers) change to:
class ApplicationController < ActionController::Base
include Axel::ControllerHelpers
end
Errors object is available (as errors
) from any controller:
errors.header_status # suppress_response_codes param will set to 200 by default
errors << "Error message!" # add error messages
errors.display # { status: errors.status_code, messages: errors.messages }
errors.display? # Display errors? (was there an error added or status changed?)
errors.messages
errors.messages = []
errors.status = :not_found
errors.status_code # => 404
errors.status = 403
errors.status_code # => 403
errors.new_error(status, *m) # set status, add an error or list of errors (not in an array object)
# Can also set on the fly:
rescue_error status: :not_found, message: "Error!"
rescue_error status: :unproccessable_entity, messages: ["Error!", "Error2!"]
Metadata object that will be placed on every outgoing response body. You can add to the object like so:
metadata[:current_user] = current_user
# the body will then set this on the outgoing body:
# => { "metadata": { "current_user": "..." }, "result": "...", "...": "..." }
At the top of each controller (for APIs) should be:
respond_to_json_xml
This defines respond_to :json, :xml
.
making these responders good to use for defaults:
respond_with_action :show # Good for the end of a create to show the created object
render_action :show
respond_to_empty # Render empty `result`, fill in `metadata`, `error` if necessary
render_empty
find_resource
will automatically find a resource:
class PostsController < ApplicationController
before_filter :find_resource
def show
respond_with
end
end
curl http://localhost:3000/posts/1 # finds Post 1 and renders
curl http://localhost:3000/posts/1
# => {"metadata":{},"error":{"status":404,"messages":["Record not found"]},"result":null}
# can also customize the find_resource with `finder` and `value`
# were `finder` is column and `value` is the value of the column
query_params # Only params on the query string
post_params # POST params
object_params # Either params under the object name (ie. {"user":".."} or all POST params
object_name # singularized controller name for finding object_params
Helpers:
force_ssl! # raises Errors::ForceSSL
drop_meta! # we don't want the requester to get data like current_user, etc.
drop_meta? # Did we call `drop_meta!`?
format # The format passed from the request OR JSON
render_nil_format # This is for rendering nils in json or XML (XML is blank, JSON is "null")
safe_json_load # If you've already manually rendered some to json this helper safely loads it to a hash for re-JSONing
Errors are rescued to make for easier API workflow and responding:
Axel::Errors::ForceSSL # Drop meta
# Status: Forbidden
# Message: SSL is required
ActiveRecord::RecordNotFound # Status: 404
# Message: Record not found
Axel::Errors::NotAuthorized # Status: 401
# Message: User not authorized
ActiveModel::MassAssignmentSecurity::Error # Status: 422
# Message: Unacceptable parameter being used
Axel.config do |config|
config.add_resource :user_service,
:group,
service: { url: "https://user-service.your-platform.com" }
# Custom Path (otherwise defaults to plural of the resource_name (:user => "/users"))
# config.add_resource :user_service,
# :user,
# service: { url: "https://user-service.your-platform.com" },
# attributes: [:user_name, :first_name],
# path: "owner"
end
class Group < Axel::ServiceResource::Base
# Let's say your class doesn't match the configured resource, you can:
resource_name :group
# Setup fields (gets accessors, all available in #attributes)
field :name
field :owner_id
field :owner_type
field :uri
route "/groups/mine", :mine
route "/user/:user_id/groups", :by_user_id
# Attached to every Group request, you can define instance defaults as well
def self.default_request_options
{ headers: { "Accepts" => "stuff!", Authorization: "Bearer #{some_access_token}" } }
end
end
group = Group.new name: "test", owner_id: 1, owner_type: "Organization", uri: "blargh"
group.save
my_groups = Group.mine
user_groups = Group.by_user_id(1)
user_groups = Group.by_user_id(user_id: 1)
a_group = Group.find(1)
class User < Axel::ServiceResource::Base
has_many :personas
has_one :email_address, class: Email, included: true
end
class Email < Axel::ServiceResource::Base
belongs_to :user, find_nested: true
end
class Persona < Axel::ServiceResource::Base
belongs_to :user
end
u = User.find(1)
u.personas # => API call to /users/1/personas puts data in an array of Persona objects
u.email_address # => Uses `email_address` in the User data to put into Email objects
Persona.find(1).user # => API call to /users/#{persona.user_id} fills User object
Email.find(1).user # => API call to /personas/1/user fills User Object
Group.where(name: "test")
# => https://user-service.your-platform.com/groups?name=test
Group.all params: { name: "test" }, body: jsonified_stuffs, headers: {}, method: :post
Group.uri("https://user-service.dev/groups").where(name: "Jon").all(headers: {})
# => http://user-service.dev/groups?name=Jon
Group.uri("https://user-service.dev").at_path("/other_groups_path").where name: "test"
# => http://user-service.dev/other_groups_path?name=test
Group.where(name: "Jon").all(headers: {}).none
# => [] # Will always be empty array
Group.none.where(name: "Jon")
# => [] # can chain
Group.without_default_path.at_path("groupies")
# => https://user-service.your-platform.com/groupies
# Enumerable works!
Groups.where(name: "test").each { |g| puts e.attributes.inspect }
groups = Groups.where(name: "test").to_a
# drop cached JSON, then you can requery
groups.reload.where(owner_id: 1)
new_user.metadata # => { .. } # Metadata section of JSON output
new_user.metadata[:current_user] # => { "id"=>1, "user_name"=>"admin", "first_name"=>"Happy", "last_name"=>"Gilmore", "uri"=>"http://user-service.dev/users/1"}
new_user.errors.status_code # => 200
new_user.errors.messages # => []
new_user.result # => { ... } # Main envelope JSON body
For more info on what the requester is and can do check out Axel::ServiceResource::Base
git checkout -b my-new-feature
)git commit -am 'Add some feature'
)git push origin my-new-feature
)FAQs
Unknown package
We found that axel demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
Research
Security News
Socket researchers uncover the risks of a malicious Python package targeting Discord developers.
Security News
The UK is proposing a bold ban on ransomware payments by public entities to disrupt cybercrime, protect critical services, and lead global cybersecurity efforts.