call arbitrary chained methods on wrapper class - ruby-on-rails

I'm creating a wrapper class for an API because my application will need to call it with different credentials at different times. I started off passing the wrapper a method and arguments and then doing (basically) this when calling it
call
set_credentials
TheAPI::Thing.send(method, args)
ensure
reset_credentials_to_default
end
HOWEVER, I realized that a challenge here is if I need to chain methods; this way I can only call one at a time; so for example I wouldn't be able to to TheAPI::Thing.find(id).delete. (At least, not without re-calling the credentials setter, which is undesirable since I have to fetch a token).
Is there a way using ruby to collect the methods/args being chained onto an object? Or would I simply have to pass in some ugly ordered set of things?
EDIT: Surely activerecord's query builder does something like this, collecting the chained methods before returning, and then after they're all collected, ensuring that as a final step the query is built, called, and returned?

the way to do this is to define a proxy object and to pass that around instead of the actual thing.
In the object itself, hold a reference to the Thing and override method_missing: http://ruby-doc.org/core-2.1.0/BasicObject.html#method-i-method_missing
In the method missing do the thing you are doing today. In a nutshell this is what ActiveRecord is doing.
As far as chaining things, I don't believe it would be a problem as methods that can be chained usually return references to self. When you call the 2nd method in the chain, you actually have done the work for the first one and have an object that has the 2nd method in the chain. The only trick you need to pay attention to is that you want to return a reference to the proxy class that encapsulates the thing instead of the actual return of the thing if you want the chaining to succeed.
Give it a shot and ping me if you run into trouble and I can spin up a fully working example.

Related

rails before_create not called when creating an object with Object.const_get().new

I have a single table inheritance mechanism and a controller method that creates objects based on a text type.
From my controller:
tile = Object.const_get(tile_data[:type]).new(params_from_tile(tile_data))
tile.save
inside my model base class I have several before create hooks:
before_create :set_handle, :upload
It appears none of my hooks are firing, does it have something to do with my use of Object.const_get to create my objects?
Edit: I've managed to work around this by not using Object.const_get().new now I'm just invoking my Tile.new directly, and there does not appear to be any negative repercussions, so yeah.
Theoretically, there is no difference how you access the class, both of these would behave exactly same:
Tile.new(params_from_tile(tile_data))
and
Object.const_get("Tile").new(params_from_tile(tile_data))
Your seeing bad behaviour may have to do with some other small thing missing.
May be tile_data[:type] in your example pointing to something else, did you make sure Tile record gets saved without callback. Can you try with Object.const_get("Tile") and see what happens.
I've changed this to invoke the baseclass directly:
Tile.new(params_from_tile(tile_data))
And now my hooks are being called as expected, so I'm not sure why this behaves this way, and would appreciate a better answer from someone who knows, but it appears that the answer is that using Object.const_get().new to create an object skips all hooks. On a side note, Invoking create on the baseclass with just a type attribute will still cause subclass hooks to fire, So thats nice.

different behavior of method when immediately accessing the results

I have a class method Juxtaposition.generate_for(position) on a class that I am calling from a spec. The method sets up a map reduce and calls it map_reduce(map, reduce).out(merge: "juxtapositions")
The position variable is defined in a let prior to the it block.
When executing if I simply call the function above (which is really only calling a map reduce on data related to the position) then tests like below fail:
Juxtaposition.count.should eq 1
Juxtaposition.first.value.should eq values
However, if I call
Juxtaposition.generate_for(positions).first["value"].should eq values
prior to the two tests then they both pass. The above two tests also pass when I use pry and call the generate_for method from there.
Is there some strange behavior of map reduce in mongoid that I should be aware of? Or, is there some way to force the results into my later queries.
Solution was simple enough. I just need to make sure to call find on the call to map reduce.
More specifically:
map_reduce(map, reduce).out(merge: "juxtapositions").first
or
map_reduce(map, reduce).out(merge: "juxtapositions").to_a
Without to_a or first the actual map reduce doesn't execute it seems, even if it's meant to be stored in another collection.

Does "where" loads data before setup method executes?

I want to construct where conditions based on setup data. But seems like where executes before setup method so I'm getting null object. I'm I right and how can I construct where data based on my setup data?
In short, you can't. The where block must run before the setup block/method for reasons discussed on the mailing list (http://forum.spockframework.org). However, a where block may refer to #Shared variables, which can be initialized directly or in setupSpec(). If necessary, you can write multiple spec classes with different setupSpec() methods and keep them all in the same file.
Often, an alternative is to turn things around and use simple values (e.g. strings and numbers) in the where block, from which more complex objects are constructed in the setup block.

Are these values dependencies?

I've got an object that encapsulates remote calls. It needs credentials to make the calls. I think the credentials should be passed into the constructor so that, once the object is created, a user doesn't have to keep passing them in every time they make a call to the object. This seems like a sensible factoring.
If I do this though I've got the added complexity of the clients that use this object needing to be passed a factory instead of the object itself because they credentials won't be known until run time. So given this extra work, I was wondering if credentials (being just string values and no code) count as a dependency or not?
Does this question even make sense? You see I've gotten it into my head after using IoC that anything being passed into a constructor counts as a dependency and thus should probably be an instance of some implementation of an interface.
I wouldn't see those strings as dependencies. Instead, create an IUserContext or IUserCredentials abstraction that you can inject.

Is it bad design to base control flow/conditionals around an object's class?

I'm currently working on a Rails project, and have found times where it's easiest to do
if object.class == Foo
...
else if object.class == Bar
...
else
...
I started doing this in views where I needed to display different objects in different ways, but have found myself using it in other places now, such as in functions that take objects as arguments. I'm not precisely sure why, but I feel like this is not good practice.
If it's not good practice, why so?
If it's totally fine, when are times that one might want to use this specifically?
Thanks!
Not sure why that works for you at all. When you need to test whether object is instance of class Foo you should use
object.is_a? Foo
But it's not a good practice in Ruby anyway. It'd much better to use polymorphism whenever it's possible. For example, if somewhere in the code you can have object of two different classes and you need to display them differently you can define display method in both classes. After that you can call object.display and object will be displayed using method defined in the corresponding class.
Advantage of that approach is that when you need to add support for the third class or a whole bunch of new classes all you'll need to do is define display method in every one of them. But nothing will change in places where you actually using this method.
It's better to express type specific behavior using subtyping.
Let the objects know how they are displays. Create a method Display() and pass all you need from outside as parameter. Let "Foo" know to display foo and "Bar" know how to display bar.
There are many articles on replacing conditionals with polymorphism.
It’s not a good idea for several reasons. One of them is duck typing – once you start explicitly checking for object class in the code, you can no longer simply pass an instance of a different class that conforms to a similar interface as the original object. This makes proxying, mocking and other common design tricks harder. (The point can be also generalized as breaking encapsulation. It can be argued that the object’s class is an implementation detail that you as a consumer should not be interested in. Broken encapsulation ≈ tight coupling ≈ pain.)
Another reason is extensibility. When you have a giant switch over the object type and want to add one more case, you have to alter the switch code. If this code is embedded in a library, for example, the library users can’t simply extend the library’s behaviour without altering the library code. Ideally all behaviour of an object should be a part of the object itself, so that you can add new behaviour just by adding more object types.
If you need to display different objects in a different way, can’t you simply make the drawing code a part of the object?

Resources