IORD is a runtime scaffolding system based on an easy way to represent data.
IORD stands for Information Oriented Representation of Data.
It can be used to easily create customizable CRUD based controllers and scaffold views automatically. IORD also handles strong parameters verification based on the given data.
Add iord to your Gemfile:
gem 'iord'And run bundle install within your app's directory.
The easiest way to use IORD is to define a route with the iord/generic controller:
# config/routes.rb
resources :products, controller: 'iord/generic'This will automatically handle the CRUD methods and display the data from the Product.
The attributes displayed will be the model's attributes except deleted_at on all views
and _id, created_at, updated_at on index, new and edit.
You can still customize the views by creating the corresponding file in app/views/products/.
For namespaced resources, use the following syntax:
namespace :admin, module: nil do
resource :products, controller: 'iord/generic'
end
namespace :admin do
# normal admin scoped routes, which controllers will be in module Admin
endThe model used in this case is still ::Product.
You can also create your own route pointing to your controller, for example:
# config/routes.rb
resources :products
# app/controllers/products_controller.rb
require 'iord/controller'
class ProductsController < ApplicationController
include Iord::Controller
endYou can then override the actions, change the displayed attributes, ...
Views will be loaded from the corresponding views directory and default to IORD views.
For namespaced routes, you don't have to specify module: nil as for the quick method,
and the model used will still be ::Product.
IORD ships with generators to automatically create controllers:
rails generate iord:controller productCreates a controller including Iord::Controller with default attribute methods.
rails generate iord:scaffold customer firstname lastnameScaffolds the model and the controller, which will have specialized attribute methods based on the specified attributes.
This documentation provides customization information which are mainly available if you use your own controller.
IORD defines a lot of helper methods to retrieve the attributes to display:
show_attrs # used for `show` action
# defaults to resource_class.attribute_names.map{|i| i.to_sym} - %i(deleted_at)
index_attrs # used for `index` action
# defaults to `attrs`
new_attrs # used for `new` and `create` action
# defaults to `form_attrs`
edit_attrs # used for `edit` and `update` action
# defaults to `form_attrs`
form_attrs # defaults to `attrs`
attrs # defaults to `show_attrs` - %i(_id created_at updated_at)IORD's attributes are used to generate the views and the parameters requirements / permissions.
The default and basic attributes methods return and array of symbols directly matching the model's attributes.
For more complex cases, there are two kinds of data expected:
- display-oriented attributes for
show_attrsandindex_attrs. - form-oriented attributes for
new_attrsandedit_attrs.
Both complex cases attributes are fully recursive, meaning you can have nested objects.
Display-oriented attributes are either symbols or hashes.
Symbols are directly sent to the resource and the corresponding value is used. The name displayed for the attribute will be a humanized version of itself.
Hashes permit more complex structures based on the presence of a specific key. The value used depends on the first keys encountered given this order:
-
:arraywill display an array of attributes, typically an has_many relation.It will list each element inside an
uland display them as if they had the:objectkey with the attributes in the:attrfield.The name of the attribute will be a humanized version of the value of
:array -
:objectexpects the hash to also have the:attrskey mapped to an array of display-oriented attributes.It will use the same logic as the action but will display the values of the object it gets by calling the value of
:objecton the resource.The name of the attribute will be a humanized version of the value of
:object -
:valueis a fully customizable attribute which value will be used as the name of the attribute.The value of the attribute is computed using the
:formatmapped value which should be aProc.Depending on the current resource to respond to the
:valuemapped value, the proc will either receive the corresponding value or the resource and the:valuemapped value. -
:imagewill display the image at the url returned by the resource when calling:imagemapped value. -
:linkwill display a link to the url returned by the resource when calling:linkmapeed value. -
In any other case, it calls itself recursively by replacing the current resource by the value returned by the resource when calling the method named after the first key, and the attributes by the value of the first key.
The name of the attribute will be a humanized version of the first key.
In other words, in the products controller, the following code displays the value
category.to_slabelledCategory:{category: :to_s}
Having
{category: :to_s}will return the value of@resource.category.to_s.
Another example would be{category: {description: :to_html}}which will call@resource.category.description.to_html
Form-oriented attributes are either symbols, arrays or hashes.
Symbols are displayed using f.text_field for the input, and f.label for the label.
Arrays are displayed using f.public_send *attr for the input, and f.label attr[1] for the label.
Example:
def form_attrs
[
:name,
[:select, :category_id, Category.all.collect{|c| [c.name, c.id]}]
]
endThis will display a form with a text field labelled Name and a select labelled Category.
Hashes permit more complex structures based on the presence of a specific key.
The label will have either the value of the :attr key humanized, or the value of the :label key,
if present. Lastly, if the array has the :hidden key, then no label is displayed.
The value used depends on the first keys encountered given this order:
-
:fieldswill trigger a nested form (using the NestedForm gem), for the object referenced by the attribute mapped by:attr.The
:fieldsis mapped to an array of form-oriented attributes.It will display either one or many objects depending on the kind of relation. When displaying many objects, it will also add the
Add a ...andRemove this ...links.When displaying many objects, you can add the key
:not_new_recordto prevent it from being displayed on new objects (usefull foridfor example). -
:field, which type is check:-
when Array, uses
f.public_send*attr[:field]`.This is quite similar to directly giving an Array, but allows to change the label.
-
when Hash, calls the controller method in field
attr[:field][:helper][0]The:helpersub-key should be an array.The method should accept at least 2 arguments:
- the form object (from
form_fororfields_for) - the current attr Hash
- any other parameters provided (
attr[:field][:helper][1..-1])
- the form object (from
-
IORD uses @resource to store a model instance and @collection to store the collection.
The @resource is initialized only in resource-based actions and not in collection-based actions
such as index.
You can add a resource-based action using the following class methods:
# app/controllers/products_controller.rb
require 'iord/controller'
class ProductsController < ApplicationController
include Iord::Controller
resource_actions :inc_qty
# or
resource_actions :inc_qty, :dec_qty
# or
resource_actions [:inc_qty, :dec_qty]
# to replace any existing actions:
resource_actions! :show, :destroy
endIORD defines several URL helpers:
collection_url
new_resource_url
resource_url(resource = nil)
edit_resource_url(resource = nil)You can set the model's namespace using the following class methods:
# app/controllers/products_controller.rb
require 'iord/controller'
class ProductsController < ApplicationController
include Iord::Controller
set_resource_namespace Subsidiary
# or the other syntax this one is aliased to:
self.resource_namespace = Subsidiary
endThe model loaded will now be Subsidiary::Product.
You can query information on the resource using the following controller helper methods:
resource_class, complete model class constantresource_name, humanized version of the model class nameresource_name_u, underscore version of the model class namecollection_name, humanized version of the collection name (plural ofresource_name)resource_path, array of the modules as Symbol in which the model is nestedaction_path, path used to access the controller, used by url helpers.
You can add a response format with the following class method:
# app/controllers/products_controller.rb
require 'iord/controller'
class ProductsController < ApplicationController
include Iord::Controller
crud_response_format do |instance, format, action|
case action
when :index
format.json { instance.render json: @resource_class.all }
end
end
endThis project rocks and uses MIT-LICENSE.
Copyright 2014 Geoffroy Planquart
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.