Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Timestamp attributes are nil

I have 2 models, Microspost and User:

class Micropost < ActiveRecord::Base
  belongs_to :user
  default_scope -> { order(created_at: :desc) }
  validates :user_id, presence: true
  validates :content, presence: true, length: { maximum: 140 }
end

class User < ActiveRecord::Base
  has_many :microposts, dependent: :destroy
  attr_accessor :remember_token, :activation_token, :reset_token
  before_save   :downcase_email
  before_create :create_activation_digest
  validates :name, presence: true, length: { maximum: 50 }
end

seed.rb :

User.create!(name:  "Example User",
             email: "[email protected]",
             password:              "foobar",
             password_confirmation: "foobar",
             admin: true,
             activated:    true,
             activated_at: Time.zone.now)
99.times do |n|
  name  = Faker::Name.name
  email = "example-#{n+1}@railstutorial.org"
  password = "password"
  User.create!(name:  name,
               email: email,
               password:              password,
               password_confirmation: password,
               activated:    true,
               activated_at: Time.zone.now)  
end

# Microposts
users = User.order(:created_at).take(6)
50.times do
  content = Faker::Lorem.sentence(5)
  users.each { |user| user.microposts.create!(content: content) }
end

But when I used Faker to create Microposts, the created_at and updated_at attributes are nil in Rails but NOT in the posgresql console. This has confused me and I don't know how to fix it. Moreover when I manually create a post, the created_at attribute is not nil. Can someone please tell me what's going on?

2.1.5 :016 >   m = Micropost.create!(content: "hello", user_id: User.first.id)
  User Load (0.6ms)  SELECT  "users".* FROM "users"  ORDER BY "users"."id" ASC LIMIT 1
   (0.2ms)  BEGIN
  SQL (0.8ms)  INSERT INTO "microposts" ("content", "user_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["content", "hello"], ["user_id", 1], ["created_at", "2015-01-13 08:07:38.584269"], ["updated_at", "2015-01-13 08:07:38.584269"]]
   (9.6ms)  COMMIT
 => #<Micropost id: 301, content: "hello", user_id: 1, created_at: "2015-01-13 07:07:38", updated_at: "2015-01-13 07:07:38"> 
2.1.5 :017 > m.created_at
 => Tue, 13 Jan 2015 08:07:38 CET +01:00 

And of course here in my Posgresql console you can see that microposts do actually have timestamps.

railsdays_development=# \d+ microposts
                                                         Table "public.microposts"
   Column   |            Type             |                        Modifiers                        | Storage  | Stats target | Description 
------------+-----------------------------+---------------------------------------------------------+----------+--------------+-------------
 id         | integer                     | not null default nextval('microposts_id_seq'::regclass) | plain    |              | 
 content    | text                        |                                                         | extended |              | 
 user_id    | integer                     |                                                         | plain    |              | 
 created_at | timestamp without time zone | not null                                                | plain    |              | 
 updated_at | timestamp without time zone | not null                                                | plain    |              | 
Indexes:
    "microposts_pkey" PRIMARY KEY, btree (id)
    "index_microposts_on_user_id" btree (user_id)
    "index_microposts_on_user_id_and_created_at" btree (user_id, created_at)
Has OIDs: no

railsdays_development=# select * from microposts;
 id  |                                      content                                      | user_id |         created_at         |         updated_at         
-----+-----------------------------------------------------------------------------------+---------+----------------------------+----------------------------
   1 | Velit optio magni in modi distinctio.                                             |       1 | 2015-01-13 06:48:48.212602 | 2015-01-13 06:48:48.212602
   2 | Velit optio magni in modi distinctio.                                             |       2 | 2015-01-13 06:48:48.216021 | 2015-01-13 06:48:48.216021
   3 | Velit optio magni in modi distinctio.                                             |       3 | 2015-01-13 06:48:48.218617 | 2015-01-13 06:48:48.218617
   4 | Velit optio magni in modi distinctio.                                             |       4 | 2015-01-13 06:48:48.221544 | 2015-01-13 06:48:48.221544
   5 | Velit optio magni in modi distinctio.                                             |       5 | 2015-01-13 06:48:48.223975 | 2015-01-13 06:48:48.223975
   6 | Velit optio magni in modi distinctio.                                             |       6 | 2015-01-13 06:48:48.226611 | 2015-01-13 06:48:48.226611
   7 | Magni aliquid ut enim sunt aut.                                                   |       1 | 2015-01-13 06:48:48.22897  | 2015-01-13 06:48:48.22897
   8 | Magni aliquid ut enim sunt aut.                                                   |       2 | 2015-01-13 06:48:48.23096  | 2015-01-13 06:48:48.23096
   9 | Magni aliquid ut enim sunt aut.                                                   |       3 | 2015-01-13 06:48:48.232889 | 2015-01-13 06:48:48.232889
  10 | Magni aliquid ut enim sunt aut.                                                   |       4 | 2015-01-13 06:4:

Micropost created by Faker have nil timestamps. But Microposts I create myself have a valid timestamp.

This is from a micropost created by Faker (first 300 microposts)

2.1.5 :021 > Micropost.count
   (0.6ms)  SELECT COUNT(*) FROM "microposts"
 => 301 
2.1.5 :022 > a = Micropost.find(2).created_at
  Micropost Load (0.6ms)  SELECT  "microposts".* FROM "microposts" WHERE "microposts"."id" = $1  ORDER BY "microposts"."created_at" DESC LIMIT 1  [["id", 2]]
 => nil 
2.1.5 :023 > 

_create_microposts.rb :

class CreateMicroposts < ActiveRecord::Migration
  def change
    create_table :microposts do |t|
      t.text :content
      t.references :user, index: true

      t.timestamps null: false
    end
    add_index :microposts, [:user_id, :created_at]
  end
end
like image 255
emi Avatar asked Jan 13 '15 07:01

emi


1 Answers

After digging through your application, I've found that you have this line in your config/application.rb:

config.active_record.default_timezone = 'Warsaw'

config.active_record.default_timezone expects either :utc if you wish to use UTC, or :local if you expect it to use the time zone found in config.time_zone. Locally, when I set this to :local, I get:

>> Micropost.first
  Micropost Load (1.0ms)  SELECT  "microposts".* FROM "microposts"  ORDER BY "microposts"."created_at" DESC LIMIT 1
=> #<Micropost id: 300, content: "Nemo fuga eveniet expedita consequatur.", user_id: 6, created_at: "2015-01-19 22:21:48", updated_at: "2015-01-19 22:21:48", picture: nil>

When set to :utc, I get:

>> Micropost.first
  Micropost Load (0.6ms)  SELECT  "microposts".* FROM "microposts"  ORDER BY "microposts"."created_at" DESC LIMIT 1
=> #<Micropost id: 300, content: "Nemo fuga eveniet expedita consequatur.", user_id: 6, created_at: "2015-01-19 16:21:48", updated_at: "2015-01-19 16:21:48", picture: nil>

I probably would have missed this myself, but I went digging for the docs because the config "just didn't look right™."

The relevant documentation can be found in section 3.6 of the Rails guide under Configuring Active Record.

like image 197
CDub Avatar answered Oct 16 '22 17:10

CDub