Retro Rubies

Everything what is today IN will be tomorrow OUT and the day after it will be RETRO.

Refinery 2, episode: New engines

| Comments

I’m really suprised, because more than 500 people were reading my last (first) article about new Refinery CMS features. I decided to write more about new Refinery 2 features. This article will focus on new Refinery engine generator. It is really new hot stuff.

What are those refinery engines about?

Refinery comes with engine and form generator. Engine generator create whole CRUD on backend and pages on frontend. Refinery 1 (still stable now) had engine generator also, but it was very limited. I want to share some examples how to use new engine generator to make your life easier.

Introducing new engine generator in dumb examples

Simple engine for serving ads

We have nothing, only shell and bundler with installed latest stable rails.

1
2
3
4
5
6
rails new example -m http://refinerycms.com/t/edge
cd example
rails g refinery:engine ad name link picture:image --namespace marketing --engine retro_rubies --skip-frontend
bundle install
rails generate refinery:retro_rubies
rake db:migrate

In vendor/engines/retro_rubies is generated Refinery engine with ad model and complete admin CRUD. Engine is called retro_rubies, fully namespaced into Marketing namespace and backend is tested with few rspec requests. That’s great start. You can add some ad partial into vendor/engines/retro_rubies/app/views/marketing/ads/_ad.html.erb and render it in layout with some random ad.

Team members engine

So we have some basic ad functionality. Now we will add our team members.

1
2
3
4
rails g refinery:engine member name born:date face:image --namespace office --engine retro_rubies
rails generate refinery:retro_rubies
rake db:migrate
rake db:seed

This will generate both backend and frontend parts. So you can add team members in admin and view list and detail on frontend. Just few CSS tweaks and it is finished.

Team member quotes

It will be nice to add quotes to our team members, so we can show random member with his quote on each page.

1
2
3
4
rails g refinery:engine quote name content member_id:integer --namespace office --engine retro_rubies --skip-frontend
rails generate refinery:retro_rubies
rake db:migrate
rake db:seed

Now we just need to add model relations.

1
2
3
4
5
# member.rb
has_many :quotes, :class_name => '::Refinery::Office::Quote'

# quote.rb
belongs_to :member, :class_name => '::Refinery::Office::Member'

And finally edit quote form for better UI.

1
2
3
<%= f.number_field :member_id  -%>
# replace with
<%= f.collection_select :member_id, ::Refinery::Office::Member.all, :id, :name  -%>

Now we just need to tweak layout again. Mabye create some member_quote partial and render it with random quote where we want.

And what about localized site?

Refinery’s one great feature is localization support. Now with my hot patch, you can generate fully localized engines as well. Engine generator is extended with --i18n option. If we want translateble quotes from last paragraph, we just need to run this line to generate quotes.

1
rails g refinery:engine quote name content member_id:integer --namespace office --engine retro_rubies --skip-frontend --i18n name content

Now name and content will be saved in separate table. But it will act transparently thanks to globalized3 gem. In backend you will be able to translate name and content column.

Conclusion

I know those examples are really stupid. But in short, we can generate what we need and with small tweaks we can achieve great result just in few minutes. You can pack all generated stuff into one engine or split into multiple (by --engine option). You can divide logic in engine with --namespace option and specify translated columns with --i18n option. When you don’t need frontend, just add --skip-frontend and it will be skipped. There are also included some basic readme.md and gemspec in every generated engine. And suprisingly all generated features are shipped with some basic specs (i18n also). You can just aim to add some custom logic instead of repeating same code again and again.

And what about some custom contact form?

There is also form engine generator. You can easily generate contact or job application form. It’s super easy. I think this doesn’t need longer description.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[retro@retro  enginium]$ rails g refinery:form
Usage:
  rails generate refinery:form NAME [field:type field:type] [options]
...
Additional Supported Field Types

  All field types that are supported by the Refinery Engine generator are supported
  with the addition of these form specific ones:

  radio           - creates a set of radio buttons based off Model::FIELD_NAMES
  checkbox        - creates a checkbox for true/false values.
  select          - creates a select list with options using Model::FIELD_NAMES

Example:
    rails generate refinery:form job_inquiry name:string message:text job_type:radio brochure:checkbox qualification:select

Should I try now or not?

Those features are really new. --i18n feature is not merged into master now. There are also some issues with generating engines into one namespace (db/seeds.rb). But I’ll try to fix them ASAP. I can recommend to experiment with those features for now. Mainly bug reports are welcome. Refinery 2 with all those features should be released before March.

Next?

I’m preparing article about using RefineryCMS with Twitter bootstrap. OK, I’m lying. I’m preparing one lowcost RefineryCMS site with Twitter bootstrap and I will probably release twitter-bootstrap engine for RefineryCMS. All you will need to do is adding it into your Gemfile. If you would like to read article about building whole site from scratch using RefineryCMS and Twitter bootstrap left me some comment here or tweet me. Also feel free to follow me on Twitter if you like my articles.

ZOMG! Refinery 2 now as Mountable Engine!

| Comments

Most widely used Rails CMS (according to ruby-toolbox) passed a big change. You can send your thanks to ugisozols and parndt. It is fully namespaced now and available as mountable engine, so you can easily attach it into your existing application.

You can try new Refinery from github master via rails template.

You can now mount refinery where you will need inside yours config/routes.rb.

1
2
3
Retrorubies::Application.routes.draw do
  mount Refinery::Core::Engine => '/awesome-refinery-path'
end

Refinery settings refactored hard!

Instead of old style settings saved in your refinery_settings database table Refinery now provides a couple of initializers. You can find them in config/initialiters/refinery. You can specify there settings like site languages or site name.

There are also two brand new features in core.rb initializer. You can now specify custom backend assets (javascript or stylesheet) in config/initializers/refinery/core.rb. This is my work and it is inspired by awesome Greg Bell’s Active Admin.

You can also specify html tags whitelist for included wysiwyg WYMeditor. This feature is result of parndt’s awesome work. So you definitely should nominate him to rubyhero for his great work.

1
2
3
4
5
6
7
8
9
10
Refinery::Core.configure do |config|
  # Add extra tags to the wymeditor whitelist e.g. = {'tag' => {'attributes': '1': 'href'}} or just {'tag' => {}}
  # config.wymeditor_whitelist_tags = {}

  # Register extra javascript for backend
  # config.register_javascript "prototype-rails"

  # Register extra stylesheet for backend (optional options)
  # config.register_stylesheet "custom", :media => 'screen'
end

Should I upgrade to use those cool features right now ?

If you are using some custom engines or overrided parts don’t do this. There is a lot of changes in namespacing and in conclusion there are not backwards compatible routes.

For adventurers: you can inspire by parndt’s rework of refinerycms-blog for latest refinery master branch. Isn’t it another good reason for rubyhero nomination ?