Ah right. Why not load in all the feature values from both tables when you first load the user? That way you’re dealing with just the one query per request, to grab the current user, and after that you just play with that object.
The client cannot set the value of a feature.
I will use it to limit which parts of the application a particular client has access to. A feature is key value pair where the value can be anything True/False, a URL, etc.
FeatureMaster contains all of the features for the app and their default values: id
Feature contains a client specific override: feature_master_id
When I develop a new piece of functionality I can limit who has access to it - It means that I can configure the app per client.
Yeah, if you’re using it that often you could either pull it in with your current_user when you load that or put it in the session as you suggest.
But maybe it’s worth taking a step back. I’m a little confused by the architecture: what other data is stored in the database along with these features? Can users modify features in any way or are you the only one that does that? Why do you have feature_master as well as feature?
In this case I am wanting to make it as efficient as possible because Features(Client wide enabled functionality) and a very simliar type of concept Permissions(User enabled functionality) are going to be used extensively on the majority of pages.
// do something
// do something else
I’m even considering baking this out or saving these values in session or something simliar so I only need to query all the features and permissions for a user on login.
SELECT COALESCE(f.value, fm.value) AS value
FROM feature_master AS fm
LEFT OUTER JOIN feature AS f
AND f.feature_master_id = fm.id
WHERE fm.feature_key IN ('ManageUsers','OtherFeature','AnotherFeature')
Given that info would you still make up to 10 queries per page for this data?
Well, I’m a bit wary of premature optimization: in theory the find_by_sql method is faster, but it’s also a bit less readable, and unless you run into a bottleneck my instinct would be to put it in controller logic, so the first of your proposed options.