Closed Curter29 closed 6 years ago
Hi @Curter29, sorry for the slow reply, passing the identity should work - are you also doing the setup needed for vanity to connect to the database?
To use Vanity from anywhere, you'll need to do some of the setup currently done in vanity/frameworks/rails.rb
, specifically:
$redis = Redis.new # or from elsewhere
Vanity.configure do |config|
# ... any config
end
Vanity.connect!(
adapter: :redis,
redis: $redis
)
Vanity.load!
Then per request:
# Tracks an action associated with a metric. Useful for calling from a
# Rack handler. Note that a user should already be added to an experiment
# via #ab_test before this is called - otherwise, the conversion will be
# tracked, but the user will not be added to the experiment.
identity_object = Identity.new(env['rack.session'])
Vanity.track!(:click, {
# can be any object that responds to `to_s` with a string
# that contains the unique identifier or the string identifier itself
:identity=>identity_object,
:values=>[1] # optional
})
Does your user object return its id on to_s
? Otherwise, try passing in the user id itself
This was really helpful to explain how to use Vanity.track!
outside of a controller/view context. My follow-on question is:
How do I use ab_test
(or equivalent) inside of a plain old ruby object?
e.g. Given I have my identity string, how can I have Vanity assign and return an alternative for a given experiment.
Good question - this should have been more clearly documented years ago 😄 !
Vanity pulls the identity from a "context" object that responds to vanity_identity
.
So this should work: defining Vanity.context
(this is how the ActionMailer integration works)
class AVanityContext
def vanity_identity
"123"
end
end
Vanity.context = AVanityContext.new() # Any object that responds to `#vanity_identity`
Vanity.ab_test(:invite_subject)
If you're using plain ruby objects, you could also alias something in your identity model to respond similarly and then set that as the vanity context:
class User
alias_method :vanity_identity, :id
end
Currently Vanity is structured mostly around a request-based model, so this works great in the traditional request/response, but one disadvantage of this is that it's indirect and using a "global". The Vanity.context
variable should be thread safe though.
If it helps, you can also customize the behavior:
ab_test "Project widget" do
alternatives :small, :medium, :large
identify do |identity_object|
identity_object.id
end
end
This is super helpful info and very well explains what Vanity is doing under the hood. Thank you @phillbaker!
I put together a little service object that tries to make it as declarative as possible:
class VanityDispatcher
attr_reader :id
def initialize(id: nil)
@id = id
end
def track!(metric_name)
within_context { Vanity.track!(metric_name) }
end
def ab_test(metric_name)
within_context { Vanity.ab_test(metric_name) }
end
private
def within_context
old_context = Vanity.context
context = OpenStruct.new(vanity_identity: id)
Vanity.context = context
result = yield
Vanity.context = old_context
result
end
end
So then I can use it directly like:
alternative_name = VanityDispatcher.new(id: user.id).ab_test(:my_metric)
Thought it might be helpful to share in case others are using Vanity outside of the typical request-response.
Hello, i have RoR application and some plain ruby scripts, i want track metric in plain ruby. Just try
But nothing count in dashboard, just return [#<Proc:0x00ADDR (lambda)>]
What i'm doing wrong?