Forbid mocking methods that are undefined on original object - ruby-on-rails-3

I want to ensure that my EventNotifier object catches and logs an exception to the Rails logger, so I writed the following rspec test using rspec-mocks:
describe EventNotifier do
before(:all) do
RSpec::Mocks::setup(self)
end
it 'logs exception on error' do
error = RuntimeError.new('simulated for tests')
EventDispatcher.should_receive(:dispatch).with('a message').and_raise(error)
Rails.logger.should_receive(:warning).with(error)
subject.notify('a message')
end
end
class EventDispatcher
def dispatch(message)
# stuff
end
end
class EventNotifier
def notify(message)
EventDispatcher.dispatch(message)
rescue RuntimeError => e
Rails.logger.warning(e)
end
end
The test passes with bells and whistles, but I did a big mistake. Can you spot it? Indeed, the Rails method to log a warning is warn, not warning. So this code will fail when used for real.
Is there a way to make rspec-mock forbid mocking methods that do not exist on the original object?
Another example where it can be useful: if I decide to rename EventDispatcher#dispatch as EventDispatcher#route, then the test still passes. If it was java, it would have failed at compilation because the interface has changed. With rspec-mock, I do not know how to make it fail automatically.

It will be possible with rspec-mocks 3.0 which introduces verifying doubles:
Verifying doubles are a stricter alternative to normal doubles that provide
guarantees about what is being verified. When using verifying doubles, RSpec
will check that the methods being stubbed are actually present on the
underlying object if it is available. Prefer using verifying doubles over
normal doubles.
So given these classes (examples taken from the spec):
class ConsoleNotifier
def notify(msg)
puts message
end
end
class User < Struct.new(:notifier)
def suspend!
notifier.notify("suspended as")
end
end
This example would pass because the method notify exists for a real ConsoleNotifier instance:
describe User, '#suspend!' do
it 'notifies the console' do
notifier = instance_double("ConsoleNotifier")
expect(notifier).to receive(:notify).with("suspended as")
user = User.new(notifier)
user.suspend!
end
end
If the notify method is renamed as publish, the example would fail because expectations are on the method notify and that method does not exist on target object.
# would make example fail
class ConsoleNotifier
def publish(msg)
puts message
end
end
If we add a color argument to the notify method, it will fail too because the method arity is incorrect in the expectation (wrong number of arguments).
class ConsoleNotifier
def notify(msg, color)
puts color + message
end
end
When putting expectations on class, like EventDispatcher.should_receive(:dispatch) or expect(EventDispatcher).to receive(:dispatch), the created double is named a partial double in rspec-mocks vocabulary.
To make partial doubles act like verifying doubles, the verify_partial_doubles configuration option must be set:
RSpec.configure do |config|
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
end
And it will automagically ensure that the EventDispatcher class has a dispatch method. So if this method is renamed, the test will fail, as expected!

Related

pygtk3 checking does signal exist

how can I learn this before connecting anything.
example
does_signal_exist(widget, signal):
pass
button = Gtk.Button()
does_signal_exist(button, "clicked") # returns True
does_signal_exist(button, "hello") # returns False
does_signal_exist(button, "unboxed") # returns False
does_signal_exist(button, "button-press-event") # returns True
There's a wondrous tool called 'manual' or 'reference'. Look for the Gtk-3.0 manual, and click on Classes, and look for Gtk.Button. Look for Signals. If not there you can do the same for the signals inherited from previous Objects.
Using help(button or even help(Gtk.Button) (inside Python3, either in interactive or in a program), you have access to all methods, and lots of other information about the class and the instance.
Using the manual mentioned above, check out the GiRepository module - these are functions which you can use to look inside Gtk, its classes and properties.
And you can just check if it works: Use try:/except: to check if you can actually connect to the signal/event you are interested in.
def does_signal_exist(gtkWidgetObj, sigTag):
try:
gtkWidgetObj.emit(sigTag)
return True
except:
return "unknown signal name" not in format_exc():

Ensuring genuine parameters doesn't trigger "You tried to assign already serialized content to value. This is disabled due to security issues."

I've created a form builder in rails that allows users to construct their own forms. Many of the form inputs supply straight strings back to Rails (e.g. a text field). Some provide arrays of values (like date choosers). Right now I'm storing the values for these in a serialised column. It works well, and lets me re-display the custom forms when an error occurs with minimal effort. The problem is that someone entered:
--------
into a text field and ActiveRecord raised an error saying: You tried to assign already serialized content to value. This is disabled due to security issues.
I get that the string looks like YAML, but I'm wondering if there's a more graceful way around this as the user was just entering a bunch of dashes to indicate he had no phone number. I'd like it to basically fail gracefully and perhaps drop the value or store it as a serialised string if there is such a thing.
In Rails 3.0.20 LTS they've patched the code to check for YAML strings being sent to serialised columns. I've overridden the assignment method on my model to fix the string instead of raising an error:
module ActiveRecord
module AttributeMethods
module Write
extend ActiveSupport::Concern
included do
attribute_method_suffix "="
end
module ClassMethods
protected
def define_method_attribute=(attr_name)
if self.serialized_attributes[attr_name]
generated_attribute_methods.send(:define_method, "#{attr_name}=") do |new_value|
if new_value.is_a?(String) and new_value =~ /^---/
raise ActiveRecordError, "You tried to assign already serialized content to #{attr_name}. This is disabled due to security issues."
end
write_attribute(attr_name, new_value)
end
elsif attr_name =~ /^[a-zA-Z_]\w*[!?=]?$/
generated_attribute_methods.module_eval("def #{attr_name}=(new_value); write_attribute('#{attr_name}', new_value); end", __FILE__, __LINE__)
else
generated_attribute_methods.send(:define_method, "#{attr_name}=") do |new_value|
write_attribute(attr_name, new_value)
end
end
end
end
...
I wanted to use super(new_value) here to allow the original method to make the assignment but unfortunately it seemed to be bypassing the check (thus bypassing the security measure too).
def value=(new_value)
if new_value.is_a?(String) and new_value =~ /^---/
new_value.gsub!(/^-+/, '-')
end
write_attribute(:value, new_value)
end

Rails 3 ActionMailer class loaded but methods not available in controller

Many simmilar Q/A on this topic here and there, but I was unable to find exact solution for my problem. Using Rails 3.0.9 now, and trying to upgrade existing older application(not Rails).
The goal is to send simple email to new clients created by admins.
Have been following this oficial guide (and many others), but with no success.
The issue is, that method(s) defined in this controller, from class 'UserMailer', aren`t recognised from another controller, while class 'UserMailer' itself recognised is(how do I know this, will be explained below):
/app/mailers/user_mailer.rb
class UserMailer < ActionMailer::Base
default :from => "info#xxxxx.sk"
def kokotina # << this is just a dummy method for testing
caf = "ssss"
end
def regMailUsr(nazov, priezvisko, email, pass)
#nazov = nazov
#priezvisko = priezvisko
#email = email
#pass = pass
#url = "http://loyalty2.xxxx.sk"
mail(to: email, subject: 'Vaša registrácia bola dokončená.')
end
end
I have also created View for this mail controller but that is not important right now.
The fragments from clients controller are here:
/app/controllers/clients_controller.rb
# encoding: UTF-8
class ClientsController < ApplicationController
load_and_authorize_resource
.......
def new
#noveHeslo = genHeslo(10) # << I defined this in application_controller.rb and it works
UserMailer.kokotina # << just a dummy method from UserMailer
#client = Client.new(params[:client])
.......
end
.......
def create
.......
if #client.save
#send email to new client:
UserMailer.regMailUsr(params[:client][:fname], params[:client][:lname], params[:client][:email], params[:client][:password]).deliver
.....
end ......
Now how do I know that my class is loaded? If in client controller, I change 'UserMailer' to 'xUserMailer', I will get 'no class or method in ...' error, but without 'x', I get only:
'undefined method `kokotina' for UserMailer:Class'
I also tried to define my methods in UserMailer:Class like this:
def self.kokotina # << this is just a dummy method for testing
caf = "ssss"
end
#or even like this
def self <<
def kokotina # << this is just a dummy method for testing
caf = "ssss"
end
end
#and then tried to invoke this method(s) like this:
UserMailer.new.kokotina
#or simply
kokotina
Strange is, that when I put contents of file '/app/mailers/user_mailer.rb' at the end of 'application_helper.rb' file, just after the end of 'module ApplicationHelper', I get no errors but of course, it won`t work.
Please keep in mind that I have no problem coding in another languages, but this mystic/kryptic rules of Ruby on Rails are still a complete mistery to me and unfortunatelly, I don`t have time or even motivation to read time extensive quides or even books for RoR beginners. I have been coding much more difficult applications and implementations, but this heavily discriminating system is driving me nuts.
Thank you all!
Problem solved!
The trick was, that in '/app/mailers/user_mailer.rb', I had multibyte characters. In mail subject.
So I added:
# encoding: UTF-8
at the very first line of '/app/mailers/user_mailer.rb'
I found this by total accident: later my rails app could not start, and server was simply throwing HTTP 500 error. So no trace, error defining etc.
I found out that multibyte string in:
mail(to: email, subject: 'Vaša registrácia bola dokončená.')
Was responsible for crash. When I removed that string, I noticed one important side effect: my methods became magicaly available for another controller!!!!
So if someone could give me at least one reason to lowe Rails...

Stub method called from constructor when using Fabrication

I've got the following model
class User < ActiveRecord::Base
before_create :set_some_values
private
def set_some_values
#do something
end
end
In specs I'm using Fabrication gem to create objects but I can't find a way to stub the set_some_values method. I tried
User.any_instance.stub!(:set_some_values).and_return(nil)
but Fabrication seems to ignore this. Is it possible to do?
This is why I don't like ActiveRecord callbacks -- because if you want to have nothing to do with a callback (because, say, you're making a call to an external service inside the callback) you still have to be concerned about stubbing it out. Yes you could stub out methods inside the callback, but it's the same problem, and actually it's a bit worse because now you are concerned about something inside a method you want nothing to do with.
As usual there are multiple options here.
One option which I've used a lot in the past is, add a condition to your callback that turns it off by default. So your Post class could look like:
class Post
before_save :sync_with_store, :if => :syncing_with_store?
def syncing_with_store?; #syncing_with_store; end
attr_writer :syncing_with_store
def sync_with_store
# make an HTTP request or something
end
end
Now wherever you really want to call the callback (perhaps in your controller or wherever), you can set post.syncing_with_store = true before you call post.save.
The downside to this approach is, it's something that you (and other devs working with you) have to keep in mind, and it's not really obvious that you have to do this. On the other hand, if you forget to do this, nothing bad happens.
Another option is to use a fake class. Say you have a Post that pushes its data to an external data store on save. You could extract the code that does the pushing to a separate class (e.g. Pusher) which would be accessible at Post.pusher_service. By default, though, this would be set to a fake Pusher class that responds to the same interface but does nothing. So like:
class Post
class << self
attr_accessor :pusher_service
end
self.pusher_service = FakePostPusher
before_save :sync_with_store
def sync_with_store
self.class.pusher_service.run(self)
end
end
class FakePostPusher
def self.run(post)
new(post).run
end
def initialize(post)
#post = post
end
def run
# do nothing
end
end
class PostPusher < FakePostPusher
def run
# actually make the HTTP request or whatever
end
end
In your production environment file, you'd set Post.pusher_service = Pusher. In individual tests or test cases, you'd make a subclass of Post -- let(:klass) { Class.new(Post) } -- and set klass.pusher_service = Pusher (that way you don't permanently set it and affect future tests).
The third approach, which I have been experimenting with, is this: simply don't use ActiveRecord callbacks. This is something I picked up from Gary Bernhardt's screencasts (which, by the way, are pretty amazing). Instead, define a service class that wraps the act of creating a post. Something like:
class PostCreator
def self.run(attrs={})
new(attrs).run
end
def initialize(attrs={})
#post = Post.new(attrs)
end
def run
if #post.save
make_http_request
return true
else
return false
end
end
def make_http_request
# ...
end
end
This way PostCreator.run(attrs) is the de facto way of creating a post instead of going through Post. Now to test saves within Post, there's no need to stub out callbacks. If you want to test the PostCreator process, there's no magic going on, you can easily stub out whichever methods you want or test them independently. (You could argue that stubbing out methods here is the same as stubbing out AR callbacks, but I think it's more explicit what's going on.) Obviously this only handles post creation, but you could do the same for post updating too.
Anyway, different ideas, pick your poison.
The #set_some_values method here is called when you call #save on the record. So it has nothing to do with the constructor and therefore you don't need to stub User.any_instance -- just make your record and then do a partial stub, as in:
record.stub(:set_some_values)
record.save

What does this Rails Engine code mean: config.to_prepare &method(:activate).to_proc

I'm working with Spree, which uses Rails engines extensively. A common pattern I find is this. However I have trouble understanding this code.
class Engine < Rails::Engine
def self.activate
...
end
config.to_prepare &method(:activate).to_proc
end
What does .to_prepare do
What does the &method operator do?
What is the overall effect of the code?
Many Thanks!
&method(:activate).to_proc
This is best consumed one item at a time. (It should be noted that this portion of the code is 100% non-Rails-specific Ruby.)
method is a Ruby method (it's all very meta). It is documented thusly:
Looks up the named method as a
receiver in obj, returning a Method
object (or raising NameError). The
Method object acts as a closure in
obj’s object instance, so instance
variables and the value of self remain
available.
Check out the following IRB session:
ruby-1.9.2-p136 :001 > def my_method
ruby-1.9.2-p136 :002?> puts "in my_method"
ruby-1.9.2-p136 :003?> 10
ruby-1.9.2-p136 :004?> end
=> nil
ruby-1.9.2-p136 :005 > method(:my_method)
=> #<Method: Object#my_method>
So the method call is looking up (in your example) the activate method and creating a Method object for it. Method contains a method called to_proc, which "returns a Proc object corresponding to this method". Continuing our IRB session:
ruby-1.9.2-p136 :006 > method(:my_method).to_proc
=> #<Proc:0x000001010a3e38 (lambda)>
Finally, we use the ampersand operator, which, when preceding a Proc object during a method call, will be replaced by the block the Proc contains. One more time in IRB:
ruby-1.9.2-p136 :007 > def executor(&block)
ruby-1.9.2-p136 :008?> block.call
ruby-1.9.2-p136 :009?> end
=> nil
ruby-1.9.2-p136 :010 > executor( &method(:my_method).to_proc )
in my_method
=> 10
So, in pseudocode, what the line you listed is saying is:
config.to_prepare(a block containing the functionality of the method activate)
config.to_prepare
[Edited based on schof's comment]
config.to_prepare takes a block that should be run to set up your Railtie/Engine. It is run once in production mode and on every request in development, and is the only code guaranteed to be called on every single request in development mode. This is important if you are modifying classes (class_eval, etc.) as part of your engine initialization; otherwise, you're going to see different behavior in development vs. production.
But Why?
The reason this is a common idiom is so that you don't have to define your preparation code inside the to_prepare block itself; you can define method(s) in your class and then convert them to a block (which remembers its scope) using the magic described above. The code is functionally equivalent to:
class Engine < Rails::Engine
config.to_prepare do
(the contents of self.activate)
end
end