For a full diff of necessary changes, please see LuckyDiff.
- Upgrade Lucky CLI (homebrew)
brew update
brew upgrade lucky
- Upgrade Lucky CLI (Linux)
Remove the existing Lucky binary and follow the Linux instructions in this section https://luckyframework.org/guides/getting-started/installing#on-linux
-
Update versions in
shard.yml
- Crystal should be
0.35.0
- Lucky should be
~> 0.23.0
- Authentic should be
~> 0.6.1
- LuckyFlow should be
~> 0.7.0
- jwt should be
~> 1.4.2
- Crystal should be
-
Run
shards update
- Update:
params.get
now strips white space. If you need the raw value, useparams.get_raw
. - Rename:
mount
tom
in all pages that use components. Note: This was reverted in the next version - Update: all mounted components to use new signature
mount(MyComponent.new(x: 1, y: 2))
->m(MyComponent, x: 1, y:2)
. - Remove:
Lucky::SessionHandler
andLucky::FlashHandler
fromsrc/app_server.cr
- Add:
Avram::RecordNotFoundError
to thedont_report
array insrc/actions/errors/show.cr
- Update:
def render(error : Lucky::RouteNotFoundError
todef render(error : Lucky::RouteNotFoundError | Avram::RecordNotFoundError)
insrc/actions/errors/show.cr
. - Update: any CLI tasks that use
ARGV
to use the native args See implementation
For a full diff of necessary changes, please see LuckyDiff.
- Upgrade Lucky CLI (homebrew)
brew update
brew upgrade lucky
- Upgrade Lucky CLI (Linux)
Remove the existing Lucky binary and follow the Linux instructions in this section https://luckyframework.org/guides/getting-started/installing#on-linux
-
Update versions in
shard.yml
- Crystal should be
0.35.0
- Lucky should be
~> 0.22.0
- Authentic should be
~> 0.6.0
- jwt should be
~> 1.4.2
- Crystal should be
-
Run
shards update
For a full diff of necessary changes, please see LuckyDiff.
- Upgrade Lucky CLI (homebrew)
brew update
brew upgrade lucky
- Upgrade Lucky CLI (Linux)
Remove the existing Lucky binary and follow the Linux instructions in this section https://luckyframework.org/guides/getting-started/installing#on-linux
-
Update versions in
shard.yml
- Crystal should be
0.34.0
- Lucky should be
~> 0.21.0
- Authentic should be
~> 0.5.4
- LuckyFlow should be
~> 0.6.3
- Crystal should be
-
Run
shards update
- Rename:
config/logger.cr
toconfig/log.cr
- Update:
config/log.cr
to use the newLog
. See implementation - Update:
Procfile.dev
and update thesystem_check
toscript/system_check && sleep 100000
. - Update: all
Lucky.logger.{level}("message")
calls to use the new Crystal LogLog.{level} { "message" }
- Remove: the following lines from
config/database.cr
# Uncomment the next line to log all SQL queries
# settings.query_log_level = ::Logger::Severity::DEBUG
Before this version, you would log data like this:
Lucky.logger.debug("Logging some message")
Lucky.logger.info({path: @context.request.path})
Now, you would write this like:
# Use the Crystal std-lib log for simple String messages
Log.debug { "Logging some message" }
# Use the Dexter extension for logging key/value data
Log.dexter.info { {path: @context.request.path} }
For a full diff of necessary changes, please see LuckyDiff.
- Update
.crystal-version
file to0.34.0
- Upgrade to crystal 0.34.0
- Upgrade Lucky CLI (homebrew)
brew update
brew upgrade crystal-lang # Make sure you're up-to-date. Requires 0.34.0
brew upgrade lucky
- Upgrade Lucky CLI (Linux)
Remove the existing Lucky binary and follow the Linux instructions in this section https://luckyframework.org/guides/getting-started/installing#on-linux
- Update versions in
shard.yml
- Crystal should be
0.34.0
- Lucky should be
~> 0.20.0
- Authentic should be
~> 0.5.2
- LuckyFlow should be
~> 0.6.2
- Crystal should be
- Run
shards update
- Update:
link
no longer accepts aString
path or URL, it must be an Action. Changelink()
to ana
tag with anhref
(a "Google", href: "https://google.com"
), or use an action class withlink
(link "Home", to: "/"
becomeslink("Home", to: Home::Index)
. - Remove: the
?
from anyneeds
using a predicate method. e.g.needs signed_in? : Bool
->needs signed_in : Bool
. Lucky now automatically creates a method ending with?
forneeds
with aBool
type. - Update: your development
ENV["PORT"]
to beENV["DEV_PORT"]
if you need to customize the port your local server is running on. - Update: all
SaveOperation
classes where a raw hash is being passed in. e.g.MyOperation.new({"name" => "Gary"})
->MyOperation.new(name: "Gary")
, or if you must use a hash, wrap it in params first:MyOperation.new(Avram::Params.new({"name" => "Gary"})
- Remove: the
on:
option fromneeds
inside every Operation class. e.g.needs created_by : String, on: :create
->needs created_by : String
. You will need to explicitly pass these when callingnew
,create
, andupdate
.
- Update: all instance variables called from a
needs
on a page or component can now just use the method of that name. e.g.@current_user
->current_user
- Add:
include Lucky::CatchUnpermittedAttribute
to theclass Shared::Field(T)
insrc/components/shared/field.cr
. This will raise a nicer error if you forget to permit a column in your SaveOperation - Add: the new
Lucky::RemoteIpHandler.new
to your app handlers insrc/app_server.cr
just beforeLucky::RouteHandler.new
. - Add:
robots.txt
to yourpublic/
directory.User-agent: * Disallow:
- Update:
UserSerializer
to inherit from theBaseSerializer
if it doesn't already. - Add:
cookie.http_only(true)
to yourconfig/cookies.cr
file. This goes inside yoursettings.on_set
block. - Update: your node dependencies where needed
- Update: the
setup
script inscript/setup
. See implementation. Be sure to remove the ECR tags. - Add: this line
system_check: script/system_check && $SHELL
to yourProcfile.dev
- Add: the new
system_check
script inscript/system_check
. Note: you may need tochmod +x script/system_check
. See implementation. Be sure to remove the ECR tags. - Add: the new
function_helpers
script inscript/helpers/function_helpers
. See implementation - Add: the new
text_helpers
script inscript/helpers/text_helpers
. See implementation
For a full diff of necessary changes, please see LuckyDiff.
- Update
.crystal-version
file to0.33.0
- Upgrade to crystal 0.33.0
- Upgrade Lucky CLI (homebrew)
brew update
brew upgrade crystal-lang # Make sure you're up-to-date. Requires 0.33.0
brew upgrade lucky
- Upgrade Lucky CLI (Linux)
Remove the existing Lucky binary and follow the Linux instructions in this section https://luckyframework.org/guides/getting-started/installing#on-linux
- Update versions in
shard.yml
- Crystal should be
0.33.0
- Lucky should be
~> 0.19.0
- Authentic should be
~> 0.5.1
- LuckyFlow should be
~> 0.6.2
- Crystal should be
- Run
shards update
- Add the compression plugin to
package.json
- Make these changes
to your
webpack.mix.js
file - In
src/app_server.cr
addLucky::StaticCompressionHandler.new("./public", file_ext: "gz", content_encoding: "gzip")
above theLucky::StaticFileHandler.new
.
- Make these changes to
config/server.cr
to gzip text responses.
For a full diff of necessary changes, please see LuckyDiff.
- Upgrade to crystal 0.31.1
- Upgrade Lucky CLI (homebrew)
brew update
brew upgrade crystal-lang # Make sure you're up-to-date. Requires 0.31.1
brew upgrade lucky
- Upgrade Lucky CLI (Linux)
Remove the existing Lucky binary and follow the Linux instructions in this section https://luckyframework.org/guides/getting-started/installing#on-linux
-
Update
.crystal-version
to0.31.1
-
Update versions in
shard.yml
- Crystal should be
0.31.1
- Lucky should be
~> 0.18
- Authentic should be
~> 0.5.0
- LuckyFlow should be
~> 0.6.0
- Crystal should be
-
Run
shards update
-
Rename: all
render
calls in actions tohtml
. -
Update: the
src/actions/errors/show.cr
file to the new format:class Errors::Show < Lucky::ErrorAction DEFAULT_MESSAGE = "Something went wrong." default_format :html dont_report [Lucky::RouteNotFoundError] def render(error : Lucky::RouteNotFoundError) if html? error_html "Sorry, we couldn't find that page.", status: 404 else error_json "Not found", status: 404 end end # When the request is JSON and an InvalidOperationError is raised, show a # helpful error with the param that is invalid, and what was wrong with it. def render(error : Avram::InvalidOperationError) if html? error_html DEFAULT_MESSAGE, status: 500 else error_json \ message: error.renderable_message, details: error.renderable_details, param: error.invalid_attribute_name, status: 400 end end # Always keep this below other 'render' methods or it may override your # custom 'render' methods. def render(error : Lucky::RenderableError) if html? error_html DEFAULT_MESSAGE, status: error.renderable_status else error_json error.renderable_message, status: error.renderable_status end end # If none of the 'render' methods return a response for the raised Exception, # Lucky will use this method. def default_render(error : Exception) : Lucky::Response if html? error_html DEFAULT_MESSAGE, status: 500 else error_json DEFAULT_MESSAGE, status: 500 end end private def error_html(message : String, status : Int) context.response.status_code = status html Errors::ShowPage, message: message, status: status end private def error_json(message : String, status : Int, details = nil, param = nil) json ErrorSerializer.new(message: message, details: details, param: param), status: status end private def report(error : Exception) : Nil # Send to Rollbar, send an email, etc. end end
-
Rename:
title
tomessage
insrc/pages/errors/show_page.cr
. -
Add:
BaseSerializer
tosrc/serializers/
.abstract class BaseSerializer < Lucky::Serializer def self.for_collection(collection : Enumerable, *args, **named_args) collection.map do |object| new(object, *args, **named_args) end end end
-
Add:
require "./serializers/base_serializer"
to yoursrc/app.cr
aboverequire "./serializers/**"
-
Optional: Update all serializers to inherit from
BaseSerializer
. Also merge Show/Index serializers in to a single class.# Merge these two classes class Users::IndexSerializer < Lucky::Serializer end class Users::ShowSerializers < Lucky::Serializer end # in to this class class UserSerializer < BaseSerializer # Same contents as Users::ShowSerializer # Calls to Users::IndexSerializer now become: # # UserSerializer.for_collection(users) end
-
Rename:
Errors::ShowSerializer
toErrorSerializer
-
Update:
ErrorSerializer
to inherit from the newBaseSerializer
-
Update:
ErrorSerializer
contents with:class ErrorSerializer < BaseSerializer def initialize( @message : String, @details : String? = nil, @param : String? = nil # If there was a problem with a specific param ) end def render {message: @message, param: @param, details: @details} end end
-
Add:
Avram::SchemaEnforcer.ensure_correct_column_mappings!
tosrc/start_server.cr
belowAvram::Migrator::Runner.new.ensure_migrated!
. -
Update: any mention to renamed errors in this commit. You can likely ignore this as most people do not rescue these specific errors.
-
Add:
accepted_formats [:json]
toApiAction
insrc/actions/api_action.cr
.abstract class ApiAction < Lucky::Action accepted_formats [:json] end
-
Add:
accepted_formats [:html, :json], default: :html
toBrowserAction
insrc/actions/browser_action.cr
abstract class BrowserAction < Lucky::Action accepted_formats [:html, :json], default: :html end
-
Update:
src/app_server.cr
with explicit return type on themiddleware
method.
# Add return type here
def middleware : Array(HTTP::Handler)
[
# ...
] of HTTP::Handler # Add this or app will fail to compile
end
- Add:
include Lucky::RequestExpectations
tospec/spec_helper.cr
belowinclude Carbon::Expectations
- Add:
Avram::SchemaEnforcer.ensure_correct_column_mappings!
tospec/spec_helper.cr
belowAvram::Migrator::Runner.new.ensure_migrated!
- Update: Change
at_exit do
inspec/setup/start_app_server.cr
toSpec.after_suite do
- Ensure you've upgraded to crystal 0.30.1
- Upgrade Lucky CLI (homebrew)
brew update
brew upgrade crystal-lang # Make sure you're up-to-date. Requires 0.30.1
brew upgrade lucky
-
Upgrade Lucky CLI (Linux)
-
Update
.crystal-version
to0.30.1
Remove the existing Lucky binary and follow the Linux instructions in this section https://luckyframework.org/guides/getting-started/installing#on-linux
- Update versions in
shard.yml
- Lucky should be
~> 0.17
- Lucky should be
- Run
shards update
If you're not sure about an upgrade step, or simply want to look at an example, see the lucky_bits upgrade.
- Rename: Action rendering method
text
toplain_text
. - Update: use of
number_to_currency
now returns a String instead of writing to the view directly. - Delete:
config/static_file_handler.cr
. - Add: a new
Lucky::LogHandler
configure to the bottom ofconfig/logger.cr
. - Update:
Avram::Repo.configure
toAvram.configure
inconfig/logger.cr
.
config/logger.cr
require "file_utils"
logger =
if Lucky::Env.test?
# Logs to `tmp/test.log` so you can see what's happening without having
# a bunch of log output in your specs results.
FileUtils.mkdir_p("tmp")
Dexter::Logger.new(
io: File.new("tmp/test.log", mode: "w"),
level: Logger::Severity::DEBUG,
log_formatter: Lucky::PrettyLogFormatter
)
elsif Lucky::Env.production?
# This sets the log formatter to JSON so you can parse the logs with
# services like Logentries or Logstash.
#
# If you want logs like in development use `Lucky::PrettyLogFormatter`.
Dexter::Logger.new(
io: STDOUT,
level: Logger::Severity::INFO,
log_formatter: Dexter::Formatters::JsonLogFormatter
)
else
# For development, log everything to STDOUT with the pretty formatter.
Dexter::Logger.new(
io: STDOUT,
level: Logger::Severity::DEBUG,
log_formatter: Lucky::PrettyLogFormatter
)
end
Lucky.configure do |settings|
settings.logger = logger
end
Lucky::LogHandler.configure do |settings|
# Skip logging static assets in development
if Lucky::Env.development?
settings.skip_if = ->(context : HTTP::Server::Context) {
context.request.method.downcase == "get" &&
context.request.resource.starts_with?(/\/css\/|\/js\/|\/assets\//)
}
end
end
Avram.configure do |settings|
settings.logger = logger
end
- Update:
script/setup
to include the new postgres checks.
# This must go *after* the 'shards install' step
+ printf "\n▸ Checking that postgres is installed\n"
+ check_postgres | indent
+ printf "✔ Done\n" | indent
+ printf "\n▸ Verifying postgres connection\n"
+ lucky db.verify_connection | indent
printf "\n▸ Setting up the database\n"
lucky db.create | indent
- Add: a new
AppDatabase
class insrc/app_database.cr
that inherits fromAvram::Database
.
class AppDatabase < Avram::Database
end
- Add:
require "./app_database"
tosrc/app.cr
right below therequire "./shards"
. - Rename:
Avram::Repo.configure
toAppDatabase.configure
inconfig/database.cr
. - Add:
Avram.configure
block.
config/database.cr
database_name = "..."
AppDatabase.configure do |settings|
if Lucky::Env.production?
settings.url = ENV.fetch("DATABASE_URL")
else
settings.url = ENV["DATABASE_URL"]? || Avram::PostgresURL.build(
database: database_name,
hostname: ENV["DB_HOST"]? || "localhost",
# Some common usernames are "postgres", "root", or your system username (run 'whoami')
username: ENV["DB_USERNAME"]? || "postgres",
# Some Postgres installations require no password. Use "" if that is the case.
password: ENV["DB_PASSWORD"]? || "postgres"
)
end
end
Avram.configure do |settings|
settings.database_to_migrate = AppDatabase
# this is moved from your old `Avram::Repo.configure` block.
settings.lazy_load_enabled = Lucky::Env.production?
end
- Move: the
settings.lazy_load_enabled
fromAppDatabase.configure
toAvram.configure
block. - Add: a
database
class method tosrc/models/base_model.cr
that returnsAppDatabase
.
abstract class BaseModel < Avram::Model
def self.database : Avram::Database.class
AppDatabase
end
end
-
Update:
Avram::Repo
toAppDatabase
inspec/setup/clean_database.cr
. -
Avram no longer automatically adds a timestamp and primary key to migrations. Add a primary key and timestamps to your old migrations.
Also note that the syntax for a UUID has changed. You use
primary_key id : UUID
instead of an option on 'create'def migrate create :users do # Add these to your 'create' statements in your migrations primary_key id : Int64 # Or 'UUID' if using UUID add_timestamps end end
-
Note: Avram now defaults primary keys to
Int64
instead ofInt32
. You can use thechange_type
macro to migrate your primary keys and foreign keys toInt64
if you need. Runlucky gen.migration UpdatePrimaryKeyTypes
.
class UpdatePrimaryKeyTypesV20190723233131 < Avram::Migrator::Migration::V1
def migrate
alter table_for(User) do
change_type id : Int64
end
alter table_for(Post) do
change_type id : Int64
change_type user_id : Int64
end
end
end
- Update: models now default the primary key to
Int64
. This can be overridden if your tables uses a different column type for your primary keys, such as Int32 or UUID
abstract class BaseModel < Avram::Model
macro default_columns
primary_key id : UUID
timestamps
end
end
This also means that any model that uses UUID
for a primary key can remove the primary_key_type
option
class User < BaseModel
# 0.16 and earlier
table :users, primary_key_type: :uuid do
column email : String
end
# Now with 0.17 it will use the 'default_columns' from the 'BaseModel'
table :users do
column email : String
end
end
- Rename:
Query.new.destroy_all
toQuery.truncate
. (e.g.UserQuery.new.destroy_all
=>UserQuery.truncate
) - Rename: all association query methods from the association name to
where_{association_name}
. (e.g.UserQuery.new.posts
=>UserQuery.new.where_posts
) - Update: all association query methods no longer take a block. Pass the query in as an argument. (e.g.
UserQuery.new.posts { |post_query| }
=>UserQuery.new.where_posts(PostQuery.new)
) - Update:
where_{association_name}
methods no longer need to be preceded by ajoin_{assoc}
, unless you need a custom join (i.e.left_join_{assoc}
). If you use a custom join, you will need to add theauto_inner_join: false
option to yourwhere_{assoc}
method.
- Rename: the
src/forms
directory tosrc/operations
. - Update:
require "./forms/mixins/**"
andrequire "./forms/**"
torequire "./operations/mixins/**"
andrequire "./operations/**"
respectively insrc/app.cr
- Rename:
BaseForm
toSaveOperation
insrc/operations
. (e.g.User::BaseForm
=>User::SaveOperation
) - Rename:
fillable
topermit_columns
- Rename: form class names to new naming convention. (e.g.
class UserForm < User::SaveOperation
=>class SaveUser < User::SaveOperation
). This step is optional, but still recommended to avoid future confusion. - Rename:
Avram::VirtualForm
toAvram::Operation
. - Rename: virtual form class names to new naming convention VerbNoun. (e.g.
class SignInForm < Avram::Operation
=>class SignInUser < Avram::Operation
). - Rename:
virtual
toattribute
. - Update: all
SaveOperation
classes to callbefore_save prepare
. Theprepare
method is no longer called by default, which allows you to rename this method as well. - Update:
FillableField
toPermittedAttribute
insrc/components/shared/
. Checkfield.cr
andfield_errors.cr
. - Update: all authentic classes and modules to use new operation setup. This may require renaming some files to fit the
VerbNoun
verb_noun.cr
convention.
Files in src/operations/
# src/operations/mixins/password_validations.cr
module PasswordValidations
+ macro included
+ before_save run_password_validations
+ end
#...
end
# src/operations/request_password_reset.cr
- class RequestPasswordReset < Avram::VirtualForm
+ class RequestPasswordReset < Avram::Operation
#...
end
# src/operations/reset_password.cr
- def prepare
- run_password_validations
+ before do
Authentic.copy_and_encrypt password, to: encrypted_password
# src/operations/sign_in_user.cr
- class SignInUser < Avram::VirtualOperation
+ class SignInUser < Avram::Operation
# src/operations/sign_up_user.cr
- def prepare
+ before_save do
validate_uniqueness_of email
- run_password_validations
- Update
sign_in_user.cr
to match the new template. - Rename the
FindAuthenticatable
mixin toUserFromEmail
, again the Lucky CLI template is a helpful guide.
- Upgrade to crystal 0.30.0
No updates to Lucky itself are required. There may be Crystal 0.30.0 related changes you may need to make.
- Upgrade to crystal 0.29.0
- Upgrade Lucky CLI (macOS)
brew update
brew upgrade crystal-lang # Make sure you're up-to-date. Requires 0.29.0
brew upgrade lucky
-
Upgrade Lucky CLI (Linux)
-
Update
.crystal-version
to0.29.0
Remove the existing Lucky binary and follow the Linux instructions in this section https://luckyframework.org/guides/getting-started/installing#on-linux
-
Update versions in
shard.yml
- Lucky should be
~> 0.15
- Lucky should be
-
Run
shards update
-
Rename
src/server.cr
tosrc/start_server.cr
. -
Edit
src/start_server.cr
by changingapp
toapp_server
andApp
toAppServer
.- delete the line that starts with
puts "Listening on
-
Update
src/{your app name}.cr
to require./start_server
-
Rename
src/dependencies.cr
tosrc/shards.cr
-
Move the
App
class to a new file insrc/app_server.cr
-
Rename
App
toAppServer
and renameLucky::BaseApp
toLucky::BaseAppServer
in your newsrc/app_server.cr
-
Update
src/app.cr
to require new./app_server
file -
Update
src/app.cr
to require new./shards
file -
Replace usages of
Lucky::Action::Status::
with the respective crystalHTTP::Status::
- Upgrade to crystal 0.28.0
- Create new file
config/force_ssl_handler.cr
with the following content:
Lucky::ForceSSLHandler.configure do |settings|
settings.enabled = Lucky::Env.production?
end
- Upgrade Lucky CLI (macOS)
brew update
brew upgrade crystal-lang # Make sure you're up-to-date. Requires 0.27.2
brew upgrade lucky
-
Upgrade Lucky CLI (Linux)
-
Update
.crystal-version
to0.27.2
Remove the existing Lucky binary and follow the Linux instructions in this section https://luckyframework.org/guides/installing/#install-lucky
-
Update versions in
shard.yml
- Lucky should be
~> 0.13
- LuckyFlow should be
~> 0.4
- Authentic should be
~> 0.3
- Lucky should be
-
Run
shards update
-
Find and replace
LuckyRecord
withAvram
-
Add
Lucky::AssetHelpers.load_manifest
belowrequire "dependencies"
insrc/app.cr
for browser apps. Skip for API only apps. -
Query#preload
with a query now includes the association name ->Query#preload_{{ assoc_name }}
-
Remove
unexpose
andunexpose_if_exposed
from your actions. Pages now ignore unused exposures so these methods have been removed. -
Change
require "lucky_record"
torequire "avram"
insrc/dependencies
-
Rename
config/log_handler.cr
toconfig/logger.cr
-
Replace
config/logger.cr
with this:
require "file_utils"
logger =
if Lucky::Env.test?
# Logs to `tmp/test.log` so you can see what's happening without having
# a bunch of log output in your specs results.
FileUtils.mkdir_p("tmp")
Dexter::Logger.new(
io: File.new("tmp/test.log", mode: "w"),
level: Logger::Severity::DEBUG,
log_formatter: Lucky::PrettyLogFormatter
)
elsif Lucky::Env.production?
# This sets the log formatter to JSON so you can parse the logs with
# services like Logentries or Logstash.
#
# If you want logs like in development use `Lucky::PrettyLogFormatter`.
Dexter::Logger.new(
io: STDOUT,
level: Logger::Severity::INFO,
log_formatter: Dexter::Formatters::JsonLogFormatter
)
else
# For development, log everything to STDOUT with the pretty formatter.
Dexter::Logger.new(
io: STDOUT,
level: Logger::Severity::DEBUG,
log_formatter: Lucky::PrettyLogFormatter
)
end
Lucky.configure do |settings|
settings.logger = logger
end
Avram::Repo.configure do |settings|
settings.logger = logger
end
-
If using
is
in queries, rename the calls toeq
-
App in
src/app.cr
should now inherit fromLucky::BaseApp
. See the changes you need to make. -
Move
bin/setup
toscript/setup
-
In your
README
replacebin/setup
withscript/setup
-
Replace
bin/lucky
in your.gitignore
with just/bin/
. Lucky projects should now put bash scripts in/script
. Binaries go in/bin/
and are ignored. -
id
in actions usingroute
now have the underscored version of the resource name prepended. You'll need to rename yourid
calls to<resource_name>_id
.
# Example from v0.12
class Users::Show < BrowserAction
route do
# Using the 'id' param
UserQuery.find(id)
end
end
# Would now be
class Users::Show < BrowserAction
route do
# Now it is 'user_id'
UserQuery.find(user_id)
end
end
-
Make changes to laravel.mix
-
Make changes to package.json
-
Run
yarn install
And you should now be good to go!
- Upgrade Lucky CLI (macOS)
brew update
brew upgrade crystal-lang # Make sure you're up-to-date. Requires 0.27
brew upgrade lucky
- Upgrade Lucky CLI (Linux)
Remove the existing Lucky binary and follow the Linux instructions in this section https://luckyframework.org/guides/installing/#install-lucky
Use your package manager to update Crystal to v0.27
-
In
db/migrations
, changeLuckyMigrator::Migration
->LuckyRecord::Migrator::Migration
for every migration -
Remove
lucky_migrator
fromshard.yml
-
Remove
lucky_migrator
fromsrc/dependencies
-
Remove the
LuckyMigrator.configure
block fromconfig/database.cr
-
Configuration now requires passing an argument. Find and replace
.configure do
with.configure do |settings|
in all files inconfig
-
Update
config/session.cr
-
Change
Lucky::Session::Store.configure
toLucky::Session.configure do |settings|
-
Change your session key because signing/encryption has changed. For example: add
_0_12_0
to the end of the key. -
Remove
settings.secret = Lucky::Server.settings.secret_key_base
-
-
If using
cookies[]
anywhere in your app, change the key you use. Lucky now signs and encrypts all cookies. Old cookies will not decrypt properly. -
Change
session[]=
andcookies[]=
tosession|cookies.set|get
-
Change
session|cookies.destroy
tosession/cookies.clear
-
cookies.unset(:key)
anddelete.unset(:key)
should becookies|session.delete(:key)
-
Remove
unexpose current_user
fromsrc/actions/home/index.cr
-
Query#count
has been renamed toQuery#select_count
. For example:UserQuery.new.count
is nowUserQuery.new.select_count
-
Change
flash.danger
toflash.failure
in your actions. -
Update
Lucky::Flash::Handler
toLucky::FlashHandler
insrc/app.cr
-
Update usages of
Lucky::Response
toLucky::TextResponse
-
Update usages of
LuckyInflector::Inflector
toWordsmith::Inflector
-
Remove
config/session.cr
and copyconfig/cookies.cr
-
Replace
config/email.cr
with this one. -
Add this line to
spec_helper.cr
(around line 19) ->LuckyRecord::Migrator::Runner.new.ensure_migrated!
-
In
config/server.cr
, copy the new block starting atline 15
. -
Update shard versions in
shard.yml
:- Lucky
~> 0.12
- LuckyRecord
~> 0.7
- Authentic
~> 0.2
- LuckyFlow
~> 0.3
- Lucky
-
Change
.crystal-version
to0.27.0
-
Run
shards update
to install the new shards
- Upgrade Lucky CLI (macOS)
brew update
brew upgrade crystal-lang # Make sure you're up-to-date
brew upgrade lucky
- Upgrade Lucky CLI (Linux)
Remove the existing Lucky binary and follow the Linux instructions in this section https://luckyframework.org/guides/installing/#install-lucky
Use your package manager to update Crystal to v0.25
-
Update
.crystal-version
to0.25.0
-
Change
crystal deps
toshards install
inbin/setup
-
Update
lucky_flow
andlucky_migrator
inshard.yml
lucky_flow
should now be0.2
lucky_migrator
should now be0.6
-
Remove any cached shards: rm -rf ~/.cache/shards
This is to address a bug in shards: crystal-lang/shards#211
-
Run
shards update
-
Find all instances of
nested_action
and replace withnested_route
-
Find all instances of
action
and replace withroute
in your actionsTo make it easier to only change the right thing, search for
action do
and replace withroute do
. This will make it fairly easy to find and replace across your whole project. -
Move static assets from
static/assets
topublic/assets
-
Move
static/js
tosrc/js
-
Move
static/css
tosrc/css
-
Remove
/public
from.gitignore
-
Add these to
.gitignore
/public/mix-manifest.json
/public/js
/public/css
-
Update
src/app.cr
lines:- Remove host and port: https://github.com/luckyframework/lucky_cli/blob/ce677b8aefbbef2f06587d835795cbb59c5801dd/src/web_app_skeleton/src/app.cr.ecr#L25
- Add
bind_tcp
with host and port: https://github.com/luckyframework/lucky_cli/blob/ce677b8aefbbef2f06587d835795cbb59c5801dd/src/web_app_skeleton/src/app.cr.ecr#L50
-
Update webpack config to match this: https://github.com/luckyframework/lucky_cli/blob/ce677b8aefbbef2f06587d835795cbb59c5801dd/src/browser_app_skeleton/webpack.mix.js#L12-L37
-
Calls to the
asset
method no longer require prefixing/assets
. You may not be using this. The compiler will complain and help you find the right asset if you need to update this.
Note: Lucky skipped version 0.9 so that Lucky and Lucky CLI are on the same version.
- Upgrade Lucky CLI
On macOS:
brew update
brew upgrade crystal-lang # Make sure you're up-to-date
brew upgrade lucky
If you are on Linux, remove the existing Lucky binary and follow the Linux instructions in this section https://luckyframework.org/guides/installing/#install-lucky
- View the upgrade diff and make changes to your app
In previous upgrade guides (below) every change is listed individually. This was time consuming and error-prone. Now, you can view all changes in this GitHub commit.
-
Ensure node version is at least 6.0
node -v
. Install a newer version if yours is older. -
Move files in
src/pipes
tosrc/actions/mixins
-
Change
allow
tofillable
in forms -
Change
allow_virtual
tovirtual
in forms -
Run
shards update
-
Run
bin/setup
to run new migrations, Laravel Mix and seeds file
If you have any problems or want to add extra details please open an issue or Pull Request. Thank you!
- Upgrade Lucky CLI
On macOS:
brew update
brew upgrade crystal-lang
brew upgrade lucky
If you are on Linux, remove the existing Lucky binary and follow the Linux instructions in this section: https://luckyframework.org/guides/installing/#install-lucky
- Update dependencies in
shard.yml
dependencies:
lucky:
github: luckyframework/lucky
version: "~> 0.8.0"
lucky_migrator:
github: luckyframework/lucky_migrator
version: ~> 0.4.0
Then run shards update
- Update
config/server.cr
You can probably copy this as-is, but if you have made customizations to your
config/server.cr
then you'll need to customize this:
Lucky::Server.configure do |settings|
if Lucky::Env.production?
settings.secret_key_base = secret_key_from_env
settings.host = "0.0.0.0"
settings.port = ENV["PORT"].to_i
else
settings.secret_key_base = "<%= secret_key_base %>"
# Change host/port in config/watch.yml
# Alternatively, you can set the PORT env to set the port
settings.host = Lucky::ServerSettings.host
settings.port = Lucky::ServerSettings.port
end
end
private def secret_key_from_env
ENV["SECRET_KEY_BASE"]? || raise_missing_secret_key_in_production
end
private def raise_missing_secret_key_in_production
raise "Please set the SECRET_KEY_BASE environment variable. You can generate a secret key with 'lucky gen.secret_key'"
end
- Add
config/watch.yml
This is used by the watcher so it knows what port the server is running on.
host: 0.0.0.0
port: 5000
- Update
config/database.cr
Put this inside of the LuckyRecord::Repo.configure do |settings|
block:
# In development and test, raise an error if you forget to preload associations
settings.lazy_load_enabled = Lucky::Env.production?
See a full example here: https://github.com/luckyframework/lucky_cli/blob/a25472cc7461b1803735d086e57a632f92f93a1c/src/web_app_skeleton/config/database.cr.ecr
- You will need to preload associations now:
This will make N+1 queries a thing of the past.
# Will now raise a runtime error in dev/test
post = PostQuery.new.find(id)
post.comments # Must preload comments
# Now, you need to preload the comments
post = PostQuery.new.preload_comments.find(id)
post.comments
- Rename
field
tocolumn
in your models. For example
class Post < BaseModel
table :posts do
column title : String # was "field title : String" previously
end
end
- Optionally include
responsive_meta_tag
inMainLayout
You can include this in head
to make your app layout responsive.
-
Change
abstract def inner
toabstract def content
inMainLayout
-
Change method call to
inner
tocontent
in the render method ofMainLayout
-
Change instances of
def inner
todef content
in Pages -
Change form
needs
to useon: :create
needs
in forms should now use on: :save
if you want the old behavior.
See https://luckyframework.org/guides/saving-with-forms/#passing-extra-data-to-forms for more info
- Must pass extra params using
create
orupdate
You can no longer pass params to Form#new
. You must pass them in the
create
or update
.
UserForm.new(name: "Jane").save!
UserForm.create!(name: "Jane")
More info at https://luckyframework.org/guides/saving-with-forms/#passing-data-without-route-params
-
Change calls from
form.save_succeeded?
toform.saved?
-
Trap int in src/server.cr
Add this to your src/server.cr
before server.listen
Signal::INT.trap do
server.close
end
- Add
bin/lucky/
to.gitignore
# Add to .gitignore
bin/lucky/
- Add nice HTML error page
Copy contents of the linked file to src/pages/errors/show_page.cr
https://github.com/luckyframework/lucky_cli/blob/a25472cc7461b1803735d086e57a632f92f93a1c/src/web_app_skeleton/src/pages/errors/show_page.cr
- Add default
Error::ShowSerializer
This is used for serializing errors to JSON. Add this to
src/serializers/errors/show_serializer.cr
# This is the default error serializer generated by Lucky.
# Feel free to customize it in any way you like.
class Errors::ShowSerializer < Lucky::Serializer
def initialize(@message : String, @details : String? = nil)
end
def render
{message: @message, details: @details}
end
end
- Update
Errors::Show
action
The error handling action now supports more errors and renders better output.
Copy the contents of the linked file to src/actions/errors/show.cr
https://github.com/luckyframework/lucky_cli/blob/a25472cc7461b1803735d086e57a632f92f93a1c/src/web_app_skeleton/src/actions/errors/show.cr
- Require serializers
Add the following to src/app.cr
.
require "./serializers/**"
- Update to Crystal v0.24.1. Lucky will fail on earlier versions
brew update
brew upgrade crystal-lang
brew upgrade lucky
If you are on Linux, remove the existing Lucky binary and follow the Linux instructions in this section: https://luckyframework.org/guides/installing/#install-lucky
- Update dependencies in
shard.yml
dependencies:
lucky:
github: luckyframework/lucky
version: "~> 0.7.0"
lucky_migrator:
github: luckyframework/lucky_migrator
version: ~> 0.4.0
Then run shards update
- Configure the domain to use for the RouteHelper:
# Add to config/route_helper.cr
Lucky::RouteHelper.configure do |settings|
if Lucky::Env.production?
# The APP_DOMAIN is something like https://myapp.com
settings.domain = ENV.fetch("APP_DOMAIN")
else
settings.domain = "http:://localhost:3001"
end
end
- Add
csrf_meta_tags
to yourMainLayout
# src/pages/main_layout.cr
# Somewhere in the head tag:
csrf_meta_tags
- Remove
needs flash
fromMainLayout
# Delete this line
needs flash : Lucky::Flash::Store
- Remove
expose flash
fromBrowserAction
and add forgery protection
# src/actions/browser_action.cr
abstract class BrowserAction < Lucky::Action
include Lucky::ProtectFromForgery
end
- Change
Shared::FlashComponent
to get the flash from@context
# src/components/shared/flash_component.cr
# Change this:
@flash.each
# To:
@context.flash.each
- Add
*.dwarf
to the .gitignore
# Add to .gitignore
*.dwarf