@ damien-mathieu has a solid answer for displaying localized dates from I18n.localize , and his comment raises an important caveat: this interrupts the text input form. Since then, the rails give us a good solution.
Like Rails 5 , you can use the Rails attribute API to customize how user input is converted to a model or database value. In fact, it was available in Rails 4.2 , but not fully documented.
Through the considerable efforts of Sean Griffin, all model types are now defined as ActiveRecord::Type objects. This defines the only source of truth for how the attribute is processed. The type determines how the attribute is serialized (from the ruby ββtype to the database type), deserialized (from the database type to the ruby ββtype), and discarded (from user input to the ruby ββtype). This is a big deal, because messing with it used to be a minefield of special cases that developers should avoid.
First uncheck attribute docs to understand how to redefine attribute type. You probably need to read the docs to understand this answer.
How Rails Converts Attributes
Here's a quick tour of the Rails Attributes API. You can skip this section, but then you will not know how it works. What kind of fun is this?
Understanding how Rails handles user input for your attribute will allow us to override only one method instead of creating a more complete custom type. It will also help you write code better, as rails code is pretty good.
Since you did not mention the model, I assume that you have a Post with the attribute :publish_date (some would prefer the name :published_on , but I digress).
What is your type?
Find out which type :publish_date . We do not care that this is an instance of Date , we need to know what type_for_attribute returns:
This method is the only reliable source of information for everything related to the types of model attributes.
$ rails c > post = Post.where.not(publish_date: nil).first > post.publish_date.class => Date > Post.type_for_attribute('publish_date').type => :date
Now we know that the attribute :publish_date is a type :date . This is determined by ActiveRecord :: Type :: Date , which extends ActiveModel :: Type :: Date , which extends ActiveModel :: Type :: Value . I contacted the rails 5.1.3, but you will want to read the source of your version.
How is user input converted to ActiveRecord :: Type :: Date?
So, when you set :publish_date , the value is passed to cast , which calls cast_value . Since the form input is a string, it will try to execute fast_string_to_date , then fallback_string_to_date , which uses Date._parse .
If you get lost, do not worry. You do not need to understand the rails code to configure the attribute.
Custom Type Definition
Now that we understand how Rails uses the attribute API, we can easily make our own. Just create a custom type to override cast_value to expect localized date strings:
class LocalizedDate < ActiveRecord::Type::Date private
See how I just copied the rails code and made a little tweak. Easily. You can improve this by calling super and move the :short format to a parameter or constant.
Register your type so that it can be referenced by the symbol:
Cancel type :publish_date with your custom type:
class Post < ApplicationRecord attribute :publish_date, :localized_date end
Now you can use localized values ββin your form inputs: