Chris Zempel
Joined
Activity
Made a post on HN. Loved the first answer:
Here's a situation I see come up often.
New developers (I consider myself here) will always estimate wrong. They will also feel bound to their estimates as deadlines.
What's the high value way to demonstrate willingness to share estimate revisions promptly and transparently? What's important to remember when you start getting stressed out?
I've got these models:
class Firm
has_many :funds
end
class Fund
belongs_to :firm
has_many :investments
end
class Investment
belongs_to :fund
has_many :investments
end
class Company
belongs_to :investment
end
With each one of these models, I'm directly concerned with the identity and thread of continuity each one has over time, and not necessarily what information there actually is about it (I don't care what info exists about a company at a given time, just that the info for a company actually belongs to that company).
Now each of these models need to have a cashflow attached to them. This object doesn't really have a conceptual identity, it just describes a particular characteristic of the model it's attached to (info about money in, money out, and when it occurs). Right now, I see a couple ways forward:
1) Make a single cashflow class that I can attach agnostically to any aforementioned model. The gist of the implementation looking like this:
class Cashflow
#has attached_id, attached_type
def belongs_to
"#{attached_type.capitalize.constantize}".find(attached_id)
end
end
#Then I can also write some cashflow-related methods that I attach to the models through a concern or something like this:
class Company
def cashflows
Cashflow.where(belongs_to: self)
end
end
2) Make individual cashflow classes for every model
class CompanyCashflow
#does cashflow stuff
end
#FirmCashflow, FundCashflow, etc...
3) Or a more polymorphic approach: have a base cashflow class that I instantiate in a scoped way, so I can isolate model-specific logic (which I'm not sure if I'll need yet) there:
class Cashflow < ActiveRecord::Base
#cashflow stuff
def initialize(model)
attached_type = model.class
attached_id = model.id
end
class CompanyCashflow < Cashflow
#company specific stuff
def initialize(model)
#does company-specific stuff
super
end
end
@cashflow = Cashflow.new(@company)
The main axis I want to think upon here is, eventual efficiency. If I have to go in and change this down the line after I have production data, that's not very efficient. First, how would you attach a cashflow to these other models? But second, and more importantly, what sort of reasoning, tradeoffs, and experiences inform your choice of designing the domain this way (or most pertinently, what's the very first thing you think before diving down into an intuitive reaction?)
Although, I suppose that's best for role-based if a company has consistent roles and scopes users need. For item-based, a vaguer table would serve better:
class UserConnection
belongs_to :user
belongs_to :item (?)
not sure how that would work. You could approximate it by:
def item
"#{item_class.to_s.constantize}".find(item_id)
end
Ultimately, a user should be able to see and access CRUD options based off of which company they're associated with. So inside this domain, companies are actually the sub-domain inside which a user operates.
class User < ActiveRecord::Base
has_many :company_connections
has_many :companies, through: :company_connections
end
class CompanyConnection < ActiveRecord::Base
belongs_to :user
belongs_to :company
end
class Company < ActiveRecord::Base
has_many :company_connections
has_many :users, through: :company_connections
has_many :products
has_many :options, through: :products
end
From there, I could go a variety of ways -- if I wanted role-based access, I could store that on the user. If I wanted item/scope based access, I could also store a reference to that object that on the user, and allow access for that based on it.
But what happens when I have co-owners of a given company who want access to the same level of information & scoping? Storing both of their id's in one column seems wrong to me, which means I'd need another table to maintain information about the group of users. Identity is a vague term.
UserGroup, Group, or Membership? Then inside that, I can attach different access levels.
For now, I'm gonna defer this decision and just stick a single user_id on there, but make sure I don't call it directly.
I'm building an app with data set up similar to this:
class Company < ActiveRecord::Base
has_many :products
has_many :options, through: :products
end
class Product < ActiveRecord::Base
belongs_to :company
has_many :options
end
class Option < ActiveRecord::Base
belongs_to :product
belongs_to :company, through: :product
end
Now I'm not actually sure if that reverse belongs_to :through works, but you get the gist of it. Each level has "ownership" of the next level down. (Company owns Products that have/own Options)
Each level has one or more Users that need to be able to able to act on behalf of those below it. For example, one of the users who manages at the Company level should have full CRUD access to everything that company and everything it owns.
However, a product manager should only have access to CRUD rights for his product and all the options that product owns. And company managers shouldn't be able to have access to other companies or anything inside of them. Option owners, etc, there are user at all different levels.
I'd like to be able to have gmail-like functionality where a full-access user can jump in and interact with the app as though they were a limited-access user the same way they can access a variety of email accounts.
So what I'm thinking is that, really, it's not a "User" that acts upon the models, but rather the "Identity" of a user that actually affects what behavior they can access, and that it's this "Identity" object I should route all the policies and scoping for user through - so a user can act on behalf of a variety of identities they have access to. My first question:
- Is this idea of an "Identity" a sensible abstraction, or is there a better way?
The rest of this question might be irrelevant, but typing it out anyway:
- Assuming this is, the user would act on behalf of a current_identity, and then be able to choose what that is from all their available identities. Going down this path, I'd like to avoid a HABTM relationship between users and identities -- one way I can think of is using an in-between:
class User < ActiveRecord::Base
has_many :user_identities
end
class UserIdentity < ActiveRecord::Base
belongs_to :user
belongs_to :identity
class Identity < ActiveRecord::Base
has_many :user_identities
#scoping an identity to a specific subset of the given models, ie, this is an identity for a 'Product' with id: 3
end
- Or, is there an alternative I can do to avoid needing this extra model (ex: serializing a bunch of user_id's in every identity and checking against that)? And is it worth it?