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

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

Related

Polymorphism error in my model

I'm trying to make a polymorphic model for my reservations.
A reservation can be from a USER to a ROOM, or from a USER to a MENU.
Those are my classes and migrations.
class Room < ActiveRecord::Base
belongs_to :user
has_many :reservations, as: reservable
class Menu < ActiveRecord::Base
belongs_to :user
has_many :reservations, as: reservable
class Reservation < ActiveRecord::Base
belongs_to :user
belongs_to :reservable, polymorphic: true
end
In my controller I'm trying to access my reservations thru:
def your_trips
#trips = current_user.reservations
end
But I'm getting the error:
NameError in PagesController#home
undefined local variable or method `reservable' for # <Class:0x000000054c8308> Did you mean? reset_table_name
Extracted source (around line #4):
Rails.root: /home/ubuntu/workspace
Application Trace | Framework Trace | Full Trace
app/models/room.rb:4:in `<class:Room>'
app/models/room.rb:1:in `<top (required)>'
app/controllers/pages_controller.rb:3:in `home'
Does anyone have ideas why?

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

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)

Undefined method error while running rspec test

All,
I am getting the following undefined method errors below when running my rspec tests. When I have gotten this error before I had a method misspelled or my order of execution caused it. I checked both along with some other posts on StackOverflow, but nothing helped. Can anyone offer any guidance?
Rspec Failures:
FFFF
Failures:
1) Post vote methods #up_votes counts the number of votes with value = 1
Failure/Error: expect(#post.up_votes ).to eq(3)
NoMethodError:
undefined method `up_votes' for #<Post:0x007fe92f381a38>
# ./spec/models/post_spec.rb:14:in `block (4 levels) in <top (required)>'
2) Post vote methods #down_votes counts the number of votes with values = -1
Failure/Error: expect(#post.down_votes ).to eq(2)
NoMethodError:
undefined method `down_votes' for #<Post:0x007fe92a18c228>
# ./spec/models/post_spec.rb:20:in `block (4 levels) in <top (required)>'
3) Post vote methods #points returns the sum of all down and up votes
Failure/Error: expect(#post.points ).to eq(1) # 3 - 2
NoMethodError:
undefined method `points' for #<Post:0x007fe92986c620>
# ./spec/models/post_spec.rb:26:in `block (4 levels) in <top (required)>'
4) Vote validations value validation only allows -1 or 1 as values
Failure/Error: expect(#post.up_votes).to eq((-1) || eq(1))
NoMethodError:
undefined method `up_votes' for nil:NilClass
# ./spec/models/vote_spec.rb:5:in `block (4 levels) in <top (required)>'
Post_rspec
require 'rails_helper'
describe Post do
describe "vote methods" do
before do
#post = Post.create(title: 'Post title', body: 'Post bodies must be pretty long.')
3.times { #post.votes.create(value: 1) }
2.times { #post.votes.create(value: -1) }
end
describe '#up_votes' do
it "counts the number of votes with value = 1" do
expect(#post.up_votes ).to eq(3)
end
end
describe '#down_votes' do
it "counts the number of votes with values = -1" do
expect(#post.down_votes ).to eq(2)
end
end
describe '#points' do
it "returns the sum of all down and up votes" do
expect(#post.points ).to eq(1) # 3 - 2
end
end
end
end
vote_spec file
describe Vote do
describe "validations" do
describe "value validation" do
it "only allows -1 or 1 as values" do
expect(#post.up_votes).to eq((-1) || eq(1))
end
end
end
end
Post.rb
class Post < ActiveRecord::Base
has_many :comments, dependent: :destroy
has_many :votes
has_one :summary
belongs_to :user #means the post table has the user table's primary key in it
belongs_to :topic
mount_uploader :avatar, AvatarUploader
default_scope {order('created_at DESC')}
validates :title, length: {minimum: 5}, presence: true
validates :body, length: {minimum: 20}, presence: true
def markdown_title
(render_as_markdown).render(self.title).html_safe
end
def markdown_body
(render_as_markdown).render(self.body).html_safe
end
private
def render_as_markdown
renderer = Redcarpet::Render::HTML.new
extensions = {fenced_code_blocks: true}
redcarpet = Redcarpet::Markdown.new(renderer, extensions)
#return redcarpet
end
end
For the post_spec.rb errors, check the Post model (see file app/models/post.rb) has the following methods defined in it:
up_votes
down_votes
points
Consider including the code for post.rb in your original question too.
For the vote_spec.rb errors, there is no #post variable, it will be nil. This error message hints at this:
Failure/Error: expect(#post.up_votes).to eq((-1) || eq(1))
NoMethodError: undefined method `up_votes' for nil:NilClass

Ruby: Join with ActiveRecord using non-standard schema

I'm struggling to make a join between tables work on a non-standard schema. I know the proper way of doing it would be migrating the schema and using the ActiveRecord convention but as long as I'm using this to consume data for testing purposes, that's not an option.
The join can be made using the key 'AGREEMENT_TYPE_ID' that exists in both tables.
I have the following in the models definition:
class Agreements < ActiveRecord::Base
self.table_name = 'AGREEMENTS'
self.primary_key = 'AGREEMENT_ID'
has_one :Agreement_Types, :foreign_key => 'AGREEMENT_TYPE_ID'
end
class Agreement_Types < ActiveRecord::Base
belongs_to :Agreements
self.table_name = 'AGREEMENT_TYPES'
self.primary_key = 'AGREEMENT_TYPE_ID'
end
This is the instantiation:
puts Agreements.joins(:Agreement_Types)
This is the output:
C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/inheritance.rb:111:in `compute_type': uninitialized constant Agreements
::AgreementTypes (NameError)
from C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/reflection.rb:172:in `klass'
from C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/associations/join_dependency/join_association.rb:40:in `initialize'
from C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/associations/join_dependency.rb:152:in `new'
from C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/associations/join_dependency.rb:152:in `build_join_association'
from C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/associations/join_dependency.rb:115:in `build'
from C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/associations/join_dependency.rb:123:in `block in build'
from C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/associations/join_dependency.rb:122:in `each'
from C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/associations/join_dependency.rb:122:in `build'
from C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/associations/join_dependency.rb:18:in `initialize'
from C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/relation/query_methods.rb:358:in `new'
from C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/relation/query_methods.rb:358:in `build_joins'
from C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/relation/query_methods.rb:266:in `build_arel'
from C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/relation/query_methods.rb:260:in `arel'
from C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/relation.rb:171:in `exec_queries'
from C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/relation.rb:160:in `block in to_a'
from C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/explain.rb:25:in `logging_query_plan'
from C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/relation.rb:159:in `to_a'
from C:in `to_ary'
from prueba.rb:29:in `puts'
from prueba.rb:29:in `puts'
from prueba.rb:29:in `<main>'
I find a solution that works:
class AgreementType < ActiveRecord::Base
self.table_name = 'AGREEMENT_TYPES'
self.primary_key = 'AGREEMENT_TYPE_ID'
belongs_to :Agreement
end
class Agreement < ActiveRecord::Base
self.table_name = 'AGREEMENTS'
self.primary_key = 'AGREEMENT_ID'
has_one :AgreementType, :primary_key => 'AGREEMENT_TYPE_ID', :foreign_key => 'AGREEMENT_TYPE_ID'
end

Activerecord in rails 3.2 within an engine throws NameError: uninitialized constant when using accepts_nested_attributes_for

I am building a rails engine. I have the following two model classes:
module LandingPageEng
class LandingPage < ActiveRecord::Base
attr_protected # just for debugging right now
has_many :slide_show_images, :dependent => :destroy
accepts_nested_attributes_for :slide_show_images, allow_destroy: true
end
end
The second class is:
module LandingPageEng
class SlideShowImage < ActiveRecord::Base
attr_accessible :image, :landing_page_id
belongs_to :landing_page
validates :image, :presence => true
end
end
The tables associated with them are landing_page_eng_landing_page and landing_page_eng_slide_show_image.
When I run the following in the console I get the error NameError: uninitialized constant SlideShowImage.
1.9.3-p194 :001 > LandingPageEng::LandingPage.new({"title"=>"wd", "tagline"=>"wed", "slide_show_images"=>{"_destroy"=>""}})
NameError: uninitialized constant SlideShowImage
from /Users/martinjlogan/.rvm/gems/ruby-1.9.3-p194/gems/activesupport- 3.2.6/lib/active_support/inflector/methods.rb:229:in `block in constantize'
from /Users/martinjlogan/.rvm/gems/ruby-1.9.3-p194/gems/activesupport-3.2.6/lib/active_support/inflector/methods.rb:228:in `each'
from /Users/martinjlogan/.rvm/gems/ruby-1.9.3-p194/gems/activesupport-3.2.6/lib/active_support/inflector/methods.rb:228:in `constantize'
from /Users/martinjlogan/.rvm/gems/ruby-1.9.3-p194/gems/activesupport-3.2.6/lib/active_support/core_ext/string/inflections.rb:54:in `constantize'
<snip>
I have been banging my head on this and can't figure it out. Any help much appreciated.
I don't have a Rails 3 setup with engines to test this on quickly but I think the issue is with your has_many configuration; it's looking for a class that's named SlideShowImage but your class name is LandingPageEng::SlideShowImage.
I believe adding a :class_name option to your has_many will fix this.
http://railsapi.com/doc/rails-v3.0.8rc1/classes/ActiveRecord/Associations/ClassMethods.html#M004956

Resources