Nobody said "quarter" means multiply by 4. They said "quater" means multiply by 4, which it essentially does [1]. In addition to being a real word, it's also a prefix, e.g. "quaternary" means fourth in order.
You made a typo (quater) in correcting someone's else's typo (forth). Several people have pointed out the irony and have patiently tried to teach you a new word, but you seem to keep reading past all of them without comprehending ¯\_(ツ)_/¯
Does the trademark office just rubber stamp anything they get and let the lawyers fight it out? IANAL, but these look pretty similar:
85632326 (Instructure):
IC 042. US 100 101. G & S: Application service provider (ASP) featuring software to enable uploading, posting, showing, displaying, tagging, blogging, sharing or otherwise providing electronic media or information over the Internet or other communications network
86642511 (Canvas Labs):
IC 042. US 100 101. G & S: software as a service (SaaS) services featuring software used to allow collaboration between users for sharing information; software as a service (SaaS) services featuring software to create, structure, edit, access, integrate, manage, interpret and synchronize documents, content and data between users
The trademark office will catch it sometimes but the onus is typically on the trademark holder to monitor & object to any trademark filings that might conflict with ones they've registered.
The API is pretty comprehensive, and is growing daily. With the exception of some legacy features, all of the web app's UI is built on top of it, as are the mobile apps.
Even a text column would be preferable IMO ... you wouldn't need to worry about remapping if a value got removed, it's more easily queryable, and it's certainly more legible if you're looking at raw data (say, via psql). Plus you probably won't really save much (any?) space with an (64-bit) int.
Native "enums" (types) in PostgreSQL are a mixed bag. They do have some advantages:
- you can treat them like strings (e.g. `SET status = 'approved'`, but they are a fixed size (four bytes)
- when queried they appear as strings too. Nice for debugging
- if you enter an invalid value (anywhere, not just in Rails) PG will throw a wibbly
But the biggest problem with enum types is if/when you want to add a new value to an enum type, it's annoyingly non-trivial. You can't run `ALTER TYPE ... ADD` because it doesn't work in a transaction. [0]
Instead you need to drop the type, recreate it (with the new value) and then alter all the tables that use this type. If you have a huge DB this can get a bit silly, although you can at least do it all in a transaction.
It is fairly trivial to add support for real Postgres enum types - https://gist.github.com/clarkdave/5936375 - but it's not as elegant as having it properly supported by ActiveRecord.
As other posters have mentioned here, it'd be useful if Rails' enum support used text instead of integers. You could then set up a Check constraint in PG to enforce the correct values and stop invalid data slipping into your database from other sources, whilst keeping the nice sugar in ActiveRecord.
Shouldn't the mapping to database be backend-dependent anyway? SQLite has more or less no feature, yet ORMs don't feel the need to restrict themselves to what sqlite can do.
(nota: oracle and mssql don't, afaik, have an enum type either)
(and in Postgres, enum is not a type, it's a type constructor. First you have to `CREATE TYPE yourtype AS ENUM ( values... )` then you can use `yourtype` in a table, you can't have a column of type `ENUM ( whatever )` because Postgres enums are disjoint and not structurally equivalent)
I agree with all of your points, but I don't think it's a shame. It's an awesome contribution and will make my work a lot easier on future projects. I'm personally going to try and take a stab at implementing this with strings versus ints though, since I agree you don't really save much by using the int and it's much friendlier for debug and future changes.
You can specify a smaller int size, I used 2-byte ints fairly often. Saves a good amount of space. This also makes it really easy to change the corresponding name of a value/categorization (no migration needed).
This approach works well when you want to cache data from an existing integration database and don't have the luxury of rearchitecting the whole thing.
At my previous job, we had a bunch of systems talking to a single database. Some were rails, some were not. We wanted to add memcached to the rails apps via cache-money[1]. That'll handle read-through/write-through caching for vanilla rails stuff, but we had to somehow invalidate the cache for updates that happen outside of ActiveRecord::Base#save (e.g. update_all, or a write from a non-rails system). In the end, we settled upon the same approach[2] as in the article.
The trigger-backed cache invalidator was also written in ruby, and knew from rails/cache-money what key(s) needed to be invalidated when it got a notification. IIRC you didn't need to do anything special when you added a new cache key (e.g. cache user lookups by username), since the invalidator would just know what to do.
[2] This was actually on 8.4, so unfortunately there was no NOTIFY. Instead, a plpython trigger would send a message to invalidator (persistent tcp conn per pg process), but this had the unfortunate consequences of 1. firing before the commit and 2. firing even in the event of a rollback
UTC offset is well and good if you are talking about today, but as soon as you start displaying past or future datetimes, DST will bludgeon you over the head.
And depending on your app, users might want control over the timezone. When a teacher creates an assignment in canvas-lms, the due date defaults to midnight of the selected day. It would be surprising if it set it to 2am, just because the teacher happened to be traveling when the assignment was created.
Exactly. I have run into this problem with event calendars. For example: Schedule a recurring event for 1pm. It happens to be EDT at the moment so you store the event date/time in UTC by adding 5 hours. Then, in days, weeks, or months, we change to EST. The 1pm meeting is now showing at noon.
To fix this I run a cron job on the ST/DT boundaries that increments or decrements stored date/times in the event calendar.
We did a two-day hackfest at work recently, and this was my project. As canvas-lms has grown, we've seen our GC runs get slower and slower, and this seemed like some good low hanging fruit (especially as we keep adding more languages).
I moved the translations out of the ruby heap, so as to speed up GC runs, and there were some other enhancements in both ruby and C to speed up lookups a bit.
It's still pretty new, so as I continue to refine I hope to bring those benchmarks even further.
You made a typo (quater) in correcting someone's else's typo (forth). Several people have pointed out the irony and have patiently tried to teach you a new word, but you seem to keep reading past all of them without comprehending ¯\_(ツ)_/¯
[1] https://www.dictionary.com/browse/quater