Agile Web Development on Rails. 10.4 -undefined method `price' for nil:NilClass - ruby

I am stuck here and it seems that there is no answer anywhere online. The exercise says:
Create a migration that copies the product price into the line item, and change the add_product method in the Cart model to capture the price whenever a new line item is created.
My code:
class AddPriceToLineItem < ActiveRecord::Migration
def self.up
add_column :line_items, :price, :decimal
say_with_time "Updating prices..." do
LineItem.find(:all).each do |li|
li.update_attribute :price, li.product.price
end
end
end
def self.down
remove_column :line_items, :price
end
end
I also tried:
class AddPriceToLineItem < ActiveRecord::Migration
def self.up
add_column :line_items, :price, :decimal
LineItem.all.each do |li|
li.price = li.product.price
end
end
def self.down
remove_column :line_items, :price
end
end
I keep getting this error:
rake db:migrate
== AddPriceToLineItem: migrating =============================================
-- add_column(:line_items, :price, :decimal)
-> 0.0010s
-- Updating prices...
rake aborted!
An error has occurred, this and all later migrations canceled:
undefined method `price' for nil:NilClass
It is weird that it is saying undefined nil:nilClass, as price has just been defined in the line before.
Im using rails (3.2.1), ruby 1.9.3p125.
Anyone can help?

This errors means that you are calling price on something that is nil. So I'm pretty sure one of your LineItem does not have a product.

I would be more particular. In my case a had a cart_id and product_id were nil.
So I simple clean up the DB by
sqlite> DELETE FROM line_items WHERE id= bad_id";

Related

Rails 3 NoMethodError (undefined method `unserialized_value' for "--- []\n":String):

I am using Rails 3.2.13 and postgress.
I am getting below error only in production server
NoMethodError (undefined method `unserialized_value' for "--- []\n":String):
app/controllers/blogs_controller.rb:159:in `content_generators'
I am serializing Array to store it in db. Below is code.
Controller
class BlogsController < ApplicationController
def content_generators
#blog = Blog.find(params[:id])
#users = #blog.content_generators.map do |id|
User.find(id)
end
end
end
Model
class Blog < ActiveRecord::Base
serialize :post_access, Array
serialize :content_generators, Array
attr_accessible :post_access, :content_generators
end
Migration
class AddContentgeneratorsToBlog < ActiveRecord::Migration
def change
add_column :blogs, :content_generators, :string, :default => [].to_yaml
end
end
I have already used serialization. You can see post_access is serialized. And that works perfect.
But now when I added another column content_generators it starts breaking.
Thanks for your help in advance.
Since you are using postgresql I strongly recommend using the built in array functionality:
# Gemfile
gem 'postgres_ext'
class MyMigration
def change
add_column :my_table, :that_array_column, :text, array: true, default: []
end
end
Then remove the serialize calls in your model and that's it. PG serialized array's behave exactly the same as YAML serialized ones on the model, except the db supports some query methods on them.

NameError when assigning instance of model to reference property

I'm unable to assign a model instance to a reference property of another model. Relevant code is below:
module Blog::Models
class Post < Base; belongs_to :user, dependent: :destroy end
class User < Base; has_many :posts end
...
class BasicFields < V 1.0
def self.up
create_table User.table_name do |t|
...
end
create_table Post.table_name do |t|
...
t.references :user
end
end
...
end
end
module Blog::Controllers
...
class PostEditN
...
def post(post_num)
#post = Post.find(post_num)
#user = User.find(#input.user)
...
#post.user = #user # Error thrown: NameError at /post/edit/1 uninitialized constant User
# #post.user_id = #user.id << This is my currently working solution
#post.save
redirect PostN, post_num
end
end
...
end
...
When I assign something to #post.user using Camping in console mode, it is successful, but I can't seem to accomplish the same behavior in the controller otherwise. I made do by simply assigning the #user.id to the user_id property of the Post instance. However, I would like to figure out why the alternate method works in the Camping console and not when I'm simply running the webserver.
My best guess is that this is a problem with namespaces. In the code you show Useris actually Blog::Models::User. In your controller the context is Blog::Controllers. Have you tried changing the code in the controller to?
#post = Blog::Models::Post.find(post_num)
#user = Blog::Models::User.find(#input.user)
...
I was able to resolve my issue. Seems when I was creating new Post records, I was not initializing the User. Thus, when assigning #post.user it would complain that the user property was uninitialized. The only problem I see is that an operation was attempted to be made on an oprhan Post record, which is invalid data according to the relationship with User.

Adding a Hash to an ActiveRecord Hash

I read How to add a Hash object to an ActiveRecord class? Tried but migration fails and followed the format there.
I tried:
class AddTestResponsesToSurveys < ActiveRecord::Migration
def change
add_column :surveys, :responses, :hash
end
end
When I run rake db:migrate, I get an error in my schema.rb file that says:
# Could not dump table "surveys" because of following StandardError
# Unknown type 'hash' for column 'responses'
What am I doing wrong?
generate migration with column type text
class AddTestResponsesToSurveys < ActiveRecord::Migration
def change
add_column :surveys, :responses, :text
end
end
And in your Survey model, add this
serialize :responses, Hash

How can I create a field using the id from the same row in ActiveRecord Ruby

-----UPDATE-----
Well, seems that the problem was in last.id. When database is created works OK, but when not fails. Now the question is different: How can I create a field using the id from the same row?
--------ORIGINAL------
I'm working with active record in pure ruby (without Rails), and I'm literally getting crazy with this.
This is my code
class Enviroment < ActiveRecord::Base
#self.table_name = 'enviroments'
self.connection.create_table(:enviroments, :force=>true) do |t|
t.column :name, :string, :default=>'env-'+ (last.id-1).to_s
t.column :ssh, :string, :default=>nil
end
end
and here the error:
ActiveRecord::StatementInvalid: Could not find table 'enviroments'
from /usr/lib/ruby/gems/1.8/gems/activerecord-3.2.3/lib/active_record/connection_adapters/sqlite_adapter.rb:465:in `table_structure'
if I useself.table_name = 'enviroments' still not working. I've updated the gems and neither.
I'm newbie with ruby and databases, but I can't understand this problem, I think this same code worked in the past :S
Your code to create the table (very odd to have that in the model by the way) is calling last.id, and of course to call last the table must already exist.
Because you're passing :force => true to create_table you'll actually destroy the table if it already exists.
You could probably make your code work if you stashed the value of last.id in a local variable before the call to create_table but I don't understand why you are creating tables like this.
Finally, this was my solution:
class Enviroment < ActiveRecord::Base
after_create :create_default
private
def create_default
if name == nil
s = 'env-' + self.id.to_s
self.name = s
self.save
end
end
end
class CreateSchema < ActiveRecord::Migration
create_table(:enviroments, :force=>true) do |t|
t.column :name, :string, :default=>nil
t.column :ssh, :string, :default=>nil
end

Rails3: Nested model - child validates_with method results in "NameError - uninitialized constant [parent]::[child]"

Consider the following parent/child relationship where Parent is 1..n with Kids (only the relevant stuff here)...
class Parent < ActiveRecord::Base
# !EDIT! - was missing this require originally -- was the root cause!
require "Kid"
has_many :kids, :dependent => :destroy, :validate => true
accepts_nested_attributes_for :kids
validates_associated :kids
end
class Kid < ActiveRecord::Base
belongs_to :parent
# for simplicity, assume a single field: #item
validates_presence_of :item, :message => "is expected"
end
The validates_presence_of methods on the Kid model works as expected on validation failure, generating a final string of Item is expected per the custom message attribute supplied.
But if try validates_with, instead...
class Kid < ActiveRecord::Base
belongs_to :parent
validates_with TrivialValidator
end
class TrivialValidator
def validate
if record.item != "good"
record.errors[:base] << "Bad item!"
end
end
end
...Rails returns a NameError - uninitialized constant Parent::Kid error following not only an attempt to create (initial persist) user data, but also when even attempting to build the initial form. Relevant bits from the controller:
def new
#parent = Parent.new
#parent.kids.new # NameError, validates_* methods called within
end
def create
#parent = Parent.new(params[:parent])
#parent.save # NameError, validates_* methods called within
end
The error suggests that somewhere during model name (and perhaps field name?) resolution for error message construction, something has run afoul. But why would it happen for some validates_* methods and not others?
Anybody else hit a wall with this? Is there some ceremony needed here that I've left out in order to make this work, particularly regarding model names?
After a few hours away, and returning fresh -- Was missing require "Kid" in Parent class. Will edit.

Resources