In the docs for validates_with it says
Note that the validator will be initialized only once for the whole application life cycle, and not on each validation run, so be careful about using instance variables inside it.
There are times though when I need to run one validation inside it, not the whole thing, I'm currently doing this:
## Call one validation
Validators::DatasetValidator.new.validate_name(self)
Instantiating it and running the instance method I need.
Is this OK? Or is there a way to access the already instantiated validator instead of creating a new one?
Related
I would like one instance of a model in memory to serve as a template for creating other objects for performance reasons, so that duplicates look like the original object but otherwise share no common components with the object they are initialized from, as if they were loaded with Model.find(template_object.id). I've tried some of the available solutions but none seems to do what I need: .dup and .deep_dup will create a new object with nil id and .clone will make some of the fields common to both the initializer and the initialized.
Currently my API is giving out the original objects that I keep as class variables, but I discovered that it leads to obscure memory leaks when the code using the objects manipulates their associations - these are kept in memory indefinitely. I hope that by giving out copies the associations of the template objects will stay untouched and the leak will be gone.
This sounds like the use case for defining a class and just initializing instances. You can customize whatever properties you want shared in the MyClass#new method. Without knowing more about your needs I will add that if you must store a template in memory you could store it as a class variable perhaps MyClass##template but would need to hear more to opine further. 😄
What I found when browsing rails source is the .instantiate method:
MyModel.instantiate(#my_other_instance.attributes_before_type_cast.deep_dup)
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.
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.
I am following a View Based Class model to setup a Calabash testing framework for my app , i.e., each view has a class containing the requisite methods for that view.
But when I call calabash functions such as "wait_for()" it throws me an error:
undefined method `wait_for' for LoggedInPage:Class (NoMethodError)
I have already added these in my env.rb
require 'calabash-cucumber/wait_helpers'
require 'calabash-cucumber/operations'
World(Calabash::Cucumber::Operations)
World(Calabash::Cucumber::WaitHelpers)
The issue probably that the page object classes aren't being initialised in the same 'world' as cucumber is running in. Adding the files to env adds them and their methods to the world that cucumber is running. You have to pass that world into your page objects when they are created to give them access to those functions.
Have your page object classes inherit from calabashes page object bases - http://www.rubydoc.info/gems/calabash-cucumber/Calabash/IBase
and when you create a new instance of a page object pass in self.
class MyPage < Calabash::IBase
...
new_instance_of_page_object = MyPage.new(self)
In this specific case, inheriting from IBase will give you access to the functions you are talking about, but passing in self will mean you have access to any other things that you have added in your env file.
Suppose I register some instance in OpenRasta's dependency resolver using
resolver.AddDependencyInstance(IInterface, instance, DependencyLifetime.Singleton)
Now if I want to swap that instance later, say to reread fresh data from the db, is another call to resolver.AddDependencyInstance the right thing to do?
Checking the InternalDependencyResolver implementation, it seems to be fine. However I'm asking because the behavior is not defined (in openrasta's sources, where I checked), and the method prefix "Add" is suggestive of different behavior.
I wouldn't use Singleton if you have to swap the instance at some point.
Use DependencyLifetime.Transient and have a constructor injection in the class where you need the new instance