Effective Developer
This gem contains some developer quality of life scripts and rails helpers.
Getting Started
To use the included rails helpers and rake tasks in your current rails project, add to the Gemfile:
group :development
gem 'effective_developer'
end
Run the bundle command to install it:
bundle install
To use the included command line shell scripts in any directory, clone this repo:
git clone git@github.com:code-and-effect/effective_developer.git
and add the following to your PATH
(edit your ~/.bashrc or ~/.profile):
export PATH="$PATH:$HOME/effective_developer/bin"
To use the included git hooks for all git repos, run the following:
git config --global core.hooksPath ~/effective_developer/githooks
Shell scripts
To use the included command line shell scripts:
export PATH="$PATH:$HOME/effective_developer/bin"
gem_develop
A command line shell script to update a Gemfile
and use any provided gems locally.
This makes it very quick to swich to developing a gem locally.
gem_develop
should be run from the root directory of any rails app.
> gem_develop effective_datatables effective_resources
to change:
gem 'effective_datatables'
gem 'effective_resources'
into:
gem 'effective_datatables', path: '~/Sites/effective_datatables'
gem 'effective_resources', path: '~/Sites/effective_resources'
and execute bundle
.
You can override the ~/Sites/
directory by setting ENV['GEM_DEVELOP_PATH']
.
gem_release
A command line shell script that quickly bumps the version of any ruby gem.
It checks for any uncommitted files, updates the gem's version.rb
with the given version, makes a single file git commit
with a tag and message, then runs git push origin master
, gem build
and gem push
to rubygems.
gem_release
should be run from the root directory of any ruby gem.
To print the current gem version:
> gem_release
To release a new gem version:
> gem_release 1.0.0
gem_reset
A command line shell script to update a Gemfile
to find any locally developed gems, and update them to the most current released version.
gem_reset
should be run from the root directory of any rails app.
Just run with no arguments:
> gem_reset
to change:
gem 'effective_datatables', path: '~/Sites/effective_datatables'
gem 'effective_resources', path: '~/Sites/effective_resources'
into:
gem 'effective_datatables'
gem 'effective_resources'
and execute bundle update effective_datatables effective_resources
.
gitreset
Careful, this command will delete all your un committed changes.
A command line script to call git reset --hard
and also delete any newly created files.
It truly resets you back to a fresh working copy. Perfect for tweaking scaffold and code generation tools.
> gitreset
gitsweep
A command line script to delete any git branch that has already been merged into master & develop
> gitsweep
killpuma
kill -9
the first running puma process. Bails out of SystemStackError (stack level too deep).
> killpuma
Git hooks
To use the included git hooks for all git repos, run the following:
git config --global core.hooksPath ~/effective_developer/githooks
pre-push
Prevents pushing git commits that have the following bad patterns:
- Gemfile includes 'path: ' gems
- binding.pry
Rake scripts
csv:export
Exports all database tables to individual .csv files.
rake export:csv
csv:import::foos
Where table is the name of a model. Dynamically created rake task when a /lib/csv_importers/foos.rb
file is present.
rake csv:import:foos
csv:import::scaffold
Scaffolds an Effective::CsvImporter
file for each .csv file in /lib/csv_importers/data/*.csv
rake csv:scaffold
or
rake csv:scaffold[users]
rename_class
Quickly rename a rails class throughout the entire app.
The script considers the .classify
, .pluralize
and .singularize
common usage patterns.
Then performs a global search and replace, and renames files and directories.
rake rename_class[account,team]
or
rake rename_class[account,team,skipdb]
to skip any changes to database migrations.
reset_pk_sequence
If you ever run into the error duplicate key violates unique constraint (id) error
, run this script:
rake reset_pk_sequence
This makes sure that the autoincremented (postgresql) Pk sequence matches the correct id
value.
pg:pull
Creates a new backup on heroku, downloads that backup to latest.dump, and then calls pg:load
rake pg:pull
rake pg:pull[staging]
By default, any data in the logs
table will be excluded. To include the logs data:
rake pg:pull logs=true
pg:load
Drops and re-creates the local database then initializes database with the contents of latest.dump
rake pg:load
rake pg:load[something.dump]
pg:save
Saves the development database to a postgresql .dump file (latest.dump by default)
rake pg:save
rake pg:save[something.dump]
pg:clone
Clones the production (--remote heroku by default) database to staging (--remote staging by default)
rake pg:clone
rake pg:clone[origin,staging]
validate
Loads every ActiveRecord object and calls .valid?
on it.
rake validate
rake validate[post]
Rails Helpers
CSV Importer
Extend a class from Effective::CsvImporter
to quickly build a csv importer.
Put your importer in lib/csv_importers/users_importer.rb
and the data in lib/csv_importers/data/users.csv
. Both filenames should be pluralized.
A rake command will be dynamically created rake import:users
.
Required Methods
The importer requires two instance methods be defined:
-
def columns
a hash of names to columns. The constantsA
== 0,B
== 1, uptoAT
== 45 are defined to work better with spreadsheets. -
def process_row
will be run for each row of data. Any exceptions will be caught and logged as errors.
Inside the script, there are a few helpful functions:
-
col(:email)
will return the normalized value in that column. -
last_row_col(:email)
will return the normalized value for this column in the previous row. -
raw_col(:email)
will return the raw value in that column
module CsvImporters
class UsersImporter < Effective::CsvImporter
def columns
{
email: A,
first_name: B,
last_name: C,
admin?: D
}
end
def process_row
User.new(email: col(:email), first_name: col(:first_name), last_name: col(:last_name), admin: col(:admin?)).save!
end
end
end
When using col()
or last_row_col()
helpers, the value is normalized.
- Any column that ends with a
?
will be converted into a boolean. - Any column that ends with
_at
will be converted into a DateTime. - Any column that ends with
_on
will be converted into a Date. - Override
def normalize
to add your own.
def normalize(column, value)
if column == :first_name
value.upcase
else
super
end
end
Override before_import()
or after_import()
to run code before or after the import.
Code Generation
The goal of the effective_developer
code generation project is to minimize the amount of hand coding required to build a rails website.
Only the rails model file should be written by a human.
All database migrations, controllers, forms and views should be generated.
Creating a new working in-place CRUD feature should be a 1-liner.
A huge head start to the interesting part of the code.
effective scaffolds
Scaffolding is the fastest way to build a CRUD rails app.
The effective scaffolds generally follow the same pattern as the rails generate commands.
To create an entire CRUD resource from the command line:
rails generate effective:scaffold thing name:string description:text
rails generate effective:scaffold thing name:string description:text --actions index show mark_as_paid
rails generate effective:scaffold admin/thing name:string description:text
rails generate effective:scaffold admin/thing name:string description:text --actions crud-show
Or to skip the model & migration:
rails generate effective:scaffold_controller thing
rails generate effective:scaffold_controller thing index show
rails generate effective:scaffold_controller thing index show --attributes name description
rails generate effective:scaffold_controller admin/thing crud mark_as_paid
rails generate effective:scaffold_controller admin/thing crud-show
model file
If there is a regular rails model file present, all attributes, belong_tos, scopes and has_many accepts_nested_attributes will be considered when generating the scaffold.
Make a model file like this (or generate it with rails generate effective:model post name:string body:text
and tweak from there):
class Post < ApplicationRecord
belongs_to :user
belongs_to :category
# Attributes
effective_resources do
title :string
body :text
published_at :datetime
end
validates :title, presence: true
validates :description, presence: true
has_many :comments
accepts_nested_attributes_for :comments
scope :published, -> { where.not(published_at: nil) }
def to_s
title || 'New Post'
end
end
and then run
rails generate effective:scaffold post
rails generate effective:scaffold_controller admin/post
Tweak from here
all scaffolds
You can call scaffolds one at a time:
# These two accept attributes on the command line. like effective:scaffold
rails generate effective:model thing name:string description:text
rails generate effective:migration thing name:string description:text
# Thes accept actions on the command line. Pass --attributes as an option. like effective:scaffold_controller
rails generate effective:controller thing # /admin/thing
rails generate effective:route thing
rails generate effective:ability thing # CanCanCan
rails generate effective:menu thing # If app/views/*namespaces/_navbar.html.haml is present
rails generate effective:datatable thing
rails generate effective:views thing
rails generate effective:form thing
Replace SQL Example
You can do this:
Region.update_all("snippets = REPLACE(snippets, 'ActionController::Parameters', 'ActiveSupport::HashWithIndifferentAccess')")
Content Replacer
To find & replace content in the action_text_rich_texts body column:
Effective::ContentReplacer.new.count("foo")
and
Effective::ContentReplacer.new.replace!("foo", "bar")
License
MIT License. Copyright Code and Effect Inc.
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Bonus points for test coverage
- Create new Pull Request