Brick Layer
The concept behind Brick Layer is to have a site manager that includes CMS as a feature. It should be easy to plug into any Rails 3.1 application. It provides the bare minimum support to get up and rolling quickly with a basic CRUD data management system that easily outputs JSON as an alternative format by default.
Features
-
CRUD and RESTful DataSet Support
-
If you just need to have a system of any kind of data that outputs to json
-
-
Search Support
-
Searching across a certain set of data or all data sets should be easy
-
-
Routing Support
-
Easily tie a route to a certain data set endpoint
-
-
Auto UI Generation
-
Allow the dataset definitions to generate your user interface for you
-
-
User Authentication
-
Basic User Authentication Setup
-
-
Custom Config API
-
Easily ping the app to get JSON format delivery of existing Routes and other configuration
-
Requirements
-
Right now this requires Mongo which currently provides the maximum flexibility in what the use cases are.
Installation
Add the gem to your Rails 3.1 application Gemfile and that’s it!
gem 'brick_layer'
Also in your ‘app/assets/stylesheets’ directory add:
//= require brick_layer
Associated Gems
This gem can work with other code that can server as clients.
Data Sets
To define a data set:
# You can name your data set whatever you want, but you probably want to try and end it with “DataSet” as a convention
class ShipDataSet < BrickLayer::DataSet
field :name, type: String
field :size, type: String
end
This will include the timestamps and text search abilities (if you need them) by default. After creating a data set or a few, it should be accessible via:
http://<host>:<port>/brick_layer/data-sets/ship_data_sets
OR EVEN BETTER
http://<host>:<port>/brick_layer/data-sets/ship_data_sets.json
If you want to make a method accessible in the data set json you can just:
class ShipDataSet < BrickLayer::DataSet
field :name, type: String
field :size, type: String
expose_data :my_method
def my_method(={})
"result from my method"
end
end
This will make the method’s result available in the json in the format:
{ my_method: "result from method" }
The options variable is there to support changing up the data if you want for some reason. The default html view on a page data set will pass { :html => true } as an option to the exposed data method. So you can format the display of exposed data methods if you want.
class ShipDataSet < BrickLayer::DataSet
field :name, type: String
field :size, type: String
expose_data :my_method
def my_method(={})
if [:html]
"something that is readable in an html view"
else
"some other format for json display"
end
end
end
CRUD and Auto Form Builder
There is a built in auto-crud system with simple styles to handle quickly adding data to the database.
Brick Layer is using simple form to help support the auto building for HTML5 forms for custom field types. You can find out more about simple form at github.com/plataformatec/simple_form
Using the UI form builder is fairly easy. It’ll automatically read the fields you define on a model and display them correctly.
Let’s say we define a standalone data set like:
class Product < BrickLayer::DataSet
field :name, type: String
field :release_date, type: DateTime
field :publish, type: Boolean
end
Then we head over to:
http://<host>:<port>/brick_layer/data-sets/products
From there will be able to create a new product and the fields will be formatted to match the data types we’ve described here.
Now, I know what you are thinking - what about when I want to have a file field or something similar. That’s easy to:
class Product < BrickLayer::DataSet
field :name, type: String
field :release_date, type: DateTime
field :publish, type: Boolean
custom_field :description, :text
custom_field :website, :url
custom_field :phone, :phone
custom_field :avatar, :image # This requires you have imagemagick installed
end
All you have to do is say ‘custom_field_type’ with whatever mapping that is supported by simple form.
File and Image Uploads
Brick Layer is using a combo of dragonfly and carrierwave to allow resizing support of images by passing dimension variables into your data set for custom_fields with the ‘image’ type.
class Employee < BrickLayer::DataSet
custom_field :avatar, :image, { :sizes => { :small => "50x50>", :large => "400x400#" } }
custom_field :badge, :image, { :sizes => { :small => "50x50>", :large => "400x400#" } }
custom_field :resume, :file
end
The uploaded file will be located at: “/files/”. The uploaded image will be located at: “/media//[image_name]”.
Note this data will then be available in your JSON data load and that the fields “avatar_small” and “avatar_large” will be in different paths.
Enable Supported WYSIWYG for Text Fields
You can pass simple form supported options into your custom field to enable the built in WYSIWYG editor or whatever else you want to pass to the view.
class Product < BrickLayer::DataSet
custom_field :description, :text, { :input_html => { :class => "withEditor" } }
end
Relationships
Relationships are also supported so you can add those and the fields should automatically show up.
class Owner < BrickLayer::DataSet
field :name
has_one :company, autosave: true
def to_s
self.name
end
end
class Company < BrickLayer::DataSet
field :name
belongs_to :owner
has_many :employees, autosave: true
def to_s
self.name
end
end
class Employee < BrickLayer::DataSet
belongs_to :company
field :first_name, type: String
field :last_name, type: String
field :dob, type: DateTime
end
The defined “to_s” method will be used when displaying item information in the form fields.
Admin UI Control (CUSTOM DATA SET LINKS)
If you choose to use the view navigation outside of just using URLs you can add the standalone classes you want to show in an initializer file.
# config/initializers/brick_layer_init.rb (or whatever you want)
BrickLayer.data_sets_standalones = [:companies, :employees]
This will add these classes to the “Custom Data Sets Link” in the admin navigation and also initialize the navigation link to show all together.
Admin UI Control (ROUTES and PAGES)
The concept behind the admin of brick layer when it comes to pages is that you don’t have to use them unless you want to. In order to get a page (which is basically a route with a data set) requires little work. There is a conventional way of using pages.
First you have to enable page support by adding this configuration to your initializer file:
# config/initializers/brick_layer_init.rb (or whatever you want)
BrickLayer.enable_pages = true
Once that is done you’ll get a pages link that’ll allow you to create new routes and attach data sets to them. So the way this works is that you define your dataset for page just like any other dataset. Except you put it in your models/page_data_sets/directory (this is a convention)
# app/models/page_data_sets/home_page
class PageDataSets::HomePage < BrickLayer::DataSet
belongs_to :company
field :welcome_message, type: String
field :blurb, type: String
custom_field :welcome_message, :text
end
Once you do this and you go to create a route you’ll get the option to select the data set associated with the route. Once you create the route it’ll redirect you to the edit page for that route which will show the custom form fields associated with that page. That’s it!
So all you have to do at this point is create data sets that you want to associate with a page that’ll be made available when you request the page. Don’t forget that you can aggregate more data on a page as well.
For example, let’s say you have a product custom data set already and you want to display the 10 most recent on the homepage. You can do this:
# app/models/page_data_sets/home_page
class PageDataSets::HomePage < BrickLayer::DataSet
belongs_to :company
field :welcome_message, type: String
field :blurb, type: String
custom_field :welcome_message, :text
expose_data :most_recent_products
def most_recent_products(={})
DummyCompany.order_by(:created_at,"DESC").limit(10)
end
end
That data will be made available for that page attached to that route!
Also, let’s say that you want to give the administrator control over what the limit to display on that page is. No sweat, you would:
# app/models/page_data_sets/home_page
class PageDataSets::HomePage < BrickLayer::DataSet
belongs_to :company
field :welcome_message, type: String
field :blurb, type: String
field :limit, type: Integer
custom_field :welcome_message, :text
expose_data :most_recent_products
def most_recent_productss(={})
product_limit = 10 || self.limit
DummyCompany.order_by(:created_at,"DESC").limit(product_limit)
end
end
You can access this data at:
http://<host>:<port>/brick_layer/your-route-here
AND OF COURSE in JSON!
http://<host>:<port>/brick_layer/your-route-here.json
Authentication for Admin Access
By default there isn’t an administrator set in Brick Layer. Once you create 1 the brick layer admin will automatically lock and you will be able to login using the correct username and password.
Authentication of Content with Token
By default all requests for endpoints using the json format on “index”(list) and “show” actions will be exposed.
However, if you set a token in your “initializers/bricklayer_init.rb” file or similar to:
Bricklayer.token = "your-token-here"
It will force require any access to the brick layer data to have the header “X-AUTH-TOKEN” set in the request for the data to match that token.
Search
To search all data sets you can ping the url with the path to search and pass it params. The search supports most mongo queries.
So you can:
http://<host>:<port>/brick_layer/data-sets/search?title_in="document title"
If you want to search on a specific data set just pass it in as a model param:
http://<host>:<port>/brick_layer/data-sets/search?title_in="document title"&models="ship_data_set"
You can also chain queries together:
http://<host>:<port>/brick_layer/data-sets/search?queries[title_in]="document title"&queries[meta_description_in] = "meta description"
Just add .json to the end of ‘search’ and you get results in json format:
http://<host>:<port>/brick_layer/data-sets/search.json?title_in="document title"