Skip to content

Instantly share code, notes, and snippets.

@anka

anka/gist:56aeae44812041a29aba Secret

Created Feb 17, 2015
Embed
What would you like to do?
Setting default values for has_one association
class User < ActiveRecord::Base
# Adding the subscription association and set
# the desired kind of the subscription
has_one :subscription, -> {where kind: Subscription.kinds[:single]}
end
class Subscription < ActiveRecord::Base
# Adding an enum with predefined values
enum kind: {single: 2, company: 7}
belongs_to :user
end
# Testing the assocation
# After building a subscription the kind will
# be preset to 2
@user = User.new
@user.build_subscription
=> #<Subscription id: nil, user_id: nil, kind: 2, name: nil, note: nil, created_at: nil, updated_at: nil>
@ramonrails

This comment has been minimized.

Copy link

@ramonrails ramonrails commented Jun 15, 2020

This is a good way to set default values for has_one association
But, for a business use case?

Pros:

  • Integer uses less space (for large data sets)
  • possible => subscription.single!, subscription.single? subscription.kind

Cons:

  • in this code, user can only have either single or company subscription (but, it may be the required business logic)
  • Publishing an API would be costly (on time, consumer effort/learning-curve)
    • need serving the string instead of integer (to make it easy for API consumer). More processing on each call! Scalable?
    • confuse the consuming user with integer values (of not served strings). Discouraging less experienced interested parties?
    • consumer to remember the mapping
    • documentation will be needed for this column
  • If the API is designed in another framework (like node), then
    • mapping business logic needs knowledge transfer
  • tomorrow, when enum increases to 5 values, all above must be repeated again!
    • more code
    • more processing on each API call
    • more documentation
    • more manual work to keep all API consumers aligned
  • business logic for single/company
    • will require lof of ifs
    • bloated User model, or split into modules and include

Alternate solution is STI

SingleSubscription < Subscription
CompanySubscription < Subscription

Pros:

  • Super easy to use in the code (maintainable)
  • User can have both subscriptions together
  • no lambda evaluation (less work for ruby/AR/rails)
  • publishing API is super easy
    • No documentation required for this column
    • consumer will see data and understand. easy.
    • more bytes but less processing per API call. internet bandwidth and storage is cheap now. No?
    • write on node, or any other framework. easy. No need to copy mapping business logic to node.
    • less code in serving the API. No need to map it back to string
  • when "type" increases to 5 or more values
    • no extra documentation needed. scalable.
    • no extra work to keep API consumers aligned. scalable.
    • increase as many values as you need. scalable.
    • an ML system can start making sense without being fed the business logic
  • less experienced developers become productive faster
  • business logic for single/company
    • does not bloat the user model
    • stays refactored in separate classes (no need to include modules to reduce the fat model)

Cons:

  • "SingleSubscription" in DB takes more bytes per tuple than an integer. But then why not using bits instead of booleans?
  • More bytes to pass to an API call. But it's flawlessly and easily scalable for third parties.

Just my opinion. Discardable at your free will 😀
Have a wonderful year ahead. (Despite the pandemic, Yes)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.