Rails Updating attribute always inserts nil - ruby-on-rails

Having an issue with a database update. At first I thought it might be related to Carrierwave but after this test I don't think so anymore.
Here I try and update the attribute in the rails console, only to have the image field return nil. But notice that the property_id field changes.
2.2.0 :004 > Propimage
=> Propimage(id: integer, property_id: integer, image: string, created_at: datetime, updated_at: datetime)
2.2.0 :005 > Propimage.last
Propimage Load (0.7ms) SELECT "propimages".* FROM "propimages" ORDER BY "propimages"."id" DESC LIMIT 1
=> #<Propimage id: 37, property_id: 5, image: nil, created_at: "2015-07-15 20:06:55", updated_at: "2015-07-15 20:22:30">
2.2.0 :006 > Propimage.last.update_attributes(image: 'Picture.jpg', property_id: 3)
Propimage Load (0.3ms) SELECT "propimages".* FROM "propimages" ORDER BY "propimages"."id" DESC LIMIT 1
(0.1ms) begin transaction
Propimage Load (0.2ms) SELECT "propimages".* FROM "propimages" WHERE "propimages"."id" = ? LIMIT 1 [["id", 37]]
SQL (0.5ms) UPDATE "propimages" SET "image" = ?, "property_id" = ?, "updated_at" = ? WHERE "propimages"."id" = ? [["image", nil], ["property_id", 3], ["updated_at", "2015-07-15 20:24:06.501042"], ["id", 37]]
(1.1ms) commit transaction
=> true
2.2.0 :007 > Propimage.last
Propimage Load (0.2ms) SELECT "propimages".* FROM "propimages" ORDER BY "propimages"."id" DESC LIMIT 1
=> #<Propimage id: 37, property_id: 3, image: nil, created_at: "2015-07-15 20:06:55", updated_at: "2015-07-15 20:24:06">
2.2.0 :008 >
And here I try to create a new entry
2.2.0 :009 > Propimage.new(image: 'Picture.jpg', property_id: 5).save
(0.2ms) begin transaction
SQL (1.0ms) INSERT INTO "propimages" ("image", "property_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["image", nil], ["property_id", 5], ["created_at", "2015-07-15 20:30:17.797735"], ["updated_at", "2015-07-15 20:30:17.797735"]]
(1.7ms) commit transaction
=> true
My next step is to recreate this table in the database. Any help is greatly appreciated.
class CreatePropimages < ActiveRecord::Migration
def change
create_table :propimages do |t|
t.references :property, index: true, foreign_key: true
t.string :image
t.timestamps null: false
end
end
end
propimage.rb
class Propimage < ActiveRecord::Base
belongs_to :property
mount_uploader :image, ImageUploader
end

Related

rails_admin won't let me keep my enum field as nil

Model:
class Reservation < ApplicationRecord
# https://naturaily.com/blog/ruby-on-rails-enum
enum recurrence: {
daily: 0,
weekly: 1,
monthly: 2,
annually: 3
}, _prefix: :recurring
belongs_to :user
validates :name, :user_id, presence: true
...
end
Migration:
class CreateReservations < ActiveRecord::Migration[5.2]
def change
create_table :reservations do |t|
t.string 'name', null: false
...
t.boolean 'recurring', default: false, null: false
t.integer 'recurrence', index: true, allow_blank: true, default: nil # trying a lot of things here
t.datetime 'expire_time'
...
end
end
end
Works as expected in the console:
2.4.5 :002 > res = Reservation.new(name: 'test', user_id: 1)
=> #<Reservation id: nil, name: "test", recurring: false, recurrence: nil, date: nil, start_time: nil, end_time: nil, expire_time: nil, user_id: 1, created_at: nil, updated_at: nil>
2.4.5 :003 > res.valid?
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
=> true
2.4.5 :004 > res.save
(0.2ms) BEGIN
Reservation Create (0.5ms) INSERT INTO "reservations" ("name", "user_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["name", "test"], ["user_id", 1], ["created_at", "2019-09-24 20:42:40.933959"], ["updated_at", "2019-09-24 20:42:40.933959"]]
(2.1ms) COMMIT
=> true
2.4.5 :005 > res.reload
Reservation Load (0.3ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."id" = $1 LIMIT $2 [["id", 5], ["LIMIT", 1]]
=> #<Reservation id: 5, name: "test", recurring: false, recurrence: nil, date: nil, start_time: nil, end_time: nil, expire_time: nil, user_id: 1, created_at: "2019-09-24 20:42:40", updated_at: "2019-09-24 20:42:40">
2.4.5 :006 > res.recurrence
=> nil
And yet, in Rails Admin, when I create or edit a record, they all get assigned to the first enum. Even when I intentionally delete the value from the form, it still saves the record with the first enum value.
Rails Admin:
config.model Reservation do
weight 2
parent Event
list do
field :name
field :display_date do
formatted_value { bindings[:object].display_date }
end
field :recurrence, :active_record_enum # should be unnecessary, but trying everything
field :expire_time
field :user do
label 'Creator'
formatted_value { bindings[:object].user.name }
end
end
end
I have tried:
not indexing this field (thinking Rails Admin wants a value for indexed columns)
ensuring `:active_record_enum` is declared on `field :recurrence`
As suggested, here's the related section of the log:
Started POST "/admin/reservation/new" for ::1 at 2019-09-25 10:09:50 -0400
Processing by RailsAdmin::MainController#new as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"VbhHM7YD+oQvwMYIQzMHyT5e0MXFFuN3pyH/1s6yM8n6kqKvywZ5E8zaABMKhOU+oWpfU1Kk55FWYjL9TzbkbQ==", "reservation"=>{"name"=>"logs", "date"=>"", "start_time"=>"", "end_time"=>"", "recurring"=>"0", "recurrence"=>"", "expire_time"=>"", "start_time_of_day"=>"", "end_time_of_day"=>"", "day_of_week"=>"", "date_of_month"=>"", "date_of_year"=>"", "user_id"=>"1"}, "return_to"=>"http://localhost:3000/admin/reservation", "_save"=>"", "model_name"=>"reservation"}
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
(0.2ms) BEGIN
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Reservation Create (0.4ms) INSERT INTO "reservations" ("name", "recurrence", "day_of_week", "date_of_month", "date_of_year", "user_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id" [["name", "logs"], ["recurrence", 0], ["day_of_week", ""], ["date_of_month", ""], ["date_of_year", ""], ["user_id", 1], ["created_at", "2019-09-25 14:09:50.926864"], ["updated_at", "2019-09-25 14:09:50.926864"]]
(1.3ms) COMMIT
Redirected to http://localhost:3000/admin/reservation
Completed 302 Found in 26ms (ActiveRecord: 3.0ms)
And, sure enough the param "recurrence"=>"" is transformed into ["recurrence", 0]
It seems to be a known issue, but if it's a legit bug, I still need help with a work-around. Anyone solved this already?
This technically works, but I'm thinking it's not the ideal solution:
If you declare your enum as a hash (not an array) and don't assign anything to 0, it works.
In my case enum recurrence: { daily: 0, weekly: 1, monthly: 2, annually: 3 } becomes enum recurrence: { daily: 1, weekly: 2, monthly: 3, annually: 4 }
The logs show the param isn't passed to the SQL:
Started POST "/admin/reservation/new" for ::1 at 2019-09-25 10:21:17 -0400
Processing by RailsAdmin::MainController#new as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Joyg5VuquwMMKg+ps2zg9t+8r0DZ0iOIkqRlk1cBkemJpkV5Jq84lO8wybL62wIBQIgg1k5gJ25j56i41oVGTQ==", "reservation"=>{"name"=>"test3", "date"=>"", "start_time"=>"", "end_time"=>"", "recurring"=>"0", "recurrence"=>"", "expire_time"=>"", "start_time_of_day"=>"", "end_time_of_day"=>"", "day_of_week"=>"", "date_of_month"=>"", "date_of_year"=>"", "user_id"=>"1"}, "return_to"=>"http://localhost:3000/admin/reservation", "_save"=>"", "model_name"=>"reservation"}
User Load (1.2ms) SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
(0.2ms) BEGIN
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Reservation Create (1.3ms) INSERT INTO "reservations" ("name", "day_of_week", "date_of_month", "date_of_year", "user_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" [["name", "test3"], ["day_of_week", ""], ["date_of_month", ""], ["date_of_year", ""], ["user_id", 1], ["created_at", "2019-09-25 14:21:17.091292"], ["updated_at", "2019-09-25 14:21:17.091292"]]
(5.7ms) COMMIT
The param contains "recurrence"=>"", but the INSERT INTO doesn't have an array for recurrence like it did before.
And I confirmed in the console:
2.4.5 :001 > res = Reservation.first
Reservation Load (0.4ms) SELECT "reservations".* FROM "reservations" ORDER BY "reservations"."id" ASC LIMIT $1 [["LIMIT", 1]]
=> #<Reservation id: 4, name: "test3", date: nil, start_time: nil, end_time: nil, recurring: false, recurrence: nil, expire_time: nil, start_time_of_day: nil, end_time_of_day: nil, day_of_week: "", date_of_month: "", date_of_year: "", user_id: 1, created_at: "2019-09-25 14:21:17", updated_at: "2019-09-25 14:21:17">
2.4.5 :002 > res.recurrence
=> nil
However, it seems to me like I'm just passing a dis-allowed value and letting Rails reject it. This still seems to be an issue with Rails Admin, specifically with integer enums.
It could be a restriction of using hashes, because nil values should work. Since you're mapping those to 0-indexed values, you should just use a symbol array. The ActiveRecord::Enum documentation (linked above) states:
Note that when an array is used, the implicit mapping from the values to database integers is derived from the order the values appear in the array. In the example, :active is mapped to 0 as it's the first element, and :archived is mapped to 1. In general, the i-th element is mapped to i-1 in the database.
So you should be able to just use an array of symbols for this.

How to save into another table when one table's one record changed from nil to not nil with Rails?

Rails version: 5.2.2.1
Want to insert or update data in post_copies when title data in posts changed from nil to real data.
What I tried:
Model
class Post < ApplicationRecord
after_save :save_post_copy
private
def save_post_copy
if will_save_change_to_title? == nil and saved_change_to_title?
post_copy = PostCopy.find_by(id: self.id)
if post_copy.nil?
PostCopy.create!(id: self.id, title: self.title, body: self.body)
else
post_copy.update!(title: self.title, body: self.body)
end
end
end
end
Console
Case 1: Update from nil to not nil data
post = Post.new
=> #<Post id: nil, title: nil, body: nil, created_at: nil, updated_at: nil>
post.body = 'test'
=> "test"
post.save!
(0.1ms) begin transaction
Post Create (0.9ms) INSERT INTO "posts" ("body", "created_at", "updated_at") VALUES (?, ?, ?) [["body", "test"], ["created_at", "2019-05-20 07:19:50.289983"], ["updated_at", "2019-05-20 07:19:50.289983"]]
(6.5ms) commit transaction
=> true
post.title = '3'
=> '3'
post.save!
(0.1ms) begin transaction
Post Update (0.5ms) UPDATE "posts" SET "title" = ?, "updated_at" = ? WHERE "posts"."id" = ? [["title", "3"], ["updated_at", "2019-05-20 07:20:04.138089"], ["id", 8]]
PostCopy Load (0.1ms) SELECT "post_copies".* FROM "post_copies" WHERE "post_copies"."id" = ? LIMIT ? [["id", 8], ["LIMIT", 1]]
PostCopy Create (0.3ms) INSERT INTO "post_copies" ("title", "body", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["title", "3"], ["body", "test"], ["created_at", "2019-05-20 07:20:04.148852"], ["updated_at", "2019-05-20 07:20:04.
148852"]]
(7.1ms) commit transaction
=> true
Case 2: Update from not nil to nil data
post
=> #<Post id: 10, title: "ten", body: "10", created_at: "2019-05-20 07:21:08", updated_at: "2019-05-20 07:21:41">
post.title = nil
post.save!
(0.1ms) begin transaction
Post Update (1.4ms) UPDATE "posts" SET "title" = ?, "updated_at" = ? WHERE "posts"."id" = ? [["title", nil], ["updated_at", "2019-05-20 07:34:15.594000"], ["id", 10]]
PostCopy Load (0.1ms) SELECT "post_copies".* FROM "post_copies" WHERE "post_copies"."id" = ? LIMIT ? [["id", 10], ["LIMIT", 1]]
PostCopy Create (0.3ms) INSERT INTO "post_copies" ("body", "created_at", "updated_at") VALUES (?, ?, ?) [["body", "10"], ["created_at", "2019-05-20 07:34:15.598453"], ["updated_at", "2019-05-20 07:34:15.598453"]]
(1.8ms) commit transaction
=> true
Case 3: Update from not nil to not nil(another) data
post
=> #<Post id: 10, title: "ten", body: "10", created_at: "2019-05-20 07:21:08", updated_at: "2019-05-20 07:21:41">
post.will_save_change_to_title?
=> nil
post.title = '1'
=> "1"
post.will_save_change_to_title?
=> true
post.save!
(0.1ms) begin transaction
Post Update (0.6ms) UPDATE "posts" SET "title" = ?, "updated_at" = ? WHERE "posts"."id" = ? [["title", "1"], ["updated_at", "2019-05-20 07:37:46.467899"], ["id", 10]]
PostCopy Load (0.1ms) SELECT "post_copies".* FROM "post_copies" WHERE "post_copies"."id" = ? LIMIT ? [["id", 10], ["LIMIT", 1]]
PostCopy Update (0.3ms) UPDATE "post_copies" SET "title" = ?, "updated_at" = ? WHERE "post_copies"."id" = ? [["title", "1"], ["updated_at", "2019-05-20 07:37:46.471654"], ["id", 10]]
(1.3ms) commit transaction
=> true
Case 2 and case 3 trigger the saving/updating to post_copies action. So the will_save_change_to_title? == nil can't known data change from nil to not nil.
From here:
https://api.rubyonrails.org/classes/ActiveModel/Dirty.html
There are these methods:
person = Person.new
person.changed? # => false
person.name = 'Bob'
person.changed? # => true
person.name_changed? # => true
person.name_changed?(from: nil, to: "Bob") # => true
person.name_was # => nil
person.name_change # => [nil, "Bob"]
person.name = 'Bill'
person.name_change # => [nil, "Bill"]
But seems 'not exists in will_save_change_to_title.
I think your problem is in using "after_save": try using "before_save" instead.
EDIT: Alright, i've tried it as well now, and after i realized it wasn't working, i checked your link: it doesn't look like you've done what is required to implement those methods.
Everything is specified at the top of the page:
The requirements for implementing ActiveModel::Dirty are:
include ActiveModel::Dirty in your object.
Call define_attribute_methods passing each method you want to track.
Call [attr_name]_will_change! before each change to the tracked attribute.
Call changes_applied after the changes are persisted.
Call clear_changes_information when you want to reset the changes information.
Call restore_attributes when you want to restore previous data.
Try following those instructions and the example.

Rails find_or_initialize_by not inserting data only "created_at", "updated_at"

I am trying to pull data from a csv and insert into database using rake. For some reason the insert statement is not including the data provided. As you can see in the Development.log file it searches for the correct record which does not exist then it tries to create the record. but only inserts date stamps for "created_at", "updated_at".
I am new to rails so it might be something very easy, but i was unable to find an answer online.I have been trying to figure out why its not working all day, any help is greatly appreciated
USDAData.csv
"ABELI","Abelia","abelia"
"ABGR4","Abelia ×grandiflora","glossy abelia"
"ABELM","Abelmoschus","okra"
"ABES","Abelmoschus esculentus","okra"
"ABMA9","Abelmoschus manihot",""
USDAData.rake
namespace :USDAData do
desc "import data from USDA to database"
task :import => :environment do
file = File.open(File.join(Rails.root, 'db', 'USDAData.csv'))
file.each do |line|
attrs = line.split(",")
#Accepted_Symbol = attrs[0].gsub!(/\A"|"\Z/, '')
#Scientific_Name = attrs[1].gsub!(/\A"|"\Z/, '').titleize
#Common_Name = attrs[2].gsub!(/\A"|"\Z/, '').titleize
p = Plant.find_or_create_by(Accepted_Symbol: #Accepted_Symbol, Scientific_Name: #Scientific_Name, Common_Name: #Common_Name)
end
end
end
development.log
[1m[36mPlant Load (0.4ms)[0m [1mSELECT "plants".* FROM "plants" WHERE "plants"."Accepted_Symbol" = ? AND "plants"."Scientific_Name" = ? AND "plants"."Common_Name" = ? LIMIT 1[0m [["Accepted_Symbol", "ABELI"], ["Scientific_Name", "Abelia"], ["Common_Name", "Abelia\n"]]
[1m[35m (0.2ms)[0m begin transaction
[1m[36mSQL (0.5ms)[0m [1mINSERT INTO "plants" ("created_at", "updated_at") VALUES (?, ?)[0m [["created_at", "2015-02-19 23:20:54.468007"], ["updated_at", "2015-02-19 23:20:54.468007"]]
[1m[35m (9.6ms)[0m commit transaction
[1m[36mPlant Load (0.2ms)[0m [1mSELECT "plants".* FROM "plants" WHERE "plants"."Accepted_Symbol" = ? AND "plants"."Scientific_Name" = ? AND "plants"."Common_Name" = ? LIMIT 1[0m [["Accepted_Symbol", "ABGR4"], ["Scientific_Name", "Abelia ×Grandiflora"], ["Common_Name", "Glossy Abelia\n"]]
[1m[35m (0.1ms)[0m begin transaction
[1m[36mSQL (0.3ms)[0m [1mINSERT INTO "plants" ("created_at", "updated_at") VALUES (?, ?)[0m [["created_at", "2015-02-19 23:20:54.482516"], ["updated_at", "2015-02-19 23:20:54.482516"]]
[1m[35m (9.8ms)[0m commit transaction
[1m[36mPlant Load (0.1ms)[0m [1mSELECT "plants".* FROM "plants" WHERE "plants"."Accepted_Symbol" = ? AND "plants"."Scientific_Name" = ? AND "plants"."Common_Name" = ? LIMIT 1[0m [["Accepted_Symbol", "ABELM"], ["Scientific_Name", "Abelmoschus"], ["Common_Name", "Okra\n"]]
plant.rb
class Plant < ActiveRecord::Base
attr_accessor :Accepted_Symbol, :Scientific_Name, :Common_Name
validates :Accepted_Symbol, presence: true, :null => false
validates :Scientific_Name, presence: true, :null => false
validates :Common_Name, presence: true
before_save :test
def test
puts "test: #{#Accepted_Symbol}"
end
end
schema.rb
ActiveRecord::Schema.define(version: 20150218210119) do
create_table "plants", force: :cascade do |t|
t.string "Accepted_Symbol"
t.string "Scientific_Name"
t.string "Common_Name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
Rails Console > Plant.first(5)
>> Plant.first(5)
Plant Load (0.3ms) SELECT "plants".* FROM "plants" ORDER BY "plants"."id" ASC LIMIT 5
=> [#<Plant id: 1, Accepted_Symbol: nil, Scientific_Name: nil, Common_Name: nil, created_at: "2015-02-19 23:20:54", updated_at: "2015-02-19 23:20:54">,
#<Plant id: 2, Accepted_Symbol: nil, Scientific_Name: nil, Common_Name: nil, created_at: "2015-02-19 23:20:54", updated_at: "2015-02-19 23:20:54">,
#<Plant id: 3, Accepted_Symbol: nil, Scientific_Name: nil, Common_Name: nil, created_at: "2015-02-19 23:20:54", updated_at: "2015-02-19 23:20:54">,
#<Plant id: 4, Accepted_Symbol: nil, Scientific_Name: nil, Common_Name: nil, created_at: "2015-02-19 23:20:54", updated_at: "2015-02-19 23:20:54">,
#<Plant id: 5, Accepted_Symbol: nil, Scientific_Name: nil, Common_Name: nil, created_at: "2015-02-19 23:20:54", updated_at: "2015-02-19 23:20:54">]
The before_save outputs the symbol, thus adding to the confusion. The data is making it all the way to the active-record but then those attributes are dropped from the insert statement.
SOLVED:
The issue was attr_accessor :Accepted_Symbol, :Scientific_Name, :Common_Name in my Plant.rb model, as suggested by Jordan Dedels. Marked as answered.
attr_accessor should only be used for attributes you do not want to store in the database. Remove this line and it should work:
attr_accessor :Accepted_Symbol, :Scientific_Name, :Common_Name

undefined method with has_many association

I have 2 models with a one-to-many association: User and Recipe. the User class has_many :recipes while the Recipe class belongs_to :user. I've already run the migration, reloaded the rails console, and checked to make sure that user_id is a column in the recipes table. Still, I get an undefined method error when I try to append a recipe to a user:
2.0.0-p598 :047 > user.recipes << Recipe.first
NoMethodError: undefined method `recipes' for #<User:0x00000004326fa0>
here is the migration code (I've already run rake db:migrate):
class AddUserIdToRecipes < ActiveRecord::Migration
def change
add_column :recipes, :user_id, :integer
end
end
Here is the User model code:
class User < ActiveRecord::Base
has_one :profile
has_many :recipes
end
Here is the Recipe model code:
class Recipe < ActiveRecord::Base
validates_presence_of :title, :body
belongs_to :user
def long_title
"#{title} - #{published_at}"
end
end
Why does recipes still show up as an undefined method?
Try this on your console:
irb(main):007:0> user = User.new first_name: 'John', last_name: 'Doe'
=> #<User id: nil, first_name: "John", last_name: "Doe", created_at: nil, updated_at: nil>
irb(main):008:0> user.save
(0.1ms) begin transaction
SQL (0.6ms) INSERT INTO "users" ("created_at", "first_name", "last_name", "updated_at") VALUES (?, ?, ?, ?) [["created_at", "2015-01-19 21:14:33.489371"], ["first_name", "John"], ["last_name", "Doe"], ["updated_at", "2015-01-19 21:14:33.489371"]]
(0.6ms) commit transaction
=> true
irb(main):009:0> r = Recipe.new name: 'oooohh awesome', description: 'my description goes here'
=> #<Recipe id: nil, name: "oooohh awesome", description: "my description goes here", created_at: nil, updated_at: nil, user_id: nil>
irb(main):010:0> r.save
(0.1ms) begin transaction
SQL (0.2ms) INSERT INTO "recipes" ("created_at", "description", "name", "updated_at") VALUES (?, ?, ?, ?) [["created_at", "2015-01-19 21:15:16.548090"], ["description", "my description goes here"], ["name", "oooohh awesome"], ["updated_at", "2015-01-19 21:15:16.548090"]]
(1.2ms) commit transaction
=> true
irb(main):011:0> user.recipes << Recipe.first
Recipe Load (0.2ms) SELECT "recipes".* FROM "recipes" ORDER BY "recipes"."id" ASC LIMIT 1
(0.0ms) begin transaction
SQL (0.2ms) UPDATE "recipes" SET "updated_at" = ?, "user_id" = ? WHERE "recipes"."id" = 1 [["updated_at", "2015-01-19 21:15:49.181586"], ["user_id", 1]]
(1.3ms) commit transaction
Recipe Load (0.2ms) SELECT "recipes".* FROM "recipes" WHERE "recipes"."user_id" = ? [["user_id", 1]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Recipe id: 1, name: "oooohh awesome", description: "sper long deskdk", created_at: "2015-01-19 21:10:24", updated_at: "2015-01-19 21:15:49", user_id: 1>]>
irb(main):012:0> user.save
(0.1ms) begin transaction
(0.0ms) commit transaction
=> true
irb(main):013:0> user.recipes
=> #<ActiveRecord::Associations::CollectionProxy [#<Recipe id: 1, name: "oooohh awesome", description: "sper long deskdk", created_at: "2015-01-19 21:10:24", updated_at: "2015-01-19 21:15:49", user_id: 1>]>
irb(main):014:0> user.recipes.first
=> #<Recipe id: 1, name: "oooohh awesome", description: "sper long deskdk", created_at: "2015-01-19 21:10:24", updated_at: "2015-01-19 21:15:49", user_id: 1>
irb(main):015:0>
you can see that Recipe.first has been inserted into user.recipes and its saved.
I made two models similar to yours, and have exactly the same setup as you. You can follow code above to write your controllers.

for sqlite3 in Rails, some fields like "created_at" and "updated_at" are returned as nil

I'm working on a project using Rails 4 with sqlite3 as the backend database, for one of the model "Reservation", after I save a record to the database, and then retrieve it, the value field "start_time", "end_time", "created_at" and "updated_at" are returned as nil. Is there any possible reasons for this issue?
see log below:
[3] pry(main)> a = Reservation.create(start_time: DateTime.now, seats: 2, user_id: 287, end_time: DateTime.now, restaurant_id: 88)
(0.1ms) begin transaction
SQL (0.4ms) INSERT INTO "reservations" ("created_at", "end_time", "restaurant_id",
"seats", "start_time", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?, ?, ?)
[["created_at", "2014-06-30 21:10:10.121316"], ["end_time", "2014-06-30
21:10:10.115301"], ["restaurant_id", 88], ["seats", 2], ["start_time", "2014-06-30
21:10:10.115191"], ["updated_at", "2014-06-30 21:10:10.121316"], ["user_id", 287]]
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1
[["id", 287]]
User Exists (0.1ms) SELECT 1 AS one FROM "users" WHERE ("users"."email" =
'grace#seatyourself.com' AND "users"."id" != 287) LIMIT 1
SQL (0.1ms) UPDATE "users" SET "loyalty_points" = ?, "updated_at" = ? WHERE
"users"."id" = 287 [["loyalty_points", 20], ["updated_at", "2014-06-30
21:10:10.146650"]]
(0.7ms) commit transaction
=> #<Reservation id: 110, start_time: "2014-07-01 01:10:10", seats: 2, user_id: 287,
created_at: "2014-07-01 01:10:10", updated_at: "2014-07-01 01:10:10", end_time:
"2014-07-01 01:10:10", restaurant_id: 88>
[4] pry(main)> a
=> #<Reservation id: 110, start_time: "2014-07-01 01:10:10", seats: 2, user_id: 287,
created_at: "2014-07-01 01:10:10", updated_at: "2014-07-01 01:10:10", end_time: "2014-
07-01 01:10:10", restaurant_id: 88>
[5] pry(main)> b = Reservation.last
Reservation Load (0.2ms) SELECT "reservations".* FROM "reservations" ORDER BY
"reservations"."id" DESC LIMIT 1
=> #<Reservation id: 110, start_time: nil, seats: 2, user_id: 287, created_at: nil,
updated_at: nil, end_time: nil, restaurant_id: 88>
The schema for the model:
create_table "reservations", force: true do |t|
t.datetime "start_time"
t.integer "seats"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "end_time"
t.integer "restaurant_id"
end
This is the model for Reservation(validations are temporarily commented out for debugging this issue)
class Reservation < ActiveRecord::Base
belongs_to :user
belongs_to :restaurant
after_create :add_loyalty_points #,:send_confirmation_email
after_destroy :remove_loyalty_points
#validates :start_time, :end_time, :seats, presence: true
#validates :seats, numericality: {:greater_than_or_equal_to => 2, :less_than_or_equal_to => 20}
#validate :reservation_only_last_for_an_hour
#validate :reservation_should_not_exceed_restaurant_capacity
#validate :reservation_should_not_outside_operating_hours
# validates :start_time, time: {before: :end_time}
# validates :end_time, time: {after: :start_time}
def add_loyalty_points
self.user.loyalty_points += self.seats * 10
self.user.save
end
def remove_loyalty_points
if self.user.loyalty_points >= self.seats * 10
self.user.loyalty_points -= self.seats * 10
else
self.user.loyalty_points = 0
end
self.user.save
end
def send_confirmation_email
self.user.send_confirmation
end
def reservation_should_not_outside_operating_hours
return if (start_time.nil?) or (end_time.nil?)
if start_time.hour < 11 or end_time.hour > 20 or (end_time.hour == 20 && (end_time.min > 0 || end_time.second > 0))
errors[:base] << "Reservation timeslot cannot outside operating hours [11AM - 8 PM]"
false
else
true
end
end
def reservation_should_not_exceed_restaurant_capacity
return if [start_time, end_time, restaurant.capacity].all?
reserved_seats = restaurant.reservations.where("start_time = ? AND end_time = ?", start_time,end_time).sum(:seats)
if self.restaurant.capacity - reserved_seats >= seats
true
else
errors[:base] << "There are not enough seats available at this time slot: you order #{seats}, but only #{restaurant.capacity - reserved_seats} are availabled"
false
end
end
def reservation_only_last_for_an_hour
if ( !end_time.nil? && !start_time.nil? && (self.end_time - self.start_time).to_i - 3600> 0)
errors .add(:duration_error, "the duration for a reservation should not last more than 1 hour")
false
else
true
end
end
end

Resources