Reputation: 20335
Ok, so I need help with datetime database fields.
Let's say my table is called "events" and has a datetime field named "starts_at". I have confirmed this in my schema.rb file (technically I am using Postgres):
create_table "events", force: true do |t|
t.string "name", null: false
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "starts_at
...
end
In my event.rb model, I have a validation to make sure the starts_at datetime is set:
attr_accessor :starts_at
validates :starts_at, presence: true
I'm testing this via the rails console and I can't get it to save any value, let alone create any validation errors. What gives? For example:
e = Event.new
e.name = 'Post 1'
e.starts_at = DateTime.now.utc
e.save
It appears to save, but there is no validation error, no mention of "starts_at" in the displayed query. Starts_at is nil in the database. My schema defines it as a "datetime" field but it ignores my DateTime variable. I thought, ok, maybe it is technically a string field and rails doesn't auto-convert for me:
e = Event.new
e.name = 'Post 2'
e.starts_at = DateTime.now.utc.to_s
e.save
Same thing. Thinking that the resulting format is being rejected in Postgres, I try this:
e = Event.new
e.name = 'Post 3'
e.starts_at = DateTime.now.utc.strftime('%Y-%m-%d %H:%M:%S')
e.save
I thought it might work with:
e.starts_at = Time.now.utc
Or, for Unix timestamp integer style:
e.starts_at = DateTime.now.utc.to_i
Nope, nothing works. What am I doing wrong?
Some questions:
How do I get a datetime field to accept my input -- any input! -- and actually save it to the database? Do I need to know which time format is ultimately being used by the database type (Postgres, MySQL, etc) and adjust accordingly? i.e. How does database agnosticism apply?
How can I update my validation to check if the database actually accepted my input? It's counterintuitive that I am validating the presence of my starts_at variable, but it will in fact allow it to be saved as nil.
Upvotes: 0
Views: 1236
Reputation: 106882
Remove this line:
attr_accessor :starts_at
It masks the original setter that comes with Rails and sets a instance variable instead.
If there is a column (like the starts_at
column here) in the database then there is no need to define a getter oder setter method on your own.
Upvotes: 1
Reputation: 22926
Probable issue is that Rails is protecting you from mass assignment of variables.
You need to remove attr_accessor on that columns that are saved as NULL in the database.
Explained really well here - What is attr_accessor in Ruby? and Difference between attr_accessor and attr_accessible
Upvotes: 0