Rails: Migration default value cannot be overwritten by create methods - ruby-on-rails

I have an migration for new table:
class CreateContentCategories < ActiveRecord::Migration
def change
create_table :content_categories do |t|
t.string :title, default: '', null: false
t.timestamps null: false
end
end
end
When I try to create or find_or_create_by new records with options:
def self.assign_titles_to_app(titles, app)
# somewhere inside ( class scope )
title = 'movies'
content_category = find_by_title(title) || create(title: title)
puts "title: #{title} category: #{content_category.inspect}"
active record doesn't use my title
title: movies category: #<ContentCategory id: 1050, title: "", created_at: "2015-06-25 15:42:57", updated_at: "2015-06-25 15:42:57">
the same result for find_or_create_by:
title = 'movies'
content_category = find_or_create_by(title: title)
title: movies category: #<ContentCategory id: 1062, title: "", created_at: "2015-06-25 15:45:25", updated_at: "2015-06-25 15:45:25">
Documentation said:
:default - The column's default value. Use nil for NULL.
What is going wrong? how to fix it?
Info:
rails 4.2.1
activerecord 4.2.1
ruby 2.2.2
Update: I forgot about attr_accessible:
class ContentCategory < ActiveRecord::Base
# attr_accessible :title <- I forgot to add this line, oh
end

There's nothing wrong with your code, maybe you need to restart your app (and spring) or maybe the problem is in code that you haven't shown. Just to demonstrate, I added your exact code to a vanilla 4.2 app and:
[9] pry(main)> ContentCategory.assign_titles_to_app 1, 2
ContentCategory Load (0.2ms) SELECT "content_categories".* FROM "content_categories" WHERE "content_categories"."title" = ? LIMIT 1 [["title", "movies"]]
(0.1ms) begin transaction
SQL (0.7ms) INSERT INTO "content_categories" ("title", "created_at", "updated_at") VALUES (?, ?, ?) [["title", "movies"], ["created_at", "2015-06-25 16:31:59.192793"], ["updated_at", "2015-06-25 16:31:59.192793"]]
(0.5ms) commit transaction
title: movies category: #<ContentCategory id: 1, title: "movies", created_at: "2015-06-25 16:31:59", updated_at: "2015-06-25 16:31:59">
=> nil

Related

Rails 4 ActiveRecords: Save multiple records at once with validation

Hi i have the following situation. I can save this array of hashes
products = [{
:name=> 0,
:key => 12345,
:label => "test1",
},{
:name=> 0,
:key => 12145,
:label => "test",
}]
at once with
products.map {|p| Product.new(p).save }
or
Product.create(products)
Product.create!(products)
but the all my uniqueness validations like
validates :key, presence: true, uniqueness: true
are ignored, using the rails console. I am able to save this hash multiple times. Does anyone has some advice? Thanks in advance!
SOLUTION
As simple as restarting my rails console. After that my logs look like the logs from #Akadisoft.
Also using this way:
products.map {|p| Product.new(p).save }
which return an array with booleans [false,true] either the record was saved or not, which is nice for further evaluation.
I have tried your exact solution and everything works as intented..
The first time I ran the command Product.create(products) I have the following result
=> #<ActiveRecord::Relation [#<Product id: 1, key: "12345", name: 0, label: "test1", created_at: "2015-12-09 19:21:01", updated_at: "2015-12-09 19:21:01">, #<Product id: 2, key: "12145", name: 0, label: "test", created_at: "2015-12-09 19:21:01", updated_at: "2015-12-09 19:21:01">]>
We can see that it created two products (id:1 and id:2).
Now the second I run the exact same command here is the result:
[#<Product id: nil, key: "12345", name: 0, label: "test1", created_at: nil, updated_at: nil>, #<Product id: nil, key: "12145", name: 0, label: "test", created_at: nil, updated_at: nil>]
irb(main):015:0>
We can see the ID is nil because it didn't save the products. I can also see in the console output that DB transaction were rollbacked.
I tried this on console and it only added one record.
14:42 $ rails c
Loading development environment (Rails 4.2.5)
2.2.2 :001 > products = [{:key =>1},{:key=>1}]
=> [{:key=>1}, {:key=>1}]
2.2.2 :002 > products.map {|p| Product.new(p).save }
(0.1ms) begin transaction
Product Exists (0.1ms) SELECT 1 AS one FROM "products" WHERE "products"."key" = 1 LIMIT 1
SQL (0.8ms) INSERT INTO "products" ("key", "created_at", "updated_at") VALUES (?, ?, ?) [["key", 1], ["created_at", "2015-12-09 19:42:32.488255"], ["updated_at", "2015-12-09 19:42:32.488255"]]
(0.4ms) commit transaction
(0.0ms) begin transaction
Product Exists (0.1ms) SELECT 1 AS one FROM "products" WHERE "products"."key" = 1 LIMIT 1
(0.0ms) rollback transaction
=> [true, false]
2.2.2 :003 > Product.all
Product Load (0.2ms) SELECT "products".* FROM "products"
=> #<ActiveRecord::Relation [#<Product id: 1, key: 1, created_at: "2015-12-09 19:42:32", updated_at: "2015-12-09 19:42:32">]>

Rails Updating attribute always inserts nil

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

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