-
The Week #91
by- Cherry blossoms are blooming everywhere. Though it's my favorite time of year, I can't remember the last time I went (ever?) to a proper hanami (picnic under the blossoms...with booze!).Β I had an opportunity once when I was exchange student, but it happened to coincide with the famous fertility festival in Kawasaki...and a college student can't not go and see the spectacle of large male genitalia being paraded around the street...especially as it wasn't well documented online at the time. I've got a great photo of me in front of a pink one as tall as I am...but I'm not quite sure I want to post that here...yet.
- We signed a contract to get some solar panels and a battery installed on the house. After thinking and talking with different companies since October, I'm happy to have settled on a system / installer. We still don't know when the installation date is going to be, but it's a step in getting off gas. My wife has also expressed interest in maybe going all electric, so moving off gas for our cooktop and water heater...which I love...and consider another week.
- It rained last Tuesday and I got to use my cycling poncho. This was my 3rd time using and I'm getting the hang of it. The trick is, instead of putting the thumb loops around your thumbs, as the name suggests, you put them on your handlebars. I'm almost looking forward to cycling in the rain more.
- My grandma sent me a package with a bunch of photos of my grandpa (who passed almost 2 years ago), my mom when she was younger, my uncles...it's great. She also gave me permission in the card to toss anything I don't want, which is sweet and I love the explicit permission...not that I will.
- I started using my double-edge razor again when shaving. Yumi got it for me 6+ years ago with a nice brush for putting on shaving cream etc...I used it not as much as I should have and fell back into the 5+ blade razor trap. Recently, each time I went to buy new razors I'd get annoyed at the price.
Shaving is just a faff, even in the best of times. This time around with me DE razor I'm skipping the brush for shaving creams and just using the regular gel type I was using before. My hope is that if I lower the faff around using my DE razor I can continue using it and in the end throw away much less plastic, save a bunch of cash, and use nicer things (that I already own!). - I had a realization about why I post to Twitter more than my blog. Part of it is the reach of twitter vs my blog (probably for the better, that one). The other part is the simple form is 1 tap away on the home page.
My goal is to make it as easy to blog as it is to tweet and I think I'm getting close with my "mobile blogging" page. It has a few different defaults that make it closer to twitter than a blog, too. Posts are defaulted as published and visible to everyone instead of draft, and you can only post statuses β no articles or bookmarks with this interface.Mobile blogging with Tanzawa
Important though is the trip dropdown, which will allow me to travel blog in real time, which has been a long term goal / vision for my blog.
-
Checkin to θ°·η’ι¨ζ± ε ¬ε
Enjoying the fantastic weather and cherry blossoms. -
Checkin to improve
At it again. -
byStarting work on a mobile optimized posting interface for Tanzawa. Still a ways to go.
First draft -
by
5km run done. This should be lovely in a week, assuming the rain doesnβt have other plans. -
π Travel photos are underrated
byI snapped many photos while wandering Haifa last week, as I always do whenever I see something new or interesting while exploring a city. I was with my friend Tyler, who conspicuously does not take photos while exploring a new place. I asked him why,...
This is one reason I made Trips. I wanted a way to re-visit my trips. Having your photos and a map make it so much more enjoyable to remember than a pro photo someone else took.- Tagged with
- travel
- photography
-
byGetting some ideas for how I want photo posts to work in Tanzawa. Think Iβm close to being able to start on it.
-
The Week #90
by- After a few months delay I went and got my annual health check. I was able to go to the same center as last time, too. I'm always amazed at the efficientcy of these places as each person is directed from station to station and the nurses/technicians do their thing.
Despite my best efforts I gained a couple of kilos and my blood pressure was slightly up (with the state of the world how could it not π ). It's time to cut out that snacking habit I've gotten into as of late and cut down portions at dinner. - As Leo had a "forced" Tuesday off last week, since he wasn't sick, rather than be stressed at the house all day we went out and did our usual Monorail-Enoshima-Aquarium-Burger loop. He played the crane game with his own money once, but he didn't win anything, but he seemed satisfied.
While we were walking to the Enoden after lunch, Leo decided he wanted some sweets from the coffee shop, so we dropped by Tully's as well. There's a great word in Japanese for exactly this situation, where you have room for dessert despite being full: betsu-bara. Betsu means separate/different and bara being stomach. It's the first time he's had dessert stomach that I can remember. - There was a big earthquake last week around 11:30pm. It was certainly the biggest and longest quake I've felt in a while. Thankfully there wasn't any damage around here and it was mostly an annoyance because it kicks off your adrenaline, which is not helpful when you're trying to get back to sleep.
- I bought tickets for Disney next month during Leo's spring break. I've never been to Tokyo Disneyland, but I've been to Disney Sea twice.
As a kid, we lived close enough that when we went to Disney it was just for the day, never staying at the hotels. And being honest, they were probably also out of budget, even if it wasn't so close. While we're still close enough here in Yokohama for a day-trip to Disney (trains rule), we're going to stay one night. I'm excited about it, not just because it's a surprise for Leo, but because I can do those family things I couldn't do myself growing up. - Unrelated to health check results, but after skipping a week of running not on purpose I got back out and ran 5km. I always feel so much better after running, no matter how long I go out. I need to remind myself when the main obstacle is me changing clothes. Sometimes I can't run in the morning or don't want a tight lunch run. With the days starting to get longer, I wonder if I could do short post-work runs every now and again...
- After a few months delay I went and got my annual health check. I was able to go to the same center as last time, too. I'm always amazed at the efficientcy of these places as each person is directed from station to station and the nurses/technicians do their thing.
-
byI've now added support for OpenGraph meta tags in Tanzawa. It's nice to get a small feature out.
Open graph data on a blog post
Thanks to Ricardo for requesting this feature.Β -
How to Resolve Overlapping DjangoObjectTypes with Graphene and Graphene Relay
byIf your schema has multiple types defined using DjangoObjectType for the same model in a Union, selections that work on the Union won't necessarily work as is on Relay node queries.Β
For example, suppose we had a model schema like this:class Record(models.Model): record_type = models.CharField(max_length=12) @property def is_disco(self) -> bool: return self.record_type == "DISCO" @property def is_punk(self) -> bool: return self.record_type == "PUNK" class Disco(models.Model): record = models.OneToOneField(Record, related_name="disco_record") bpm = models.IntegerField() class Punk(models.Model): record = models.OneToOneField(Record, related_name="punk_record") max_chords = models.IntegerField()
Our application cares Records and, depending on the record_type, the type of meta information we want to manage changes. As such we create a new model with a OneToOneField to our record for each type we plan on managing.
When we query our records we wan to only worry about Records, so define our GraphQL types accordingly.class DiscoRecord(graphene_django.DjangoObjectType): class Meta: model = models.Record bpm = graphene.IntegerField(required=True) @classmethod def get_node(cls, info, id) -> models.Record: # Allow our object to be fetchable as a Relay Node return models.Record.objects.get(pk=id) def resolve_bpm(record: models.Record, **kwargs) -> int: return record.disco_record.bpm class PunkRecord(graphene_django.DjangoObjectType): class Meta: model = models.Record max_chords = graphene.IntegerField(required=True) @classmethod def get_node(cls, info, id) -> models.Record: # Allow our object to be fetchable as a Relay Node return models.Record.objects.get(pk=id) def resolve_max_chords(record: models.Record, **kwargs) -> int: return record.punk_record.max_chords class Record(graphene.Union): class Meta: types = (DiscoRecord, PunkRecord) @classmethod def resolve_type( cls, instance: models.Record, info ) -> Union[Type[DiscoRecord], Type[PunkRecord]]: # Graphene is unable to accurately determine which type it should resolve without help # because the unioned types are all DjangoObjectTypes for the same Record class. if instance.is_disco: return DiscoRecord elif instance.is_punk: return PunkRecord raise ValueError("Unknown record type")
Because we have the resolve_type @classmethod defined in our Union, Graphene can correctly determine the record type. Without that we'd get an error any time we tried to resolve values that only exist on the PunkRecord or DiscoRecord type.
So if we had a records query that returned our Record Union, we could query it as follows without any issues.query { records { ... on DiscoRecord { bpm } ... on PunkRecord { maxChords } } }
But what about the Relay node query? The query looks quite similar to our records query.query { node(id: "fuga") { ... on DiscoRecord { bpm } ... on PunkRecord { maxChords } } }
However, and this is the key difference, node does not return our Union type, but rather our individual DiscoRecord / PunkRecord type. And since both of those types are technically Record types (because of the same Django meta class), any PunkRecords will be resolved asΒ DiscoRecords and return an error when we try to resolve Punk only fields.
In order for node to be able to differentiate between the Punk and Disco at the type level we need one more is_type_of classmethod defined on our types.class DiscoRecord(graphene_django.DjangoObjectType): ... @classmethod def is_type_of(cls, root, info) -> bool: # When a DiscoRecord is resolved as a node it does not use the Union type # determine the object's type. # Only allow this type to be used with Disco records. if isinstance(root, models.Record): return root.is_disco return False class PunkRecord(graphene_django.DjangoObjectType): ... @classmethod def is_type_of(cls, root, info) -> bool: # When a PunkRecord is resolved as a node it does not use the Union type # to determine the object's type. # Only allow this type to be used with Punk records. if isinstance(root, models.Record): return root.is_punk return False
This way, when Graphene is looping through all of our types trying to determine which type to use for a given Record, we can inspect the actual record and prevent an erroneous match.
This is obvious in retrospect. Although our GraphQL query selectors are exactly the same the root type is different and as such requires a bit more instruction to resolve the appropriate type.