Why do I get missing method in the following situation? - ruby-on-rails

I have two problems but I'll post them as 2 different questions. Let's start with the first one.
class Order < AbstractOrder
def update_status
self.all_created.each do |order|
order.status = :in_progress
order.save
end
end
end
In my specs when I try to call
Order.update_status
I get an error saying :
Failure/Error: Order.update_status
NoMethodError:
undefined method `update_status' for #<Class:0x00000103f256a8>
# ./spec/models/order_spec.rb:17:in `block (3 levels) in <top (required)>'
Finished in 0.10439 seconds
3 examples, 1 failure
Why? I thought this was a class method not an instance method. If I create an order and do order.update_status it works. What is wrong and how do I fix it?

To bind the method to the class object you need to define it as self.update_status, and the self before all_created shouldn't be necessary:
class Order < AbstractOrder
def self.update_status
all_created.each do |order|
order.status = :in_progress
order.save
end
end
end

Related

Rails4 Minitest | using a shared reusable object

I am getting the following error when I run rake test with minitest:
$ rake test
DL is deprecated, please use Fiddle
Run options: --seed 55196
# Running:
.EE
Finished in 0.950979s, 3.1546 runs/s, 1.0515 assertions/s.
1) Error:
CategoryTest#test_invalid_without_name:
NoMethodError: undefined method `name=' for nil:NilClass
test/models/category_test.rb:14:in `test_invalid_without_name'
2) Error:
CategoryTest#test_invalid_without_long_name:
NoMethodError: undefined method `name=' for nil:NilClass
test/models/category_test.rb:19:in `test_invalid_without_long_name'
3 runs, 1 assertions, 0 failures, 2 errors, 0 skips
category_test.rb
require "test_helper"
class CategoryTest < ActiveSupport::TestCase
def category
#category = Category.new(name:'Homey')
end
def test_valid
assert category.valid?
end
def test_invalid_without_name
#category.name = nil
refute #category.valid?
end
def test_invalid_without_long_name
#category.name = "A"
refute #category.valid?
end
end
In my models I have the category.rb
class Category < ActiveRecord::Base
validates :name, presence: true
end
It seems that I have a nil class even though I am instantiating it in my category method. Any idea what is happening. I am just getting started using Minitest so not sure what is going on.
Do
def category
#category ||= Category.new(name:'Homey')
end
Then only use category not #category
Using a getter this way will set the instance var if it didnt exist before or retrieve the existing value
There are lots of ways to approach this, but the most straightforward would be to replace the category method with:
def setup
#category = Category.new(name:'Homey')
end

Assert Redis publication

I am writing a spec for an after_create callback. The spec looks like this:
it 'broadcasts creation' do
message = Message.create(body: 'foo')
expect(Redis.any_instance).to have_received(:publish)
end
My Message model looks like this:
class Message < ActiveRecord::Base
after_create -> { publish(:create) }
private
def publish(name)
Redis.new.publish(
self.class.inferred_channel_name,
json(action)
)
Redis.new.publish(
inferred_channel_name_for_single_record,
json(action)
)
puts 'published!'
end
end
I know that the callback runs because I am printing 'published' at the end, and I have verified that Redis indeed publishes something twice.
Nonetheless, my spec fails with the following message:
1) Message Methods #entangle without options broadcasts creation
Failure/Error: expect(Redis.any_instance).to have_received(:publish)
unstubbed, expected exactly once, not yet invoked: #<AnyInstance:Redis>.publish(any_parameters)
# ./spec/models/message_spec.rb:20:in `block (5 levels) in <top (required)>'
I am using bourne with mocha to use the have_received matcher.
How can I get this test to pass?
Create a mock for Redis and stub out the class and instance methods — new and publish, respectively.
it "broadcasts creation" do
redis = stub_redis
Message.create(body: "foo")
expect(redis).to have_received(:publish).twice
end
def stub_redis
mock("redis").tap do |redis|
redis.stubs(:publish)
Redis.stubs(:new).returns(redis)
end
end
You could try using the expect_any_instance_of mock.
it 'broadcasts creation' do
expect(Redis.any_instance).to receive(:publish).twice
message = Message.create(body: 'foo')
end
https://www.relishapp.com/rspec/rspec-mocks/v/3-2/docs/working-with-legacy-code/any-instance

expecting a hash rather than an instance

I have this error
ArgumentError (wrong number of arguments (1 for 0)):
lib/law/production.rb:20:in `clone'
lib/law/production.rb:20:in `clone_law'
lib/law/production.rb:11:in `initialize'
app/controllers/laws_controller.rb:86:in `new'
app/controllers/laws_controller.rb:86:in `prod_law'
app/controllers/laws_controller.rb:44:in `create'
when using this
module Law
class Production
attr_accessor :law
attr_accessor :creator
def initialize(law,current_user)
#law = law
#creator = current_user
clone_law
end
def current__user
User.find_by_authentication_token(session[:_csrf_token])
end
def clone_law
clone(#law)
end
end
end
where clone, create, prod_law are some methods
I assume Rails is expecting a hash but I don't understand why
Firstly, clone is a standard Ruby method.
Secondly, it expects no arguments at
all (as error message says), it should be called on the object you want to clone, like this:
#law.clone

RSpec Shoulda validates_presence_of nilClass

When I use Shoulda's validates_presence_of, it stumbles on a before_validation callback.
before_validation :set_document, :set_product, :set_price
I'm trying to get this spec to pass:
it { should validate_presence_of(:quantity).with_message("Please a quantity.") }
I have database defaults of 0 for a line item's quantity, unit_price, tax_rate, and price. Before a line item is validated I compute the price from the other attributes in case they have changed.
I get this error, and similar errors, for all of the attributes involved in this computation:
3) LineItem
Failure/Error: it { should validate_presence_of(:quantity).with_message("Please a quantity.") }
NoMethodError:
undefined method `*' for nil:NilClass
# ./app/models/line_item.rb:153:in `total_price'
# ./app/models/line_item.rb:223:in `set_price'
# ./spec/models/line_item_spec.rb:32:in `block (2 levels) in <top (required)>'
My callback, set_price, is very simple:
def set_price
self.price = total_price
end
And the total_price method is very simple as well:
def total_price
quantity * unit_price * (1 + tax_rate/100)
end
I'd appreciate any help with this one as I'm completely stumped. I did see some people post about custom validation methods. This seems so basic I can't figure it out how to proceed.
Since total_price runs before validation, quantity can be nil at the time the callback is executed. This is in fact what happens behind the scenes when the Shoulda matcher runs, which is why you get an error. It's trying to send the * method to quantity, which is nil.
Use after_validation or before_save instead.

Rails: "NoMethodError: undefined method `constructKDTree' for #<Class:0x00000104b1f760>"

Hi there I have 3 files in rails as follows:
1)Located at "app/controller/listings_controller.rb"
class ListingsController < ApplicationController
def index
#Construct kd Tree in memory
#tree = Listing.constructKDTree;
#tree.inspect
end
2) Located at app/models/listing.rb
require 'kd_tree.rb'
class Listing < ActiveRecord::Base
def constructKDTree
#contents = self.all
#kdTree = KDTree.new(#contents)
end
3) Located at app/models/kd_tree.rb
class KDTree
def initialize (db_listings)
'Initializing Tree'
end
end
Now I'm trying to test the method implementation for constructKDTree so I went to my rails console and tried the following commands:
1.9.2-p290 :001 > #lc = ListingsController.new
=> #<ListingsController:0x00000104f3e288 #_routes=nil, #_action_has_layout=true, #_headers={"Content-Type"=>"text/html"}, #_status=200, #_request=nil, #_response=nil>
1.9.2-p290 :002 > #lc.index
But I get this error:
NoMethodError: undefined method `constructKDTree' for #<Class:0x00000104b1f760>
from /Users/AM/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.1/lib/active_record/dynamic_matchers.rb:50:in `method_missing'
from /Users/AM/Documents/RailsWS/cmdLineWS/Businesses/app/controllers/listings_controller.rb:20:in `index'
from (irb):2
from /Users/AM/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.2.1/lib/rails/commands/console.rb:47:in `start'
from /Users/AM/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.2.1/lib/rails/commands/console.rb:8:in `start'
from /Users/AM/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.2.1/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
What am I doing wrong?
You defined constructKDTree as an instance method on Listing. Thus the method is only available on instances of the class but nit the class itself.
Depending on what you actually want to achieve, you can make the method a class method like it's done in the following code, or you could create a new instance of the Listing class and call the method on the instance.
class Listing < ActiveRecord::Base
def self.constructKDTree
#contents = self.all
#kdTree = KDTree.new(#contents)
end
end
However looking at the code you have there, you probably want to do the latter and create a new instance of the class:
listing = Listing.new
#tree = listing.constructKDTree
This is a call to a class method:
#tree = Listing.constructKDTree
This is a definition of an instance method:
def constructKDTree
#contents = self.all
#kdTree = KDTree.new(#contents)
end
You want constructKDTree to be a class method so you need to say this:
def self.constructKDTree
#...

Resources