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
- Lucky should be
~> 1.3.0
- Avram should be
~> 1.3.0
- Authentic should be
~> 1.0.1
- Carbon should be
~> 0.6.0
- Carbon Adapter should be
~> 0.6.0
- Lucky should be
-
Run
shards update
-
Upgrade Lucky CLI on Windows (Scoop)
scoop bucket add lucky https://github.com/luckyframework/scoop-bucket
scoop install lucky
No required updates needed for this release.
- Update: to Crystal 1.14
- Update: All previously pre-compiled tasks should now show in your
./bin/
as Crystal files. Build these to run them as compiled.
crystal build --release bin/lucky.gen.secret_key.cr -o bin/lucky.gen.secret_key
crystal build --release bin/lucky.watch.cr -o bin/lucky.watch
crystal build --release bin/lucky.exec.cr -o bin/lucky.exec
# ... etc...
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
- Lucky should be
~> 1.2.0
- Avram should be
~> 1.2.0
- Carbon should be
~> 0.5.1
- Carbon Adapter should be
~> 0.5.0
- LuckyFlow should be
~> 0.10.0
- Lucky should be
-
Run
shards update
-
Upgrade Lucky CLI on Windows (Scoop)
scoop bucket add lucky https://github.com/luckyframework/scoop-bucket
scoop install lucky
- Add: the annotation
@[DB::Field(ignore: true)]
to any instance variables you've added to your models. See PR - Remove: the Nexploit NPM package from your Github Actions if you're using SecTester. See PR
- Replace: any use of
Avram::Nothing.new
withIGNORE
. See PR
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
- Lucky should be
~> 1.1.0
- Avram should be
~> 1.1.0
- Authentic should be
~> 1.0.0
- Carbon should be
~> 0.4.0
- LuckyTask should be
~> 0.3.0
- LuckyFlow should be
~> 0.9.2
- LuckySecTester should be
~> 0.3.2
- Lucky should be
-
Run
shards update
- Add:
Avram.initialize_logging
to yourconfig/log.cr
file near the bottom. See PR - Update: all LuckyTask tasks. See PR
# All help_message instance methods are macro calls
def help_message
"my help message"
end
# is now
help_message "my help message"
# Calls to `name`, `summary`, or `help_message` from your task `call` method are now classes.
def call
# `name` is now
self.class.task_name
# `summary` is now
self.class.task_summary
# `help_message` is now
self.class.task_help_message
end
- Add:
allow_blank: true
on String columns you want to allow empty strings to be saved. See PR
class Post < BaseModel
table do
column title : String
# Field is required, but storing "" is ok
column sub_title : String, allow_blank: true
end
end
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
- Lucky should be
~> 1.0.0
- Avram should be
~> 1.0.0
- Authentic should be
~> 1.0.0
- Lucky should be
-
Run
shards update
- Update: to at least Crystal 1.6 or later.
- Update: Any use of a
DeleteOperation
that assumed the record could be nil should now assume the record will always exist in the block. See PR for more details
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
- Lucky should be
~> 1.0.0-rc1
- Avram should be
~> 1.0.0-rc1
- Authentic should be
~> 0.9.0
- Carbon (and carbon_sendgrid_adapter) should be
~> 0.3.0
- LuckyFlow should be
~> 0.9.0
- Lucky should be
-
Run
shards update
- Add: Avram to your
shard.yml
as a dependency. - Add:
require "avram/lucky"
tosrc/shards.cr
right belowrequire "lucky"
. See PR - Add:
require "avram/lucky/tasks"
totasks.cr
right belowrequire "lucky/tasks/**"
. See PR - Update: to Crystal 1.4 or later.
- Add:
include Lucky::RedirectableTurbolinksSupport
in yourBrowserAction
if you are using turbolinks. - Add:
live_reload_connect_tag
to yoursrc/components/shared/layout_head.cr
andreload_port: 3001
to yourconfig/watch.yml
file for live browser reloading. See this PR and this PR - Update:
Avram::Params.new()
now takesHash(String, Array(String))
instead ofHash(String, String)
. See PR - Update: arg names in
validate_numeric
fromless_than
andgreater_than
toat_least
andno_more_than
. See PR - Update: your LuckyFlow configuration...
# spec/spec_helper.cr
# ...
require "spec"
# ...
require "lucky_flow"
require "lucky_flow/ext/lucky"
require "lucky_flow/ext/avram"
# ...
# spec/setup/configure_lucky_flow.cr
# ...
LuckyFlow::Spec.setup
- Update the
lucky_sec_tester
shard to version0.1.0
- Replace turbolinks with Turbo
- Replace laravel-mix with Vite
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
- Lucky should be
~> 0.30.0
- Authentic should be
~> 0.8.2
- LuckyFlow should be
~> 0.7.3
NOTE: 0.8.0 is released, but may not be compatible yet
- Lucky should be
-
Run
shards update
- Update:
spec/support/api_client.cr
withapp AppServer.new
defined in the class.
class ApiClient < Lucky::BaseHTTPClient
app AppServer.new
def initialize
super
headers("Content-Type": "application/json")
end
def self.auth(user : User)
new.headers("Authorization": UserToken.generate(user))
end
end
- Update: the
request.remote_ip
method now pulls from the last (instead of first) valid IP in theX-Forwarded-For
list. See PR for details - Update: All primary repo branches are now
main
. Adjust any references accordingly. - Update:
./script/system_check
and remove mentions ofensure_process_runner_installed
. Nox is built-in See PR for details
- Update: uses of
AvramSlugify
toAvram::Slugify
. See PR for details - Update: specs to use transactions instead of truncate. See PR for details
# in spec/spec_helper.cr
require "./setup/**"
# Add this line
Avram::SpecHelper.use_transactional_specs(AppDatabase)
include Carbon::Expectations
include Lucky::RequestExpectations
include LuckyFlow::Expectations
- Remove: the
spec/setup/clean_database.cr
file. This accompanies the transactional specs update - Update: the
spec/setup/start_app_server.cr
file. This file is no longer needed if your action specs make standard calls, and are not using LuckyFlow. See PR for details
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
">= 1.0.0"
- Lucky should be
~> 0.29.0
- Authentic should be
~> 0.8.1
- Caron SendgidAdapter should be
~> 0.2.0
if you're using SendGrid - LuckyEnv should be
~> 0.1.4
- LuckyTask should be
~> 0.1.1
- JWT should be
~> 1.6.0
- Crystal should be
-
Run
shards update
- Remove: any usage of the
lucky build.release
task. Useshards build --release --production
instead. See PR for details - Update: to Crystal version 1.0.0 or greater. Versions below 1.0 are no longer supported. See PR for details
- Update: your
AppServer
insrc/app_server.cr
to have alisten
method defined. This method is now abstract onLucky::BaseAppServer
. See PR for details - Update: if you use UUID for primary keys in your models, ensure you've added the "pgcrypto" extension to your DB. The
id
value will no longer be generated on the Crystal side. See PR for details - Update: any usage of the
Status
enums in your SaveOperations to beOperationStatus
. See PR for details - Remove: any usage of
route
ornested_route
from your actions, and replace them with the actual route. (Optionally, you can use the Legacy Routing Shard) See PR for details - Update: your
src/app.cr
, and move the requires forconfig/server
andconfig/**
to the top of the require stack. See PR for details - Update: your
package.json
(Full Apps only) to useyarn run mix
instead of justmix
. See PR for details - Update: your
src/app_server.cr
middleware stack withLucky::RequestIdHandler.new
at the top of the stack beforeLucky::ForceSSLHandler.new
. See PR for details - Update: any usage of
add_belongs_to
with namespaced models to specify thereferences
option. See PR for details - Update: the
error_html
method insrc/actions/errors/show.cr
. Replace the following code
- html Errors::ShowPage, message: message, status: status
+ html_with_status Errors::ShowPage, status, message: message, status_code: status
- Rename: the
status
variable tostatus_code
insrc/pages/errors/show_page.cr
- Add: a new config
Lucky::RequestIdHandler
inconfig/server.cr
to set a request ID.
#...
Lucky::RequestIdHandler.configure do |settings|
settings.set_request_id = ->(context : HTTP::Server::Context) {
UUID.random.to_s
}
end
- Add: query cache to
config/database.cr
. See PR for details
Avram.configure do |settings|
settings.database_to_migrate = AppDatabase
# In production, allow lazy loading (N+1).
# In development and test, raise an error if you forget to preload associations
settings.lazy_load_enabled = LuckyEnv.production?
# Disable query cache during tests
settings.query_cache_enabled = !LuckyEnv.test?
end
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
">= 1.0.0"
- Lucky should be
~> 0.28.0
- Authentic should be
~> 0.8.0
- Carbon should be
~> 0.2.0
- Caron SendgidAdapter should be
~> 0.1.0
if you're using SendGrid - Dotenv should be replaced with LuckyEnv ~> 0.1.3
- Crystal should be
-
Run
shards update
- Remove:
needs context : HTTP::Server::Context
from any component, as well as passing it in to themount()
for the components. See PR for details - Rename: all
DeleteOperation.destroy
calls toDeleteOperation.delete
- Update:
avram_enum
to use the Crystalenum
. See PR for details
# Models get this update
- avram_enum State do
+ enum State
Started
Ended
end
# Factories get this update
- state Thing::State.new(:started)
+ state Thing::State::Started
# Operations get this update
- SaveThing.create(state: Thing::State.new(:started)) do |op, t|
+ SaveThing.create(state: Thing::State::Started) do |op, t|
# Queries get this update
- ThingQuery.new.state(Thing::State.new(:started).value)
+ ThingQuery.new.state(Thing::State::Started)
- Update: your
config/env.cr
to this.
# Environments are managed using `LuckyEnv`. By default, development, production
# and test are supported.
# If you need additional environment support, add it here
# LuckyEnv.add_env :staging
- Update: any use of
Lucky::Env
to useLuckyEnv
. (e.g.Lucky::Env.test?
->LuckyEnv.test?
). See PR for details - Update: any use of
Lucky::Env.name
to useLuckyEnv.environment
. - Update: any use of
route
ornested_route
, and replace them with the generated routes. Uselucky routes
to view all generated routes. If you still need this, you can use the Lucky Legacy Routing shard. - Add: the luckyframework/carbon_sendgrid_adapter shard if you're using Sendgrid to send mail. Be sure to
require "carbon_sendgrid_adapter"
inconfig/email.cr
.
- Update: all routes to use underscore (
_
) instead of dash (-
) as word separator. Include theLucky::EnforceUnderscoredRoute
module in your base actions. (e.g./this-route
->/this_route
)
class BrowserAction < Lucky::Action
include Lucky::EnforceUnderscoredRoute
# ...
end
- Update:
send_text_response()
responses if you're passing a raw JSON string to useraw_json()
instead. - Add:
include Lucky::SecureHeaders::DisableFLoC
to yourBrowserAction
to disable FLoC.
class BrowserAction < Lucky::Action
include Lucky::SecureHeaders::DisableFLoC
# ...
end
- Remove:
normalize-scss
from yourpackage.json
and replace withmodern-normalize
if you're usingnormalize-scss
. - Update: any query where you write code like
if SomeQuery.new.first?
toif SomeQuery.new.any?
..any?
returns a Bool instead of loading the whole object which has a small performance gain. - Add: the Breeze shard to your development workflow!
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.36.1, < 2.0.0"
- Lucky should be
~> 0.27.0
- Authentic should be
~> 0.7.3
- Carbon should be
~> 0.1.4
- Dotenv should be
~> 1.0.0
or replace with LuckyEnv 0.1.0 - LuckyFlow should be
~> 0.7.3
- JWT (if you use Auth) should be
~> 1.5.1
- LuckyTask needs to be added as a dependency
lucky_task: github: luckyframework/lucky_task version: ~> 0.1.0
- Crystal should be
-
Run
shards update
- Add: the new
lucky_task
shard as a dependency. - Update: your
tasks.cr
file with the new require, and module name change:# tasks.cr ENV["LUCKY_TASK"] = "true" # Load Lucky and the app (actions, models, etc.) require "./src/app" require "lucky_task" require "./tasks/**" require "./db/migrations/**" require "lucky/tasks/**" LuckyTask::Runner.run
- Update: all tasks in your
tasks/
directory to inherit fromLuckyTask::Task
instead ofLuckyCli::Task
. (e.g.Db::Seed::RequiredData < LuckyCli::Task
->Db::Seed::RequiredData < LuckyTask::Task
) - Update: your
config/cookies.cr
with a default cookie path of"/"
.Lucky::CookieJar.configure do |settings| settings.on_set = ->(cookie : HTTP::Cookie) { # ... other defaults # Add this line. See ref: https://github.com/crystal-lang/crystal/pull/10491 cookie.path("/") } end
- Update: to Crystal 1.0.0. You can continue to use Crystal 0.36.1 if you need.
- Update:
LuckyFlow
to be adevelopment_dependency
.
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.36.1
- Lucky should be
~> 0.26.0
- Authentic should be
~> 0.7.2
- LuckyFlow should be
~> 0.7.2
- Crystal should be
-
Run
shards update
- Update: your
Procfile
web to point to./bin/YOUR APP NAME
instead of./app
. NOTE: this is dependant on how you deploy your app, so only required if you use the heroku_buildpack for Lucky. read more and more - Update: any references directly to an
Avram::Attribute(T)
generic. e.g.Avram::Attribute(String?)
->Avram::Attribute(String)
. read more - Update: any custom database types to include the class method
adapter
that returns theLucky
constant. read more - Update: any custom database types to include the class method
criteria(query : T, column) forall T
. read more - Remove: any call to
after_completed
in a SaveOperation. Theafter_save
andafter_commit
now run even if no change is updated. read more - Rename: all
Avram::Box
classes, filenames, and thespec/support/boxes
directory (sorry 😬) toAvram::Factory
, etc.... e.g.UserBox
->UserFactory
read more. view discussion - Notice: the
Avram::Operation
now avoids callingrun
if there were validation errors in anybefore_run
. This may change some of your logic, or create surprised. read more
- Update: any calls made in Github CI config to
lucky db.create_required_seeds
tolucky db.seed.required_data
. read more - Update: any use of
route
ornested_route
in your actions to explicitly specify the route. This isn't deprecated, yet, but will be in a future version and eventually removed. - Add:
DB::Log.level = :info
to yourconfig/log.cr
file to quiet the excessive "Executing query" notices - Update: your Laravel Mix to version 6. read more
- Add: a new migration to have UUID primary keys generated from the database for existing tables. read more
# in a new migration file
def migrate
enable_extension "pgcrypto"
execute("ALTER TABLE products ALTER COLUMN id SET DEFAULT gen_random_uuid();")
execute("ALTER TABLE users ALTER COLUMN id SET DEFAULT gen_random_uuid();")
end
- Remove: all calls to
flash.keep
in your actions. read more
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.1
- Lucky should be
~> 0.25.0
- Authentic should be
~> 0.7.1
- LuckyFlow should be
~> 0.7.1
- Crystal should be
-
Run
shards update
-
Update: all
Avram::Operation
to implement the new interface.- Your main instance method should be called
run
- The
run
method should return just the value you need. No moreyield self, thing
/yield self, nil
. - Call the operation with
MyOperation.run(params)
instead ofMyOperation.new(params).submit
- The
MyOperation.run
class method takes a block that yields the operation, and your return value. Similar toSaveOperation
.
# Before Update class RequestPasswordReset < Avram::Operation #... def submit if valid? yield self, user else yield self, nil end end end # Use in your Action RequestPasswordReset.new(params).submit do |operation, user| end # After Update class RequestPasswordReset < Avram::Operation #... def run if valid? user else nil end end end # Use in your Action RequestPasswordReset.run(params) do |operation, user| end
- Your main instance method should be called
-
Rename: all usage of
with_defaults
totag_defaults
-
Update: query objects to no longer rely on mutating the query.
# Before update q = UserQuery.new q.age.gte(21) q.to_sql #=> SELECT * FROM users WHERE age >= 21 # After update q = UserQuery.new q.age.gte(21) q.to_sql #=> SELECT * FROM users
-
Rename: all usage of
raw_where
towhere
-
Update: query objects that set a default query in the initializer to use the
defaults
method.# Before update class UserQuery < User::BaseQuery def initialize admin(false) end end UserQuery.new.to_sql #=> SELECT * FROM users WHERE admin = false # After update class UserQuery < User::BaseQuery def initialize defaults &.admin(false) end end UserQuery.new.to_sql #=> SELECT * FROM users WHERE admin = false
-
Update: any
has_many through
model association to include the new assocation chain.# Before update has_many posts : Post has_many comments : Comment, through: :posts # After update # The first in the array is the association you're going through # The second is that through's association. has_many posts : Post has_many comments : Comment, through: [:posts, :comments]
-
Update: any query that used a
where_XXX
on abelongs_to
from the pluralized name to singularized.# assuming Post belongs_to User # Before update PostQuery.new.where_users(UserQuery.new) # After update PostQuery.new.where_user(UserQuery.new) # Notice the 'where_user' is single now
- Update: any mention of
DB_URL
that we told you to use should actually beDATABASE_URL
- Remove: any include for
include Lucky::Memoizable
. This is now included inObject
and available everywhere - Update: HTML tags that display a
UUID
no longer need to cast to String.link uuid, to: Whatever
- Remove: any
start_server
orstart_server.dwarf
files in the top-level directory. These are now built to yourbin/
- Update:
config/email.cr
to include a case for development to print emails.# config/email.cr BaseEmail.configure do |settings| if Lucky::Env.production? # ... elsif Lucky::Env.development? settings.adapter = Carbon::DevAdapter.new(print_emails: true) else # ... end end
- Update: any
call(io : IO)
method in your tasks, and use theoutput
property instead for testing. read more - Update: your
package.json
with all the latest front-end updates. read more - Rename: your seed tasks
tasks/create_required_seeds.cr
->tasks/db/seed/required_data.cr
, andtasks/create_sample_seeds.cr
->tasks/db/seed/sample_data.cr
- Update:
config/log.cr
to silence some of the query logging withDB::Log.level = :info
.
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.1
- Lucky should be
~> 0.24.0
- Authentic should be
~> 0.7.0
- Crystal should be
-
Run
shards update
- Rename: all instances of the
m
method tomount
. e.g.m Shared::Footer, year: 2020
->mount Shared::Footer, year: 2020
. - Update:
config/database.cr
with newAvram::Credentials
.
AppDatabase.configure do |settings|
if Lucky::Env.production?
settings.credentials = Avram::Credentials.parse(ENV["DATABASE_URL"])
else
settings.credentials = Avram::Credentials.parse?(ENV["DATABASE_URL"]?) || Avram::Credentials.new(
database: database_name,
hostname: ENV["DB_HOST"]? || "localhost",
# NOTE: This was changed from `String` to `Int32`
port: ENV["DB_PORT"]?.try(&.to_i) || 5432,
username: ENV["DB_USERNAME"]? || "postgres",
password: ENV["DB_PASSWORD"]? || "postgres"
)
end
end
- Rename: all instances of
AppClient
toApiClient
in yourspec/
directory. - Update:
script/setup
withshards install --ignore-crystal-version
. Alternatively, you can set a globalSHARDS_OPTS=--ignore-crystal-version
environment variable
- Update:
redirect_back
withallow_external: true
argument if you need to allow external referers - Update: your database credentials with the new
query
option to pass query string options
# config/database.cr
settings.credentials = Avram::Credentials.new(
database: database_name,
hostname: ENV["DB_HOST"]? || "localhost",
port: ENV["DB_PORT"]?.try(&.to_i) || 5432,
username: ENV["DB_USERNAME"]? || "postgres",
password: ENV["DB_PASSWORD"]? || "postgres",
# This option is new
query: "initial_pool_size=5&max_pool_size=20"
)
- Add:
disable_cookies
toApiAction
insrc/actions/api_action.cr
.
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