Tramway
Installation
Gemfile
gem 'tramway'
gem 'audited'
gem 'clipboard-rails'
gem 'bcrypt'
gem 'haml-rails'
gem 'bootstrap'
gem 'jquery-rails'
gem 'copyright_mafa'
gem 'trap'
gem 'kaminari'
gem 'bootstrap-kaminari-views', github: 'kalashnikovisme/bootstrap-kaminari-views', branch: :master
gem 'state_machine_buttons'
gem 'ckeditor', '4.2.4'
gem 'ransack'
gem 'smart_buttons'
gem 'carrierwave'
gem 'validates'
config/initializers/tramway.rb
# Initialize application with name
Tramway.initialize_application name: :your_application_name
# Initialize application name with model_class. Model class must be a singlethon
Tramway.initialize_application model_class: MyApplication
rails g tramway:install
config/initializers/assets.rb
Rails.application.config.assets.precompile += %w( *.jpg *.png *.js )
Every Tramway application need initialized @application object (or if you create Tramway plugin, it should be @application_engine object).
You don't need to initialize this object yourself, just configurate application with Tramway. You have 2 options of this:
Option 1. If you want to change @application object just in the code base.
rails g tramway:install
config/initializers/tramway.rb
Tramway::Core.initialize_application name: :your_application_name
Option 2. If you want to change @application object from admin panel. How to create model that will be an Application Model for the Tramway
1. Generate model that you to use. We create Organization, for example
rails g tramway:application
rails db:migrate
2. Add model_class to Initializer
Tramway::Core.initialize_application model_class: Organization
3. Create 1 instance of Organization model
rails c
Organization.create! public_name: 'Tramway', name: :organization, tagline: 'Tramway is not buggy, LOL!', main_image: 'https://raw.githubusercontent.com/ulmic/tramway-dev/develop/logo.png'
4. Add model to singleton to the tramway-admin
admin panel to be able to change its data
Tramway::Admin.set_singleton_models Organization, project: :organization # now you should use organization.name here
5. Then continue configuration of your model in admin panel with tramway-admin gem instruction, starting from point 8
6. Now you are able to change your application main info in admin panel
How-to
add favicon to your application
config/initializers/tramway.rb
::Tramway::Core.initialize_application attribute1: value, another_attribute: another_value, favicon: `/icon.ico` # icon should be in public folder
Usage
Tramway::Core::ApplicationRecord
uploader
Tramway use carrierwave for file uploading by default. To mount uploader you should use uploader
method
Interface: uploader(attribute_name, uploader_name, **options)
- attribute_name - ActiveRecord attribute to mount uploader
- uploader_name - short uploader name. You need to connect uploaders which are compatible with Tramway. Available uploaders:
- options - you are available to set options for uploaders exactly for this model. Available options:
- versions - only for :photo. Set needed versions for file to be cropped. If empty - 0 zero versions will be used. All versions you can see here
- extensions - whitelist of file extensions. If empty will be used default whitelist from the uploaders (links above)
Example:
class User < Tramway::Core::ApplicationRecord
uploader :avatar, :photo, version: [ :small, :medium ], extensions: [ :jpg, :jpeg ]
end
Tramway::Core::ApplicationDecorator
Associations
Your can decorate association models. Supporting all types of association
app/decorators/your_model_decorator.rb
class YourModelDecorator < Tramway::Core::ApplicationDecorator
decorate_association :some_model
decorate_association :another_model, decorator: SpecificDecoratorForThisCase
decorate_association :another_one_model, as: :repeat_here_as_parameter_from_model
decorate_association :something_else_model, state_machines: [ :here_array_of_state_machines_you_want_to_see_in_YourModel_show_page ] # support from tramway-admin gem
end
You can decorate a lot of models in one line
app/decorators/your_model_decorator.rb
class YourModelDecorator < Tramway::Core::ApplicationDecorator
decorate_associations :some_model, :another_model, :another_one_model, :something_else_model
end
Also, you can configurate what associations you want to see in YourModel page in admin panel support only for tramway-admin gem
app/decorators/your_model_decorator.rb
class YourModelDecorator < Tramway::Core::ApplicationDecorator
class << self
def show_associations
[ :some_model, :another_model, :another_one_model ]
end
end
end
Delegating attributes
app/decorators/your_model_decorator.rb
class YourModelDecorator < Tramway::Core::ApplicationDecorator
delegate_attributes :title, :something_else, :another_atttribute
end
Helper methods
date_view
Returns a date in the format depending on localization
app/decorators/*_decorator.rb
def created_at
date_view object.created_at
end
datetime_view
Returns a date and time in the format depending on localization
app/decorators/_decorator.rb*
def created_at
datetime_view object.created_at
end
state_machine_view
Returns the state of an object according to a state machine
app/decorators/_decorator.rb*
def state
state_machine_view object, :state
end
image_view
Returns an image in a particular format depending on the parameters of the original image file
app/decorators/*_decorator.rb
def avatar
image_view object.avatar
end
enumerize_view
Returns object enumerations as text
app/decorators/*_decorator.rb
def field_type
enumerize_view object.field_type
end
Other helpers
CopyToClipboardHelper
app/helpers/tramway/copy_to_clipboard_helper.rb
Install
include ::Tramway::Core::CopyToClipboardHelper
How to use it
It will show you in the view in bootstrap styles with font-awesome copy
icon.
Something like this:
copy_to_clipboard "some_id" # some_id is HTML id of element. Content of this element will be copied to the clipboard after pressing the button
In Russian
Базовые классы
- ApplicationDecorator - Базовый класс декоратора. В него по умолчанию включены
ActionView::Helpers
иActionView::Context
иFontAwesome5
(версия гема FontAwesome, которая поддерживает 5 версию шрифта).FontAwesome
считается вTramway
основным шрифтом для иконок. - ApplicationForm - наследованный от Reform::Form класс форм.
- ApplicationRecord - базовый класс для AR моделей
- ApplicationUploader - базовый класс для Carrierwave аплоадеров.
- FileUploader - базовый класс для загрузки файлов
- PhotoUploader - базовый класс для загрузки фотографий
- Вьюха
_messages
- предоставляет отображение ошибок в форме. Совместима с AR и Reform
Локализация
- dates - правила локализации даты
- helpers - часто используемые в формах слова
- models - часто используемые в моделях слова
- state_machines - локализация состояний
Contribution
Contributors
Run tests
make test
Deployment workflow
If you don't have access to push gem to rubygems then
Just create PR to develop branch
If you have access to push gem to rubygems then
- Create PR to develop branch
- After merging PR you should create new release via git-flow this way
git release start (version which you upgraded in lib/tramway/version.rb file)
git release finish (version which you upgraded in lib/tramway/version.rb file)
git push origin develop
git push origin master
- Then push new version of the gem
rm -rf *.gem && gem build $(basename "$PWD").gemspec && gem push *.gem
Tramway::Admin
Create admin panel for your application FAST!
Usage
How to use my plugin.
1. Add this gems to Gemfile
2. You should remove gem turbolinks
from your application and from app/assets/javascripts/application.js
3. Update your routes
config/routes.rb
Rails.application.routes.draw do
mount Tramway::Auth::Engine, at: '/auth'
mount Tramway::Admin::Engine, at: '/admin'
end
4. Then make tramway-core
installation. How-to
5. And then execute:
$ rails g tramway:user:install
$ rails db:migrate
6. Create your first admin user
$ rails c
$> Tramway::User::User.create! email: '[email protected]', password: '123456789', role: :admin
7. Add models to your admin
app/config/initializers/tramway.rb
# set available models for your admin
::Tramway::Admin.set_available_models YourModel, AnotherYourModel, project: #{project_name_which_you_used_in_application_name}
# set singleton models for your admin
::Tramway::Admin.set_singleton_models YourSingletonModel, AnotherYourSingletonModel, project: #{project_name_which_you_used_in_application_name}
::Tramway::Auth.root_path = '/admin' # you need it to redirect in the admin panel after admin signed_in
8. Configurate navbar
config/initializers/tramway.rb
Tramway::Admin.navbar_structure(
YourModel, # this line will create first-level link in your navbar, which will send you to the YourModel management
{
my_dropdown: [ # this line contains dropdown link name
AnotherYourModel # this line will create 2nd-level link in your navbar, which will send you to the YourModel management,
:divider # this line adds bootstrap divider to the dropdown list
]
},
project: :your_application_name
)
9. Create decorators and forms for all available_models.
You can run generator that will create all necessary files
$ rails g tramway:admin:install
Or generate decorator and form for only one model
$ rails g tramway:admin:model Coworking
If you're using several user roles in your admin dashboard, then you can specify scope for the form(default scope is admin
)
$ rails g tramway:admin:install --user-role=partner
Or you can create forms and decorators manually as it written below:
9a. Create decorator for models [manual option]
app/decorators/your_model_decorator.rb
class YourModelDecorator < Tramway::Core::ApplicationDecorator
decorate_associations :messages, :posts
class << self
def collections
[ :all, :scope1, :scope2 ]
end
def list_attributes
[ :begin_date, :end_date ]
end
def show_attributes
[ :begin_date, :end_date ]
end
def show_associations
[ :messages ]
end
def list_filters
{
filter_name: {
type: :select,
select_collection: filter_collection,
query: lambda do |list, value|
list.where some_attribute: value
end
},
date_filter_name: {
type: :dates,
query: lambda do |list, begin_date, end_date|
list.where 'created_at > ? AND created_at < ?', begin_date, end_date
end
}
}
end
end
delegate_attributes :title
end
NOTES:
collections
method must return array of scopes ofYourModel
. Every collection will be a tab in a list of your model in admin panellist_filters
method returns hash of filters where:- select_collection - collection which will be in the select of filter. It must be compatible with options_for_select method
- query - some Active Record query which be used as a filter of records
list_attributes
method returns array of attributes which will be shown in index page. If empty onlyname
will be shownshow_attributes
method returns array of attributes which will be shown in show page. If empty all attributes of the model will be shownshow_associations
method returns array of decorated associations which will be show in show page. If empty no associations will be shown
Filters naming:
Select filters
en:
tramway:
admin:
filters:
model_name:
filter_name: Your Filter
Date filters
en:
tramway:
admin:
filters:
model_name:
date_filter_name:
begin_date: Your Begin date filter
end_date Your end date filter
9b. Create Admin::YourModelForm
[manual option]
*app/forms/admin/your_model_form.rb
class Admin::YourModelForm < Tramway::Core::ApplicationForm
properties :title, :description, :text, :date, :logo
association :associated
association :another_polymorphic_associated
def initialize(object)
super(object).tap do
form_properties title: :string,
logo: :file,
description: :ckeditor,
date: :date_picker,
text: :text,
associated: :association,
another_polymorphic_association: :polymorphic_association,
birth_date: {
type: :default,
input_options: {
hint: 'It should be more than 18'
}
}
end
end
end
NOTE If you want fill inputs of this form, just send query params
params = {
your_model: {
logo: '/file/url',
description: 'some text',
text: 'some another text',
associated_id: 5,
another_polymorphic_associated: 56,
another_polymorphic_associated_type: 'AnotherModel'
}
}
10. Add inheritance to YourModel
app/models/your_model.rb
class YourModel < Tramway::Core::ApplicationRecord
end
11. You can add search to your index page
Tramway use gem PgSearch as search engine
Just add search
method to YourModel
like this
search_by *attributes, **associations # `attributes` and `associations` should be the same syntax as in PgSearch
Example:
class YourModel < Tramway::Core::ApplicationRecord
search_by :my_attribute, :another_attribute, my_association: [ :my_association_attribute, :another_my_association_attribute ]
12. Run server rails s
13. Launch localhost:3000/admin
CRUDs for models
By default users with role admin
have access to all models used as arguments in method ::Tramway::Admin.set_available_models
. If you want specify models by roles, use them as keys
::Tramway::Admin.set_available_models ::Tramway::Event::Event, ::Tramway::Event::ParticipantFormField,
::Tramway::Event::Participant, ::Tramway::Landing::Block, ::Tramway::User::User,
::Tramway::Profiles::SocialNetwork, project: #{project_name_which_you_used_in_application_name}, role: :admin
::Tramway::Admin.set_available_models ::Tramway::Event::Event, ::Tramway::Event::ParticipantFormField,
::Tramway::Event::Participant, project: #{project_name_which_you_used_in_application_name}, role: :another_role
You can set functions which are available by default some CRUD functions for any role:
# this line gives access only index page to YourModel for partner role
::Tramway::Admin.set_available_models YourModel => [ :index ], role: :partner
You can set conditions for functions which are available for any role:
# this line gives access to destroy only record with name `Elon Musk`
::Tramway::Admin.set_available_models YourModel => [
destroy => lambda do |record|
record.name == 'Elon Musk'
end
], role: :partner
Here docs about changing roles of Tramway::User::User
model Readme
Associations management
has_many
We have models Game and Packs.
app/models/game.rb
class Game < Tramway::Core::ApplicationRecord
has_many :packs
end
app/models/pack.rb
class Pack < Tramway::Core::ApplicationRecord
belongs_to :game
end
You want to manage packs in the Game show admin page
1. Add association to PackDecorator
app/decorators/pack_decorator.rb
class GameDecorator < Tramway::Core::ApplicationDecorator
decorate_association :packs, as: :game # we recommend you to add association name in Pack model. You need it if association name of Game in Pack is not `game`
end
has_and_belongs_to_many
We have models Game and Packs.
app/models/game.rb
class Game < Tramway::Core::ApplicationRecord
has_and_belongs_to_many :packs
end
app/models/pack.rb
class Pack < Tramway::Core::ApplicationRecord
has_and_belongs_to_many :games
end
You want to manage games in the Pack show admin page
1. Add association to PackDecorator
app/decorators/pack_decorator.rb
class PackDecorator < Tramway::Core::ApplicationDecorator
decorate_association :games
end
2. Create Admin::Packs::AddGameForm
and Admin::Packs::RemoveGameForm
app/forms/admin/packs/add_game_form.rb
class Admin::Packs::AddGameForm < Tramway::Core::ApplicationForm
properties :game_ids
association :games
def initialize(object)
super(object).tap do
form_properties games: :association
end
end
def submit(params)
params[:game_ids].each do |id|
model.games << Game.find(id) if id.present?
end
model.save!
end
end
app/forms/admin/packs/remove_game_form.rb
class Admin::Packs::RemoveGameForm < Tramway::Core::ApplicationForm
properties :id
def submit(params)
model.games -= [Game.find(params)] if id.present?
model.save!
end
end
3. Add this forms to initializer
config/initializers/tramway/admin/forms.rb
Tramway::Admin.forms = 'packs/add_game', 'packs/remove_game'
Date Picker locale
DatePicker provides ru
, en
locales. To set needed locale, just add
window.current_locale = window.i18n_locale('en');
to the app/assets/javascripts/admin/application.js
file
OR
window.current_locale = window.i18n_locale 'en'
to the app/assets/javascripts/admin/application.js.coffee
file
Decorator Helper methods
date_view
Returns a date in the format depending on localization
app/decorators/*_decorator.rb
def created_at
date_view object.created_at
end
datetime_view
Returns a date and time in the format depending on localization
app/decorators/_decorator.rb*
def created_at
datetime_view object.created_at
end
state_machine_view
Returns the state of an object according to a state machine
app/decorators/_decorator.rb*
def state
state_machine_view object, :state
end
It takes locales from I18n.t("state_machines.#{model_name}.#{state_machine_name}.states.#{state_value}")
image_view
Returns an image in a particular format depending on the parameters of the original image file
app/decorators/*_decorator.rb
def avatar
image_view object.avatar
end
enumerize_view
Returns object enumerations as text
app/decorators/*_decorator.rb
def field_type
enumerize_view object.field_type
end
file_view
Returns file name and button to download it
app/decorators/*_decorator.rb
def file_download
file_view object.file
end
Notifications
You can add notification to your admin panel to the navbar.
To add notification to application, you need just set queries in initializers.
config/initializers/tramway.rb
::Tramway::Admin.set_notificable_queries :"#{your_title}" => -> { your_query }
# Example from tramway-event gem (you also can push context variables here)
::Tramway::Admin.set_notificable_queries new_participants: -> (current_user) do
::Tramway::Event::Participant.where(participation_state: :requested).send "#{current_user}_scope", current_user.id
end
NOTE: Proc with current_user
argument is expecting. If you don't need current_user
, just name do something like that:
::Tramway::Admin.set_notificable_queries new_participants: -> (_current_user) do
# some code which does not need current_user
end
Admin Main Page management
Start page of admin panel contains only application.name
by default. To manage it just set Tramway::Admin.welcome_page_actions
with some lambda and set @content
variable with HTML.
Example:
config/initializers/tramway/admin.rb
::Tramway::Admin.welcome_page_actions = lambda do
@content = '<a href="http://it-way.pro">IT Way</a>'
end
Navbar management
Navbar structure
You can manage your navbar easy
config/initializers/tramway.rb
Tramway::Admin.navbar_structure(
YourModel, # this line will create first-level link in your navbar, which will send you to the YourModel management
{
my_dropdown: [ # this line contains dropdown link name
AnotherYourModel # this line will create 2nd-level link in your navbar, which will send you to the YourModel management,
:divider # this line adds bootstrap divider to the dropdown list
]
},
project: :your_application_name
)
NOTE: navbar structure is the same for all roles, but users will see only available models for them
Dropdown localization
To set human-read name for dropdown link you can use i18n:
config/locales/admin.yml
en:
admin:
navbar:
links:
my_dropdown: Very important dropdown
Additional buttons to the show view
You can additional buttons to the header of show view of your model. Just add its configuration to the decorator
app/decorators/your_model_decorator.rb
class YourModelDecorator < Tramway::Core::ApplicationDecorator
def
{
show: [ # means that this buttons will be shown on show view only
{
url: ::Tramway::Export::Engine.routes.url_helpers.export_path(object.id, model: object.class, collection: :tasks),
inner: lambda do # inner HTML you want to see in the button
fa_icon 'file-excel'
end,
color: :success, # bootstrap button color
method: :get # HTTP method. get method is a default. Available: :post, :patch: delete
}
]
}
end
end
Errors
- Model or Form is not available -
params[:model]
orparams[:form]
is empty OR current user does not have access to model or form inparams[:model]
orparams[:form]
Change admin user base model
config/initializers/tramway.rb
::Tramway::Admin.auth_config = { user_model: User, auth_attributes: %i[email username] }
Good features
Get actions log in admin panel
Tramway uses audited to log actions of models. That's why all we need it's creating view for model Audited::Audit
1. Add Audited::Audit model to available models
config/initializers/tramway.rb
Tramway::Admin.set_available_models(
Audited::Audit,
project: :your_project_name
)
2. Add this model to navbar
Tramway::Admin.(
Audited::Audit,
project: :your_project_name
)
3. Generate decorator for Audited::Audit
rails g tramway:admin:model Audited::Audit
Development
Tests
make test
Rubocop
make rubocop
License
The gem is available as open source under the terms of the MIT License.