Group of paper airplanes, orange one is the first place, can be used leadership/individuality concepts. ( 3d render )
Confusingly, bundler can have more than one version of Rails installed at once. if you had many versions, when you ran rails new, it probably used the default one, which could have been a very old one for you. This often confuses new developers, and especially if you installed Rails years ago and then come back to pick it up again.
To see which versions of Rails you have installed in bundler, use
gem list |grep rails
(here you are grepping, or searching against, the output for the string “rails”; without grep you would see all of your gems)
You’ll see some other gems with the name “rails” in them too, fortunately, all the rails gems are numbered concurrently.
TO install a different version of Rails in your bundler (remember, this just installs the gem code in your bundler’s system ready for use)
gem install rails -v 5.2.4.3
Finally, if you want to force rails new to use a specific version, use underscores before the “new” (that is, between “rails” and “new”)
Common Core JS am pleased to announce a rapid application development tool for Rails: It’s called “Common Core JS.”
The source code is on Github. When you install it, the gem is pulled from RubyGems.
The finished result of the example app we will build today can be seen here. (I recommend you type out each step and only refer to this if you need to.)
It’s based on the idea that you will embrace a common naming convention for your Rails app, will use AJAX rendered-everything (that means all the forms are remote: true), and want a common set of tools for rolling out a quick, dashboard-like app in Rails.
It comes with poor-man’s authentication built-in. Poor man’s auth is safe and works fine, but it isn’t designed for you to grow your entire app on and you should graduate out of if you have any granularity to your access control.
Common Core is a fantastic tool for rapidly building prototypes. It can also be used to create API back-ends for Javascript-heavy apps.
It is a blunt instrument and you should wield it carefully. In particular, you’ll want to remove specific code that it creates because it can create situations where users may have the access they shouldn’t.
Quick Setup
Let’s build the fastest app you can possibly build in Rails.
I’ll call it MyGreatApp, but yours can be named anything of coruse.
rails new MyGreatApp
Once you have the app generated (and even on faster processors Rails new still takes a hot minute or two), go to modify the Gemfile
Add the Gem
gem 'common_core_js'
To your Gemfile.
Then run: bundle install
Setup The Common Core
Then run the Common core install generator (which is implemented as a generator, not a rake task)
bundle exec rails generate common_core:install
Now you’ll create a User objeect, with a migration and model.
do this using. Note that you should not add any fields that will conflict with Devise fields, like email (I’ll add those in the next step).
bundle exec rails generate model User name:string joined_date:date timezone:integer
Add Devise
Add devise to your Gemfile
gem 'devise'
run bundle install, then install devise on the User model:
rails generate devise:install
rails generate devise User
Take a look at the fields on your User database table now. (Here I’m using DB Browser for SQLite)
Notice the fields added name, joined_date, and timezone I’ve put a red box around and the devise fields, including email and encrypted_password, I’ve put a blue box around.
Now you have the most bare-bones Rails app with Devise gem installed. This is great because you get free sign up, login and forgot password fundionality immediately.
Go to
http://127.0.0.1:3000/users/sign_up
Add jQuery
Add jQuery to your package.json via yarn
yarn add jquery
Go to config/webpack/environment.js and add this code in between the existing two lines
Now go ahead and start your rails server with bundle exec rails server
Go to /users/sign_up and create a new user account (be sure to enter the same password twice)
You will then be redirected to the Home page, which is now the Ruby on Rails “Yay you’re on Rails.” That’s fine— go ahead and customize your root URL.
Today’s Example App
I’ll make a super-simple system today where Users have many Events An Event belongs to a Format, which in our fictional world is only two choices: Zoom or Outdoor.
Events have a name, a starting datetime, and an ending datetime, and a “publicize” date on which should be before the starting time.
The two datetime fields (starting_at and ending_at) and the date field (publicize_on) can be empty (nil), but if set they are enforced to be: starting_at must be before ending_at. publicize_on must be before starting_at.
An Event will belong_to a Format (class & table). Formats will have a name field and only two records: Zoom and Outdoor. (We can assume they will be id 1 and id 2 in the formats table.)
All Events must belong_to a format, and when we create or edit an Event we can switch its format, but the format cannot be blank (null).
We already have the User object, and we also already have all the login, logout forgot password, and more provided by Devise.
We want the users to log-in and go to a dashboard of their own events.
They should be able to create, edit, & delete their own events with only the validations discussed above.
They should not be able to edit or create events belonging to other users, even by hacking the query parameters.
Finally, the user should be able to edit their own name and timezone, but not any other user’s name or timezone.
Because we want to name our routes from the perspective of the context-interaction, we’ll namespace the controller to Dashboard:: in our Ruby code and /dashboard in the URL. The controller will be at controllers/dashboard and the views will be at views/dashboard
Make the models
Since you already made the User model in the devise setup, let’s go ahead and create the Events and Formats tables.
Then open up the migration file and ed the description line, adding a larger than 256 limit, like 400
Next run bundle exec rake db:migrate to create the table.
Before I go further, let’s edit our models just a bit.
Open models/user.rb and add has_many :events
also add validates_presence_of :name
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :events
validates_presence_of :name
end
Likewise, on the Event object, defined models/event.rb, you’ll need to add the reflexive relationship for belongs_to :user and belongs_to :format
class Event < ApplicationRecord
belongs_to :user
belongs_to :format
end
Now make a formats table
bundle exec rails generate model Format name:string
class CreateFormats < ActiveRecord::Migration[6.0]
def change
create_table :formats do |t|
t.string :name
t.timestamps
end
Format.create(name: "Outdoor")
Format.create(name: "Zoom")
end
end
Then run the migration itself, which will now make the table & the two format records.
In order to show dates, we use a localized date display: the date & time is always shown to the user in their own date. To do this you have a few choices: (1) You can save the timezone to the user’s table, and let them set it for themselves, (2) You can show everybody the server’s date
Option #1 – Store timezone On the User object
We already took care of this by adding timezone to our User object.
Option #2 – Use the Server’s Timezone
If the auth object (current_user) does not respond to timezone, the Rails “system clock” will be used. The system clock’s timezone as set by the Rails app is used. This is often the timezone of the headquarter’s of the company that owns the application. (That is, if you do not know the user’s context, you simply use your own company’s context instead.)
Make the Controller, Views & Specs
Next we’re going to do the thing. We’ll make two controllers: Dashboard::EventsController for editing events and Dashboard::UsersController for the user editing their own name.
When passing the model name, pass it in the singular form
Here I’ve provided the namespace= with a value of dashboard. You will this is important to how our code comes out.
Here is the heart & soul of the common core: 5 .js.erb files, 5 .haml files, a controller, and a controller spec. Also along for the ride came controllers/dashboard/base_controller.rb as well as views/dashboard/_errors.haml, and layouts/_flash_notices.haml
Take a peak through all the generated code now.
Pay particular attention to _line.haml and _form.haml. You will note _form.haml conveniently is used for both the new/create actions and also for the update action, unifying the layout of your record across CRUD.
You can use both to customize your app quickly and easily.
One more quick step, add this to your routes.rbfile.
Make sure to nest the :events route within the :dashboard namespace, as shown here. If you aren’t familiar with namespacing in Rails, check out this blog post on my other blog, The Rails Coach.
Rails.application.routes.draw do
devise_for :users
namespace :dashboard do
resources :events
end
end
Start your server with
bundle exec rails server
If the Common Core finds null for timezone on your User object, it will default to either (1) whatever is set for your Rails app in either application.rb or an environment file, or, if don’t have this set (2) the clock timezone of the server that is running your Ruby application.
It’s generally a good idea to set your Rails app timezone to the same timezone of your company’s headquarters, and then don’t change it, because that way if your server happens to move from one timezone to another (for example, you migrate from a server on the East coast to the West coast), your app will be unaffected. If your company changes timezones, you can either leave the Rails app as-is or change it, but be sure to note any place where your default timezone comes through.
config.time_zone = 'Eastern Time (US & Canada)'
Done!
We can now do all of these fancy thigns.
Create an event. Leave name or format blank, get an error.
When you create a new event, you must give it a name and Format. Notice how if you don’t, the Rails-side logic will return the form shown with the erroneous fields marked in red.
Edit an Event
Your model-level validations — name and format as required — are enforced in the update action as well.
Deleting An Event
Adding Validation
Add this to your Event class in app/models/event.rb
validate :start_at_before_end_at, if: -> {!start_at.nil? && !end_at.nil?}
def start_at_before_end_at
if end_at < start_at
errors.add(:start_at, "can't be after end at")
errors.add(:end_at, "can't be before start at")
end
end
*Validation magic*
Finally, to add validation on all the date fields, here’s our completed Event model
class Event < ApplicationRecord
belongs_to :user
belongs_to :format
validates_presence_of :name
validate :start_at_before_end_at, if: -> {!start_at.nil? && !end_at.nil?}
validate :promote_on_before_start_at, if: -> {!promote_on.nil? && !start_at.nil?}
def start_at_before_end_at
if end_at < start_at
errors.add(:start_at, "can't be after end at")
errors.add(:end_at, "can't be before start at")
end
end
def promote_on_before_start_at
if start_at < promote_on
errors.add(:promote_on, "can't be after start at")
end
end
end
Account Dashboard
Next we’re going to create the very simplest of Account Dashboards. Remember that Devise already handles log in, log out, and forgot password, meaning most of the heavy lifting of user authentication has been taken care of.
In this simple app, we want an Account dashboard that let’s us edit only two fields: name and timezone.
First let’s add the route to routes.rb
Rails.application.routes.draw do
devise_for :users
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
namespace :dashboard do
resources :events
resources :users
end
end
Next let’s generate some scaffold
rails generate common_core:scaffold User namespace=dashboard
We now instantaly have a very basic dashboard for the User to edit their own details
The final finishing touch here will be to make the Timezone into a drop-down.
Remember, make your models first: Add limits and defaults to your database fields by modifying your migrations. Then add the relasionships between the tables using standard ActiveRercord has_many, belongs_to, and has_one.
Then build the common core scaffolding & customize the views and controllers it produces.
With these powerful tools, you can build a dashboard-like app in minutes, complete with simple interface buttons that let your users accomplish most of what they’ll need. The philosophy is that you will want this dashboard as you initially introduce people to your product. The main logic of your application will likely live more in the models, service objects, and domain layer (business logic) parts of your Rails app. For this reason, you are encouraged to customize the files only lightly. (Add some verbiage or change the CSS to customize the look & feel.)
The code you build with common core is cheap and disposable. It is not very modern, but it gets the job done. It is just “good enough” to launch a sophisticated app on, but it isn’t good enough to impress your users with a really good UI.
For that, you’ll want to throw away the front-end code and replace it with a modern JS UI like React, Vue, Ember, or Angular.
By that time, the Common core will have already helped you build (1) a prototype, (2) your business logic, and (3) possibly even some controllers you can re-use (for example, remove the format.js responses and replace them with format.json to change the controllers into a JSON-responding API controller.)
This website uses cookies to improve your experience while you navigate through the website. Out of these cookies, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may have an effect on your browsing experience.
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.
Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.