unable to specify value in ActiveRecord call (Ruby, Sinatra, not Rails) - ruby

I have a reference to a Model object called Admin which has a field called id. The object property is accessible in the puts line. I now need to pass in that ID into an ActiveRecord call to create another object (where it serves as foreign key) as follows but it throws an exception copied below (the admin.id does not get picked up in the Bill.create call):
admin = Admin.find_by(email:email)
puts "admin id #{admin.id}" # this gets printed with correct value
bill = Bill.create(admin_id: admin.id, body: body)
Exception:
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/attribute_assignment.rb:59:in `rescue in _assign_attribute': unknown attribute 'admin_id' for Bill. (ActiveRecord::UnknownAttributeError)
from /usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/attribute_assignment.rb:54:in `_assign_attribute'
from /usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/attribute_assignment.rb:41:in `block in assign_attributes'
from /usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/attribute_assignment.rb:35:in `each'
from /usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/attribute_assignment.rb:35:in `assign_attributes'
from /usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/core.rb:564:in `init_attributes'
from /usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/core.rb:281:in `initialize'
from /usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/inheritance.rb:61:in `new'
from /usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/inheritance.rb:61:in `new'
from /usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/persistence.rb:33:in `create'
from test.rb:34:in `<main>'
ActiveRecord migration for the Bills model:
def up
create_table :bills do |t|
t.integer :admin_id
t.text :body
end
add_foreign_key :bills, :admins
end
Thank you in advance for sharing insights on what I am doing wrong.

Per my comment, you should really make this into a belongs_to relation, here's the refactored migration (using latest Rails 4 syntax):
class CreateBills < ActiveRecord::Migration
def change
create_table :bills do |t|
t.references :admin
t.text :body
end
end
end
add these relations to the models:
class Admin < ActiveRecord::Base
has_many :bills
end
class Bill < ActiveRecord::Base
belongs_to :admin
end
and the code for creating a bill associated with an admin:
admin = Admin.find_by(email:email)
puts "admin id #{admin.id}" # this gets printed with correct value
bill = admin.bills.create(body: body)

Related

ArgumentError: wrong number of arguments (1 for 0) when using afer_save

ArgumentError: wrong number of arguments (1 for 0)
from /Users/Castillo/Desktop/gainer/app/models/status.rb:13:in `update_remaining_nutrients'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:507:in `block in callback'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:504:in `each'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:504:in `callback'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:352:in `add_to_target'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:495:in `block in concat_records'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:493:in `each'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:493:in `concat_records'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:134:in `block in concat'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:149:in `block in transaction'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/transactions.rb:208:in `transaction'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:148:in `transaction'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:134:in `concat'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_proxy.rb:116:in `<<'
from /Users/Castillo/Desktop/gainer/app/models/user.rb:65:in `eat'
from (irb):31
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/railties-3.2.11/lib/rails/commands/console.rb:47:in `start'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/railties-3.2.11/lib/rails/commands/console.rb:8:in `start'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/railties-3.2.11/lib/rails/commands.rb:41:in `<top (required)>'
I want to call the update_remaining_nutrients method on status.rb whenever a meal is "eaten" by the user. When I call User.first.eat(Meal.first) I get the ArgumentError. Not sure why because I'm not passing the after_add method any arguments?
user.rb
class User < ActiveRecord::Base
has_many :meals
has_many :statuses
def eat(meal)
statuses.last.meals<<meal
end
end
status.rb
class Status < ActiveRecord::Base
attr_accessible :remaining_calories, :remaining_carbs, :remaining_protein, :weight, :user_id
belongs_to :user
has_many :meals, after_add: :update_remaining_nutrients
after_save :update_users_weight , :if => Proc.new {|a| a.weight_changed?}
def update_users_weight
self.user.weight.update_attributes(weight: self.weight)
end
def update_remaining_nutrients
puts "It Works!!!!!"
end
end
meal.rb
class Meal < ActiveRecord::Base
attr_accessible :name, :description, :clean_up, :homemade, :prep_time, :user_id, :status_id
belongs_to :user
belongs_to :status
has_many :ingredient_meals
has_many :ingredients, :through => :ingredient_meals
end
If you have a look at the Association callbacks section of the docs, you'll see this example:
class Project
has_and_belongs_to_many :developers, after_add: :evaluate_velocity
def evaluate_velocity(developer)
...
end
end
That's not the has_many relationship that you have but it is close enough. If you look at the evaluate_velocity method, you'll see that the developer in question is passed as an argument by the :after_add callback. You're getting an ArgumentError about your update_remaining_nutrients being called with one argument when it doesn't want any and that matches what the the example suggests would happen.
Try this:
def update_remaining_nutrients(meal)
# Do interesting things with `meal` in here...
end

Trouble getting the timestamp attributes for Active Record

So I'm trying to get the updated at attribute for my database object, but it's not working. I can get the other attributes but not the updated_at or created_at attributes. I'm also noticing that I can't get the id attribute as well. It seems as if anything I haven't declared in my Pocket.new does not exist. Here's my code:
By the way, I'm not using rails. I'm using sinatra-activerecord and sinatra.
Model
class Pocket < ActiveRecord::Base
def retrieve(consumer_key)
url = "get/"
pocket_url = join_url(url)
# time = Time.now.to_i
token = self.token
puts consumer_key
puts self
puts time = self.updated_at #.to_i this is where it happens.
options = {
:access_token => token,
:consumer_key => consumer_key,
:since => (time if defined? time)
}
hello = RestClient.post pocket_url, options
# JSON.parse(hello)
end
Controller
get '/auth/pocket/callback' do
[…]
pocket = Pocket.new(token: #token, user: #user)
DB migration
class CreatePocket < ActiveRecord::Migration
def up
create_table :pockets do |t|
t.string :user
t.string :token
t.timestamps
end
end
def down
drop_table :users
end
end
id, created_at, and updated_at are going to be nil for un-persisted objects, which is what you have by just calling .new and not saving the object yet.
Those attributes will be sent as soon as you call .save (assuming there are no validation errors).
Actually that isn't 100% true. updated_at will not be set on the first create / save, but it will be set on subsequent saves.

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

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";

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

Why am I getting the error "undefined method `name' for" in a Formtastic / haml view where "name" is a property on the model?

This is probably something stupid, but I don't know nearly enough about rails & ruby to see it. I have the following schema & view but I am getting the error mentioned below. Business inherits from a Devise Account so thats where the email & password come from.
Any help would be greatly appreciated, thanks!
schema:
create_table "businesses", :force => true do |t|
t.string "name"
t.string "street"
t.string "city"
t.string "zip"
t.datetime "created_at"
t.datetime "updated_at"
end
View:
#registrationForm
-semantic_form_for(resource, :as => resource_name, :url=> registration_path(resource_name)) do |f|
=f.input :name
=f.input :email
=f.input :password
=f.input :password_confirmation
=f.buttons
Error:
undefined method 'name' for
<Business:0x000000052690f8 > Extracted source (around line #3):
Edit
Controller
class BusinessesController < Devise::RegistrationsController
respond_to :html
def new
super
#business = Business.new
end
end
Routes.rb
devise_for :accounts
devise_for :businesses, :controllers => { :registrations => "businesses" }
Model
class Business < Account
end
console after reloading schema
k = Business.new ( :name =>"test" )
^
(irb):1: syntax error, unexpected ')', expecting $end
from /home/chance/.rvm/gems/ruby-1.9.2-p180#global/gems/railties-3.0.5/lib/rails/commands/console.rb:44:in `start'
from /home/chance/.rvm/gems/ruby-1.9.2-p180#global/gems/railties-3.0.5/lib/rails/commands/console.rb:8:in `start'
from /home/chance/.rvm/gems/ruby-1.9.2-p180#global/gems/railties-3.0.5/lib/rails/commands.rb:23:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
You have a table named 'accounts' and a table named 'businesses'.
Account is being made by devise, and has all its attributes, and points to the 'accounts' table.
Business inherits from Account, and therefore is using Rails' STI (single table inheritance) features. It therefore points to the 'accounts' table as well.
If you were to have Business < ActiveRecord::Base it would point to your 'businesses' table. ActiveRecord's STI mechanism is very strange.
I think you need to think more about how you want your data model to work. Perhaps Business should belong_to :account and have an according :account_id.
Either that or you could add all the 'businesses' columns to the accounts table.
Try to load your schema again
rake db:schema:load

Resources