<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Three till Seven</title>
		<description>Programming, espresso, and grumbling.</description>
		<link>/</link>
		<atom:link href="/feed.xml" rel="self" type="application/rss+xml" />
		
			<item>
				<title>Amazon Fire Stick versus Google Chromecast</title>
				<description>&lt;p&gt;We went all-in on Chromecast at home. We had a Chromecast Audio in every room, even the bathroom, with a set of speakers. We set up multiple groups like “Full House” and “Kitchen and Living Room” so we could have music playing wherever we were hanging out. We had a Chromecast in the living room and in the garage with the treadmill, so we could watch videos while working out. The living room Chromecast was our main source of video entertainment since we don’t have satellite or cable TV.&lt;/p&gt;

&lt;p&gt;Our dream was to have music fill the house from Spotify, iTunes, or Soundcloud at the press of a button. To have Game of Thrones playing in the living room while a documentary played in the garage. The dream was not meant to be, however. We encountered little problems every time we used a Chromecast, such as our phones not seeing a particular Chromecast until we force-closed the app, disconnecting and reconnecting to the wifi, or unplugging and replugging the Chromecast.&lt;/p&gt;

&lt;p&gt;It’s super frustrating when all you want to do is watch some TV or listen to music while you work and the technology flakes out. Why do all the other Chromecasts show up in the Spotify app except for the one I want? Why does the garage TV show up in Netflix but not the living room TV? Why is pausing Game of Thrones fraught with the risk of never being able to unpause because by the time you come back from the kitchen, the HBO Now app has forgotten it was Chromecasting, you have to reconnect, and then it loses your place in the show so you have to scrub back to it? Why did my song cut off in the middle because it disconnected, forcing me to stop what I’m doing to try and reconnect to the Chromecast Audio?&lt;/p&gt;

&lt;p&gt;I’m a big Overwatch fan, and I love watching the Overwatch League. Shortly into stage 1 of season 1, I was all hyped to watch the evening’s games on the TV after work. However, the Twitch app on my iPhone would not detect the living room TV Chromecast. The usual technique of unplugging and replugging the Chromecast, force-closing the app, and reconnecting to wifi on my phone didn’t help. I also couldn’t detect the Chromecast from my computer, trying to cast from a Chrome browser tab to the TV. We ended up swapping the garage Chromecast with the living room Chromecast because my phone had no problem connecting to that Chromecast. By this point, I’d missed part of a game and was very annoyed. That’s when I ordered a Fire Stick on Amazon.&lt;/p&gt;

&lt;p&gt;I have had no such problems with the Amazon Fire Stick; the user experience has been night and day. We plugged it into the living room TV and it &lt;em&gt;just works&lt;/em&gt; in a way the Chromecast never did. I can pause a show and when I come back, it’s exactly where I left it. It hasn’t forgotten my place in the show, it hasn’t disconnected from the wifi, it hasn’t dumped me back to a home screen. When I reopen the Twitch app after a few days, it starts on the last channel I was watching, which is exactly what I want.&lt;/p&gt;

&lt;p&gt;I prefer the control mechanism for the Fire Stick. To browse content, I do it on my big TV screen as opposed to my tiny phone screen. I like having a remote for controlling what’s on my TV instead of using my phone.&lt;/p&gt;

&lt;p&gt;When I want to work on the couch, I have no trouble playing music on the living room speakers with the Fire Stick. The Spotify and SomaFM apps are great, and the macOS Spotify app lets me control what’s playing on the Fire Stick.&lt;/p&gt;

&lt;p&gt;That’s what the experience should have been playing Spotify via Chromecast, but so often it was a struggle. My phone would lose its connection to the Chromecast while the music would continue playing, so I’d have to try and reconnect to regain control. Put your phone down for a minute, long enough for the display to turn off, and when you unlocked your phone again, Spotify would have forgotten it was casting. I don’t think it was a problem with any particular app either since I had this experience with Spotify, HBO Now, Netflix, and Twitch.&lt;/p&gt;

&lt;p&gt;The Fire Stick shows TV shows that are available to me while I’m just browsing the menu, which is a nice feature that I didn’t even realize I wanted because the browsing experience for Chromecast is so lacking. With Chromecast, you pick an app and have to browse content in whatever way that app presents. The Fire Stick has a dashboard view that lists your apps, and it surfaces content as well. On Chromecast, the question is “what’s on Netflix” or “let’s see what HBO Now has”, as opposed to the general “what’s on TV” that the Fire Stick allows.&lt;/p&gt;

&lt;p&gt;The Chromecast seemed to have problems with our home wifi. Sometimes after casting something and letting your phone lock, unlocking your phone would show the Chromecast icon doing the “searching” animation, trying to reconnect. It was a 50-50 shot whether it would successfully reconnect or fail. If it failed, usually you couldn’t just tap the icon and try to connect again, it would be in some screwy state requiring a force-quit of the app. For whatever reason, the Fire Stick has not had this problem; it stays connected to our wifi.&lt;/p&gt;

&lt;p&gt;Perhaps the idea behind Chromecast–a simple device where the real brains are on your phone, computer, or tablet–isn’t a bad one, and it just suffers from a poor implementation, or is ahead of its time. I’m inclined to believe the Fire Stick just has a better idea to start with, though: make the device itself smart enough to keep track of what you’re watching or listening to, so it doesn’t need a separate phone, computer, or tablet to do its job. Amazon can focus on getting the experience right and have it work pretty much the same for every app, as opposed to Google who has to rely on everyone else building their Chromecast apps correctly. I like that the Fire Stick has one interface for controlling content, instead of relying on each individual app to let me control playback in a reasonable way.&lt;/p&gt;

&lt;p&gt;Granted, there’s no Chromecast Audio equivalent for the Fire Stick. We only have the one Fire Stick so we can’t play music on the various speakers around the house without using Chromecast. But the experience has been so much better with the Fire Stick that I’d rather play music on just the living room speakers than hassle with Chromecast in the other rooms. We’ve been so pleased with the Fire Stick that I wish we’d just bought one of them initially instead of wasting so much time trying to make Chromecast work.&lt;/p&gt;
</description>
				<pubDate>Sat, 14 Apr 2018 00:00:00 -0500</pubDate>
				<link>/2018/04/14/amazon-fire-stick-versus-google-chromecast/index.html</link>
				<guid isPermaLink="true">/2018/04/14/amazon-fire-stick-versus-google-chromecast/index.html</guid>
			</item>
		
			<item>
				<title>thoughts on Overwatch</title>
				<description>&lt;p&gt;Overwatch launched and immediately became super popular, but I wasn’t sure I would like it. I’d never gotten into Team Fortress 2, Counter Strike: Global Offensive frustrated me, and my time playing DotA 2 and League of Legends was short-lived. Somehow, despite Overwatch being likened to all of these games, I love Overwatch alone.
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2016/12/hanzo-with-cheese.jpg&quot; title=&quot;I love posing as Hanzo during skirmish&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2016/12/hanzo-with-cheese-400x0-7fe7f0.jpg&quot; alt=&quot;I love posing as Hanzo during skirmish&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I originally bought Overwatch because &lt;a href=&quot;http://summasmiff.github.io/&quot;&gt;my friend Summer&lt;/a&gt; got it and really enjoyed it, and I figured it’d be a way to stay in touch with her. I actually wasn’t concerned much about liking the game, thinking I’d use it to voice chat with Summer and simply tolerate the actual gameplay.&lt;/p&gt;

&lt;p&gt;I’m not the best at aiming, which may have been why I never got the hang of CS: GO. As soon as I’d stick my head out of spawn, I’d be dead because a sniper got me. Despite my bad aim, I feel like I’m helping my team in Overwatch. There are a variety of different play styles across all the characters. I can latch onto an ally as Mercy or to an enemy as Symmetra, and aiming is no longer a concern. Even with characters that use traditional guns, like D.Va or Mei, I feel effective because of D.Va’s large bullet spray and Mei’s giant ice projectiles.&lt;/p&gt;

&lt;p&gt;I like how each character has a different attitude about them, and how that translates into how I play them. I feel like a saucy bully as D.Va, chasing enemies off the payload and blasting them continuously. I feel above the petty concerns of the world as Symmetra, setting up my turrets in relative peace until an enemy dares to bother me, then I microwave them. When I’m Mercy, it’s painful watching my allies take damage or die, and I flutter amongst all of them, prioritizing those with the least health so I can keep everyone alive. I’ll also sacrifice myself as Mercy to get a good rez off and bring back multiple teammates, which seems to fit her personality.&lt;/p&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2016/12/mercy-potg.jpg&quot; title=&quot;Mercy Play of the Game&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2016/12/mercy-potg-400x0-fbebff.jpg&quot; alt=&quot;Mercy Play of the Game&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Overwatch on the PC has been an overall friendly community. I’ve met several complete strangers who have been lovely to play with. Even when I don’t friend someone and repeatedly group up with them, I still frequently get grouped up with people who are helpful, friendly, and pleasant in chat.&lt;/p&gt;

&lt;p&gt;Sometimes you get pacifists on the enemy team who like to greet you and emote, then you have to remember “don’t shoot that Reaper, he’s the friendly one,” which adds a hilarious and challenging twist to an otherwise typical round of quick play. I feel like a jerk if I kill the guy who only wanted to wave at me and make quips.&lt;/p&gt;

&lt;p&gt;I’ve also been very appreciative of Blizzard’s interactions with the community. Jeff Kaplan has been very responsive to fan requests, such as when someone asked for the Halloween event’s Junkrat voice lines to replace the standard lines when you equipped Junkrat’s Halloween skin. Kaplan’s response was a simple “ok,” then shortly after the update was made that granted the request. They’ve also been super generous with the free updates to the game that add new skins, sprays, victory poses, and emotes. Each event, I’ve been excited to earn a couple particular skins, and it gives me more reason to play the game.&lt;/p&gt;

&lt;p&gt;Overwatch has become my go-to game. It’s a great change of pace from my usual story-driven singleplayer games like Dragon Age, and each match feels different because you’re playing with other people. I enjoyed Diablo III when it came out and occasionally pick it up again, but it never felt as exciting as Overwatch. Even when I grouped with others in Diablo, it was never as social as Overwatch because there wasn’t built-in voice chat. It’s great to be able to shout out “Reaper behind” and see my team respond, or to strike up a conversation in text chat while you’re waiting to respawn.&lt;/p&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2016/12/symmetra-legendary.jpg&quot; title=&quot;Clearly MVP with that shield uptime&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2016/12/symmetra-legendary-400x0-698525.jpg&quot; alt=&quot;Clearly MVP with that shield uptime&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I recommend Overwatch to everyone that I find out is a gamer. The fact that I don’t enjoy competitive shooters and yet I still feel effective and have fun playing Overwatch is a great selling point. I think it was well worth the base price of $40 even before they started adding new content, but they keep adding new modes and iterating on the gameplay, fine-tuning the characters, so it’s an even better deal now.&lt;/p&gt;
</description>
				<pubDate>Sun, 18 Dec 2016 00:00:00 -0600</pubDate>
				<link>/2016/12/18/overwatch-review/index.html</link>
				<guid isPermaLink="true">/2016/12/18/overwatch-review/index.html</guid>
			</item>
		
			<item>
				<title>upgrading to Jekyll 3</title>
				<description>&lt;p&gt;I went down a 🐇 hole yesterday when I decided I wanted to try a new CSS framework. It started innocently enough, I found &lt;a href=&quot;https://siimple.github.io&quot;&gt;Siimple&lt;/a&gt; and figured I’d give it a try here. Siimple has SCSS files so I wanted to import them directly rather than used their minified distribution CSS. However, I got &lt;a href=&quot;https://github.com/siimple/siimple/issues/4&quot;&gt;an error&lt;/a&gt; running Jekyll 2 when importing their SCSS. Though I filed an issue on their repo, I figured maybe it was a problem that would go away if I updated my Jekyll version. I used Chase’s handy &lt;a href=&quot;https://github.com/chaserx/gems-cli&quot;&gt;gems-cli&lt;/a&gt; tool to grab the latest version of Jekyll to put in my Gemfile and, while I was at it, I updated nokogiri, kramdown, coderay, mini_magick, rake, and mechanize, too. I figure if you’re going to upgrade a gem, go big or go home, right?
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;After updating all my gems, I got a few deprecation warnings about how I was configuring Kramdown. I updated my configuration from this:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-coderay&quot;&gt;&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line-numbers&quot;&gt;&lt;pre&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;
&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;
&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;
&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;
&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;key&quot;&gt;kramdown&lt;/span&gt;:
  &lt;span class=&quot;key&quot;&gt;use_coderay&lt;/span&gt;: &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;content&quot;&gt;true&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;key&quot;&gt;coderay&lt;/span&gt;:
    &lt;span class=&quot;key&quot;&gt;coderay_line_numbers&lt;/span&gt;: &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;content&quot;&gt;nil&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;comment&quot;&gt;# nil|inline|list|table&lt;/span&gt;
    &lt;span class=&quot;key&quot;&gt;coderay_css&lt;/span&gt;: &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;content&quot;&gt;class&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;comment&quot;&gt;# style|class&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;To this:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-coderay&quot;&gt;&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line-numbers&quot;&gt;&lt;pre&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;
&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;
&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;
&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;
&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;key&quot;&gt;kramdown&lt;/span&gt;:
  &lt;span class=&quot;key&quot;&gt;enable_coderay&lt;/span&gt;: &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;content&quot;&gt;true&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;key&quot;&gt;syntax_highlighter_opts&lt;/span&gt;:
    &lt;span class=&quot;key&quot;&gt;line_numbers&lt;/span&gt;: &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;content&quot;&gt;table&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;comment&quot;&gt;# inline|table&lt;/span&gt;
    &lt;span class=&quot;key&quot;&gt;css&lt;/span&gt;: &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;content&quot;&gt;class&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;comment&quot;&gt;# style|class&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;I couldn’t seem to turn off line numbers entirely, but the original reason I’d done so was the numbers would copy when you tried to copy a block of code. Choosing the ‘table’ option fixes that problem, so I’m happy to leave line numbers turned on.&lt;/p&gt;

&lt;p&gt;However, even with deprecation warnings fixed, I was getting a ‘stack level too deep’ error from Jekyll and it would fail without running the server. I tried disabling all my plugins; nope, still broken. I tried removing some plugins and replacing them with gems, such as using &lt;a href=&quot;https://github.com/jekyll/jekyll-archives&quot;&gt;jekyll-archives&lt;/a&gt; for having tag and category archive pages. Nope, still broken. I added new gems that weren’t required with Jekyll 2, such as &lt;a href=&quot;https://jekyllrb.com/docs/pagination/&quot;&gt;jekyll-paginate&lt;/a&gt; and &lt;a href=&quot;https://github.com/jekyll/jekyll-coffeescript&quot;&gt;jekyll-coffeescript&lt;/a&gt;; nope, still broken. I tried removing and updating some of my _config.yml flags… nope, still broken.&lt;/p&gt;

&lt;p&gt;I decided to create a brand new Jekyll site and copy over 3till7.net’s content until the new site broke. However, I had a .ruby-version file in 3till7.net for some reason I can’t remember, and when I created a new Jekyll site, there was no .ruby-version. So the new site was using a later version of Ruby on my computer. It failed trying to install therubyracer, which was necessary because I use the &lt;a href=&quot;https://github.com/slashdotdash/jekyll-lunr-js-search&quot;&gt;jekyll-lunr-js-search&lt;/a&gt; gem.&lt;/p&gt;

&lt;p&gt;I was getting an error about “dyld: lazy symbol binding failed: Symbol not found” which is certainly something I’ve seen before. Like every other time therubyracer has flipped out, I was able to fix it with a combination of uninstalling and reinstalling packages while passing in special flags to use system libraries. This was what eventually did it for me in El Capitan:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem uninstall libv8
gem uninstall therubyracer
gem install libv8 -- --with-system-v8
gem install therubyracer -- --with-v8-dir=/usr/local/opt/v8-315
bundle config --local build.libv8 --with-cxx=/usr/local/bin/g++-4.2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After I got the new Jeyll site’s dependencies installed, I was able to run it with no problems. After copying over a few posts and the plugins they needed, I was able to reproduce the “stack level too deep” error. It turned out to be my &lt;a href=&quot;https://github.com/vlamy/jekyll-lightbox-tag&quot;&gt;jekyll-lightbox-tag&lt;/a&gt; configuration. The plugin has the following:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line-numbers&quot;&gt;&lt;pre&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;
&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;comment&quot;&gt;# Prevent Jekyll from erasing our generated files&lt;/span&gt;
site.config[&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;keep_files&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;/span&gt;] &amp;lt;&amp;lt; settings[&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;/span&gt;] &lt;span class=&quot;keyword&quot;&gt;unless&lt;/span&gt; site.config[&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;keep_files&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;/span&gt;].include?(settings[&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;/span&gt;])
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;I modified it to &lt;code&gt;puts settings['output']&lt;/code&gt; and it was adding &lt;code&gt;'.'&lt;/code&gt;, which is just what I had told it to do in my _config.yml:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-coderay&quot;&gt;&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line-numbers&quot;&gt;&lt;pre&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;
&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;key&quot;&gt;lightbox&lt;/span&gt;:
  &lt;span class=&quot;key&quot;&gt;output&lt;/span&gt;: &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;content&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;My original goal with setting that directory for generated output was to have generated images put in the same place as their originals. However, as a quick fix to get around &lt;em&gt;not being able to build my site at all&lt;/em&gt;, I removed the &lt;code&gt;output&lt;/code&gt; option. Jekyll was giving me a different error now, which meant progress! Now the Lightbox plugin stores generated images in a generated/ directory, which I can live with.&lt;/p&gt;

&lt;p&gt;I was getting an error about “Yikes! It looks like you don’t have pygments” though how syntax highlighting was ever working with my old Jekyll 2 site if Pygments wasn’t available is beyond me. I tried &lt;code&gt;pip install Pygments&lt;/code&gt; but didn’t have pip. I fixed that with:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;brew install python
pip install Pygments
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;However, once Pygments was installed, Jekyll still gave me the same error about not finding Pygments. What do you mean, I just installed it! I fixed this via &lt;code&gt;gem install pygments.rb&lt;/code&gt; and then also adding &lt;code&gt;gem 'pygments.rb', '~&amp;gt; 0.6.3'&lt;/code&gt; so I’d get the gem installed later if I tried to work on a different machine.&lt;/p&gt;

&lt;p&gt;The next error preventing Jekyll from building successfully was my use of the Siimple SCSS files. I switched back to my old layout temporarily since it wasn’t using Siimple. Now my site was building and my syntax was highlighted!&lt;/p&gt;

&lt;p&gt;The next problem was every time I would save a file and cause the site to rebuild, it wouldn’t actually complete because of an error with Jekyll::Converters::Markdown while converting my About page. So I’d have to Ctrl-C Jekyll and run it again, which would succeed. There’s nothing special in about.md, so I couldn’t see why that page was the problem. I banged about, trying different things like reducing the contents of about.md and disabling plugins again, but I couldn’t fix it. I thought maybe I could turn off auto-rebuilding, but I couldn’t seem to, even when I didn’t pass Jekyll the &lt;code&gt;-w&lt;/code&gt; flag. What I ended up doing was dropping my Jekyll version back from 3.1.2 to 3.0.3. Now the whole site builds when you first start Jekyll as well as when you update a page.&lt;/p&gt;

&lt;p&gt;By this point, the Siimple maintainers had responded to the issue I filed, saying &lt;a href=&quot;https://github.com/siimple/siimple/issues/4#issuecomment-207815089&quot;&gt;there was a problem on their end&lt;/a&gt; but they had a fix for me. I used their updated SCSS files and Jekyll was happy with them. So I guess I needn’t have updated from Jekyll 2 at all, since going to Jekyll 3 didn’t help me use the original Siimple SCSS. I’m glad I got the site updated, though, since Jekyll 3 seems to be faster about rebuilding than Jekyll 2 was.&lt;/p&gt;

&lt;p&gt;And that’s my long story of how I updated to Jekyll 3 to try and parse invalid SCSS but that didn’t work and instead introduced a whole slew of other issues to fix but then the bad SCSS got fixed and the upgrade issues got fixed so now 3till7.net is on Jekyll 3 &lt;em&gt;and&lt;/em&gt; using Siimple’s SCSS so it all worked out after all. 👌&lt;/p&gt;
</description>
				<pubDate>Sun, 10 Apr 2016 00:00:00 -0500</pubDate>
				<link>/2016/04/10/upgrading-to-jekyll-3/index.html</link>
				<guid isPermaLink="true">/2016/04/10/upgrading-to-jekyll-3/index.html</guid>
			</item>
		
			<item>
				<title>Stardew Valley is wonderful</title>
				<description>&lt;p&gt;I kept hearing about &lt;a href=&quot;http://store.steampowered.com/app/413150/&quot;&gt;Stardew Valley&lt;/a&gt;
on Reddit as well as seeing friends on Steam playing it. It was priced at $15 with an extra $5 to get the soundtrack. I very rarely dislike video game
soundtracks so of course I had to get the soundtrack, too. I wasn’t sure how well I’d like the actual game, but &lt;a href=&quot;https://www.reddit.com/r/GirlGamers/search?q=stardew+valley&amp;amp;restrict_sr=on&amp;amp;sort=relevance&amp;amp;t=all&quot;&gt;/r/girlgamers&lt;/a&gt; was
talking about it and it sounded cute, with $15 being cheap enough that I was
willing to give it a shot, especially to support an indie game. The few
screenshots I’d seen put Minecraft in mind because of the item bar across the
bottom of the screen, and there was a pickaxe. So whatever, I figured I’d try
it.
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2016/04/stardew-valley-1.jpg&quot; title=&quot;Raiding the trash can&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2016/04/stardew-valley-1-400x0-a59d2d.jpg&quot; alt=&quot;Raiding the trash can&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since then, I’ve put in 74 hours and I love the game. It’s such an appealing
blend of Minecraft, Animal Crossing, and Harvest Moon. Some of the things you
can do include:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Like Minecraft&lt;/th&gt;
      &lt;th&gt;Like Harvest Moon&lt;/th&gt;
      &lt;th&gt;Like Animal Crossing&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Mine for ore&lt;/td&gt;
      &lt;td&gt;Grow crops&lt;/td&gt;
      &lt;td&gt;Attend festivals&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Chop trees&lt;/td&gt;
      &lt;td&gt;Befriend villagers&lt;/td&gt;
      &lt;td&gt;Buy upgrades to your house&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Craft items&lt;/td&gt;
      &lt;td&gt;Marry someone&lt;/td&gt;
      &lt;td&gt;Fish&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Kill monsters&lt;/td&gt;
      &lt;td&gt;Raise livestock&lt;/td&gt;
      &lt;td&gt;Have buildings built&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Smelt ingots&lt;/td&gt;
      &lt;td&gt;Sell produce&lt;/td&gt;
      &lt;td&gt;Decorate your home&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Cook&lt;/td&gt;
      &lt;td&gt;Give gifts&lt;/td&gt;
      &lt;td&gt;Do favors for villagers&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;Collect mushrooms&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;Donate items to the museum&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;Gather seashells&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;Upgrade tools&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Despite having played for so long, I’m still discovering things. I’ve been
talking with friends who play it and they have buildings I don’t, they’ve done
things I haven’t. It’s very cool that the game has the same villagers and
layout for everyone, but how you make money is up to you. Stardew Valley has
some RPG elements to it, including customizing your appearance and leveling up
skills. There are other choices as well that have a permanent effect on your
game, outside of which skill enhancements to take, such as when a scientist
asks if you’d rather foster some bats in the cave on your property or cultivate
mushrooms.&lt;/p&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2016/04/stardew-valley-3.jpg&quot; title=&quot;Abigail talking about our cave&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2016/04/stardew-valley-3-400x0-7ea9c7.jpg&quot; alt=&quot;Abigail talking about our cave&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My personal choice for earning money was to take the Artisan skill and sell lots of mayonnaise. My chickens and ducks lay eggs, I pop the eggs into my mayonnaise machines, and I sell the resulting mayo for 💰. I also do a lot of pickling and make jelly from all the crops I grow. My cows and goats produce milk which I turn into cheese to sell. I also make wine and beer with my many kegs.&lt;/p&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2016/04/stardew-valley-4.jpg&quot; title=&quot;My overnight earnings&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2016/04/stardew-valley-4-400x0-f0c56e.jpg&quot; alt=&quot;My overnight earnings&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Besides trying to make money to further improve your farm, you can also work to improve the village down the road. There’s a rundown community center with mysterious creatures who get really excited when you donate various items that fix parts of the building. Once you’ve turned in enough items, some previously broken feature of the town will be restored, such as the broken-down minecarts located around the town. Restoring the minecarts gives you a fast travel option that helps you get around.&lt;/p&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2016/04/stardew-valley-2.jpg&quot; title=&quot;Restoring the community center&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2016/04/stardew-valley-2-400x0-8f7e95.jpg&quot; alt=&quot;Restoring the community center&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Buying the soundtrack 🎵 was a good choice as well because it’s so pleasant. I
uploaded it to my Google Play library so I can listen to it while I work. My
favorite track is Summer (The Sun Can Bend An Orange Sky).&lt;/p&gt;

&lt;p&gt;There’s also a library/museum combo where you can donate interesting rocks and artifacts you find. I treated this like I do the museum in Animal Crossing: if I find a thing I haven’t yet donated to the museum, I donate it, even if I know I could sell it for a high price. This paid off in Stardew Valley because you get rewards from the librarian/curator periodically for your donations. You’ll also find lost library books scattered around, often buried in the ground where you have to use your hoe to dig them up. Finding these books lets you read them at the library, where they teach you secrets such as when to catch rare fish.&lt;/p&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2016/04/stardew-valley-5.jpg&quot; title=&quot;Donations at the museum&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2016/04/stardew-valley-5-400x0-4e41e6.jpg&quot; alt=&quot;Donations at the museum&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I love that there are enough things to do in a day that I don’t have time to do them all. Wake up, collect eggs and milk, feed the livestock, harvest crops, put water in the cat’s bowl, talk to the spouse, refill all the kegs and preserves jars, repair fences, and then I’m free to go to town, the beach, the mines, the desert, the forest… By the time I’ve finished the morning chores on the farm, it’s early afternoon. Maybe I want to go down to the beach and check my crab pots, gather shells, and fish off the dock. Maybe I want to go to the mines to get more coal and ore so I can make more preserves jars and kegs for earning more money from my produce. Maybe I want to gather wild plants in the forest and kill some slimes.&lt;/p&gt;

&lt;p&gt;I also love the characters in the game. There are some serious and touching conversations that happen, and I genuinely like the different villagers. Even the grouchy old man comes around after a while. You get cut scenes when you reach different milestones in your relationships, and it’s pretty cool seeing a cut scene in a pixel art game instead of an ultra-realistic, graphics-intense game.&lt;/p&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2016/04/stardew-valley-6.jpg&quot; title=&quot;Finding Linus raiding the trash cans&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2016/04/stardew-valley-6-400x0-d985c4.jpg&quot; alt=&quot;Finding Linus raiding the trash cans&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I appreciate that the game lets you romance people regardless of gender. There’s a biracial family where the African American father is a scientist. The town carpenter is a woman. There’s a character in a wheelchair, and Linus (shown in the above screenshot) is homeless. Pam and Shane appear to have problems with alcohol. For the first year, one character isn’t present because he’s off in the army. So the town isn’t just happy cookie-cutter families.&lt;/p&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2016/04/stardew-valley-7.jpg&quot; title=&quot;Marrying Abigail&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2016/04/stardew-valley-7-400x0-64d214.jpg&quot; alt=&quot;Marrying Abigail&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stardew Valley feels open-ended enough where I don’t feel pressured down one particular path, but at the same time I have goals. That’s a problem I have that makes me grow bored with Minecraft after a while: I run out of ideas for what to do next. In Stardew Valley, I’m aware of new buildings I haven’t built yet, upgrades for my existing buildings, quests I’ve not completed, relationships I’ve not maxed out meaning cut scenes I’ve not seen, tools I’ve not upgraded, levels of the mine I’ve not reached, recipes I’ve not made, fish I’ve not caught, sections of the community center I’ve not restored… Basically, it’s not just a big open world where everything is fine the way it is, there is noticeable room for improvement and it drives me to fix things.&lt;/p&gt;

&lt;p&gt;I’ve happily paid $50-60 in the past for new Animal Crossing games. Stardew Valley and its soundtrack are well worth the $20. I’ve gotten so much play time out of it so far, and I know I’ll be playing for many more hours. It’s a great game, and I really recommend it.&lt;/p&gt;
</description>
				<pubDate>Sat, 02 Apr 2016 00:00:00 -0500</pubDate>
				<link>/2016/04/02/stardew-valley-is-wonderful/index.html</link>
				<guid isPermaLink="true">/2016/04/02/stardew-valley-is-wonderful/index.html</guid>
			</item>
		
			<item>
				<title>making a Philips Hue home</title>
				<description>&lt;p&gt;Jon has done a great job getting our house wired up with Philips Hue lights. I’ve really enjoyed having them and with the right devices, they’re very convenient. I love the bits of color and how much control we have over brightness compared with regular bulbs that don’t have dimmer switches. I wouldn’t have known where to get started, so I wanted to write up the products we’ve bought and our experience with lights and devices.
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;We use a single &lt;a href=&quot;http://www2.meethue.com/en-us/productdetail/philips-hue-bridge&quot;&gt;bridge&lt;/a&gt; that controls all Hue lights in the house. It’s located in a fairly central room and we haven’t had any problem with the bridge failing to reach a light. The only snag is when you initially add a light, it can take some time before the bridge recognizes it.&lt;/p&gt;

&lt;p&gt;In our dining room, we went with &lt;a href=&quot;http://www2.meethue.com/en-us/productdetail/philips-hue-white-extension-bulb-a19&quot;&gt;A19 bulbs&lt;/a&gt;. These are used just for giving good light over the table. For color, we use a &lt;a href=&quot;http://www2.meethue.com/en-us/productdetail/philips-hue-lightstrip-plus&quot;&gt;lightstrip&lt;/a&gt; stuck along the inside lip of the table. Jon isn’t sold on the placement but I like it. I think it works well seeing a glow of color on the chair seats and the floor under the table.&lt;/p&gt;

&lt;p&gt;In our office with the computers, we have two &lt;a href=&quot;http://www2.meethue.com/en-us/productdetail/philips-hue-bloom&quot;&gt;bloom lights&lt;/a&gt; sitting atop speakers. They’re fairly high up the wall and in the corners so the light casts a glow into the corner. We also have a single &lt;a href=&quot;http://www2.meethue.com/en-us/productdetail/philips-hue-white-and-color-ambiance---extension-bulbs&quot;&gt;BR30 bulb&lt;/a&gt; in a ceiling fixture for the majority of the light in the room and the option for more color.&lt;/p&gt;

&lt;p&gt;In our living room, we have two BR30s in the ceiling for adequate lighting and then two lightstrips around the back edge of our flatscreen. This produces a really cool effect of soft color glowing behind the TV. The TV is angled in a corner and the light fills the whole corner.&lt;/p&gt;

&lt;p&gt;In the kitchen, over the sink we have a single &lt;a href=&quot;http://www2.meethue.com/en-us/productdetail/philips-hue-white-and-color-ambiance---extension-bulbs&quot;&gt;GU10&lt;/a&gt; which is sufficient for the sink and countertop area. We have another BR30 to sufficiently light the kitchen as well as provide color.&lt;/p&gt;

&lt;p&gt;Our hallway is lit by three A19s which is more than enough light for the small hallway that it is.&lt;/p&gt;

&lt;p&gt;Both bedrooms are lit by more A19s. The bathroom has a row of &lt;a href=&quot;http://www.amazon.com/Philips-433714-Personal-Wireless-Lighting/dp/B00O0EZ94O&quot;&gt;A19 Lux bulbs&lt;/a&gt; over the sink that we usually keep in white or pale yellow shades. There’s one GU10 in the ceiling fixture over the shower which is a fun placement. You can make a blue ocean theme just inside the shower using that bulb.&lt;/p&gt;

&lt;p&gt;We’ve had good luck with a &lt;a href=&quot;http://www2.meethue.com/en-us/productdetail/philips-hue-tap-switch&quot;&gt;tap switch&lt;/a&gt; in the living room. We set up a general-purpose scene on the big button (the whole face of the switch); this is good for reading and just relaxing. The leftmost button turns on brighter lights. The bottommost button is a scene which turns off lights in the ceiling and surrounding rooms while setting the lightstrips on the back of the TV to dim colors. The rightmost button turns off all living room lights.&lt;/p&gt;

&lt;p&gt;We use another tap switch in the bathroom. The big whole-face button is intended for nighttime use when you’re half asleep and just swatting at the switch. It turns on the shower light in a dim red color and turns on just a single light over the sink, also very dim. The leftmost button is a general-purpose scheme with all bathroom lights on and the one over the shower set to a nice aqua-tinted color. The bottommost button turns on all bathroom lights but sets the shower light to a deep blue. The rightmost button turns off all bathroom lights.&lt;/p&gt;

&lt;p&gt;We’ve put &lt;a href=&quot;http://www2.meethue.com/en-us/productdetail/philips-hue-dimmer-switch&quot;&gt;dimmer switches&lt;/a&gt; in the other rooms. They’re more conventional with a labeled on button, off button, and buttons for brightening and dimming the lights.&lt;/p&gt;

&lt;p&gt;One problem we were having was instinctively hitting the built-in light switches throughout the house. Philips Hue lights are meant to be left powered on all the time; they’re supposed to regulate their power usage themselves. &lt;a href=&quot;http://www.amazon.com/gp/product/B002X88GYY&quot;&gt;These plastic covers&lt;/a&gt; work really well, clinging via magnets to the metal screws in your switch cover. We placed these over all light switches that control fixtures where we have Philips Hue bulbs.&lt;/p&gt;

&lt;p&gt;Using the iOS app, I set up scenes for use in our most frequented areas. Early Morning is a scene with fairly dim lights in soft greens and browns. I use it when I first wake up and am having my morning tea.&lt;/p&gt;

&lt;p&gt;When noon comes around, I switch to a scene called Taj that’s based on a photo of the Taj Mahal. It mixes some natural light colors with blues, yellows, and browns. This scene is brighter and we use it throughout the day.&lt;/p&gt;

&lt;p&gt;After dark, I switch to my Sunset theme which uses deep yellows, oranges, and reds that are pretty dim. The dimmer switches are useful here to make a room brighter or dimmer while still keeping the colors of the scene.&lt;/p&gt;

&lt;p&gt;We’ve found it convenient to have a dimmer switch in the bedroom on our nightstand. The switches come with sticky pads on the back so you can mount them to the wall, which we’ve done in most places, but it’s helpful to have one by the bed so you can shut off all lights in the house conveniently.&lt;/p&gt;

&lt;p&gt;Having programmable lights throughout the house is very flexible. We were able to set up a switch by the door that turns on lights in nearby rooms. That would have required rewiring the house to do that with conventional lights. I love changing colors, turning off all lights, and grouping lights via the app. These lights should be more energy efficient and longer lasting than incandescent or even compact fluorescent bulbs, which helps justify their price. I’ve also started using the &lt;a href=&quot;https://github.com/peter-murray/node-hue-api&quot;&gt;Node.js library&lt;/a&gt; for interacting with our Hue lights. I want to do something cool probably using Steam screenshots or Instagram photos as I post them to change lights around the house.&lt;/p&gt;
</description>
				<pubDate>Sun, 14 Feb 2016 00:00:00 -0600</pubDate>
				<link>/2016/02/14/making-a-philips-hue-home/index.html</link>
				<guid isPermaLink="true">/2016/02/14/making-a-philips-hue-home/index.html</guid>
			</item>
		
			<item>
				<title>Candyfair app</title>
				<description>&lt;p&gt;Halloween season came around and with it came big bags of candy at the office. Some candies disappeared faster than others, leading exclamations like “aww all the Twix are gone!” or “there’s nothing but stupid 3 Musketeers left” to be heard around the office. &lt;a href=&quot;http://summasmiff.github.io/&quot;&gt;Summer&lt;/a&gt; remarked that we needed an app to tell us how best to divide the candy so that no one who didn’t want stupid 3 Musketeers would be forced to eat them, and the weirdos who actually like 3 Musketeers could revel in their abundance. Enter my next pet project.
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2015/11/candyfair-logo.png&quot; alt=&quot;Candyfair logo, created by Summer.&quot; /&gt;
&lt;span class=&quot;caption&quot;&gt;Candyfair logo, created by &lt;a href=&quot;http://summasmiff.github.io/&quot;&gt;Summer&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;I knew I needed a database to keep track of all the candy, plus let users give their candy preferences. I went with a Rails app since I knew it would be fastest for me to get going, since I’m most familiar with Rails as a platform for basic &lt;acronym title=&quot;Create Read Update Delete&quot;&gt;CRUD&lt;/acronym&gt; apps. I basically wanted to make an app that would let a group of people see each other’s candy opinions, as well as let individuals rate each candy. I wanted the rating process to be fun, and I had the idea for a range of smiley faces as indicators of how much you liked a candy.&lt;/p&gt;

&lt;p&gt;I figured I’d deploy to Heroku because I always deploy to Heroku, again because it’s the fastest, most convenient option when deploying my own little apps. So I went ahead and set up the app with a PostgreSQL database since that works well on Heroku. I hadn’t fiddled with PostgreSQL on my MacBook since upgrading to El Capitan, but it wasn’t hard using Homebrew.&lt;/p&gt;

&lt;p&gt;The first thing was figuring out my data model, which is one of my favorite parts of any new project that involves a database. I knew I wanted accounts, so I got going with Devise for authentication, which necessitated a users table. I customized Devise a bit, going with a username field instead of email because I wanted a single login for my whole office to use, and I wanted it to match that of an app &lt;a href=&quot;https://github.com/millidavids&quot;&gt;David&lt;/a&gt; built for us.&lt;/p&gt;

&lt;p&gt;This deviation from the Devise default of using an email address actually led to a bug because of an oversight on my part. &lt;a href=&quot;http://asiansteev.tumblr.com/&quot;&gt;Steve&lt;/a&gt; helpfully caught &lt;a href=&quot;https://github.com/cheshire137/candyfair/issues/14&quot;&gt;the bug&lt;/a&gt; which allowed a user to register a new account with a blank password, but then you couldn’t log back in after you’d logged out. This happened because I couldn’t use &lt;code&gt;devise :validatable&lt;/code&gt; in my User model because that validates that the email is provided when signing up, but it also validates a password is given. So I had to manually add some password validation logic to the User model, along with validation for my custom username field that replaced the email field.&lt;/p&gt;

&lt;p&gt;I added a candies table and tied each candy to a user account. I did this thinking some non-American might try the app someday and not give a hoot about our silly American candies, or they might think that Smarties are some &lt;a href=&quot;https://en.wikipedia.org/wiki/Smarties&quot;&gt;chocolate candy made by Nestlé&lt;/a&gt; instead of those powdery things found in the US. So each user account gets their own set of candies, though I do have users by default get a predefined selection of American candies for them to rate.&lt;/p&gt;

&lt;p&gt;There’s a people table and each user account can have many people. This is how I have a single account for my office and all my coworkers are included in it. I went with something simple like this because I knew strict access control wasn’t a concern. It works on the honor system, each person only setting their own preferences. If you were using the app with your rambunctious children, you might have a problem where one child sets the other’s preferences for him so as to ensure their brother gets all the terrible candies, for example. This hasn’t been a problem at my office… yet.&lt;/p&gt;

&lt;p&gt;The preferences table ties a person to a candy with a rating of like, love, hate, or dislike. If you are indifferent towards a candy, you just don’t have a preference table entry at all for it. &lt;a href=&quot;https://github.com/cheshire137/candyfair/issues/11&quot;&gt;Summer&lt;/a&gt; proposed distinguishing between indifference and just not having rated a candy yet, and I agree it would be helpful. I’d like to show a list, for example, of which candies people have not yet rated.&lt;/p&gt;

&lt;p&gt;The major feature of the app was to tell the user how to divide their hypothetical trick-or-treat bag of candy in a way that pleases everyone. I did this by adding a few scopes to my Candy model:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;&lt;code&gt;favored_by_one&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;All candies that are only liked or loved by a single person. I display these all listed together with the suggestion that they all be given to that one person:&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2015/11/candyfair-graham.png&quot; alt=&quot;How many licks does it take?&quot; /&gt;
&lt;span class=&quot;caption&quot;&gt;How many licks does it take?&lt;/span&gt;&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;&lt;code&gt;favored_by_many&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;All candies that are liked or loved by multiple people. If the candies are all liked or all loved, I suggest they be split evenly among the people. If the reviews are mixed, though, with one or more people loving the candy while the remainder like it, I suggest they all get some of the candy, but whoever loves the candy should get a bit more. &lt;a href=&quot;http://nwarner.com/&quot;&gt;Nick&lt;/a&gt; made the suggestion that pickier eaters — those who have more dislikes and hates than likes and loves — should be favored when distributing candy, which I’m considering.&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2015/11/candyfair-circus-peanuts.png&quot; alt=&quot;This arrangement suits me just fine.&quot; /&gt;
&lt;span class=&quot;caption&quot;&gt;This arrangement suits me just fine.&lt;/span&gt;&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;&lt;code&gt;favored_by_none&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Candies that have been rated, but that no one likes or loves. The app suggests you throw these in the trash. 😝&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;Another fun part of the app is the Trends page. It lists the most popular, least popular, and most divisive candies. At our office, the most popular candies include Kit Kat, Sour Patch Kids, and Reese’s Cups. I’m a bit surprised by a sour gummy candy beating out tried-and-true chocolate, but there you are. The most unpopular candies include Circus Peanuts (of course), Necco Wafers, and Milk Duds (???).&lt;/p&gt;

&lt;p&gt;The divisive candies are fun because they’re candies that are rated favorably and unfavorably by the same number of people. These include Laffy Taffy, Hershey’s Kisses, and Jolly Ranchers. Jolly Ranchers seem innocuous enough, but anyone actually liking Laffy Taffy kind of confuses me. That stuff will rip your teeth out!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2015/11/candyfair-bullshit-circus-peanuts.png&quot; alt=&quot;47% of people haven't actually tried them.&quot; /&gt;
&lt;span class=&quot;caption&quot;&gt;47% of people haven’t actually tried them.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Finally, I tried a new gem with Candyfair: &lt;a href=&quot;https://rubygems.org/gems/wikipedia-client/versions/1.5.0&quot;&gt;wikipedia-client&lt;/a&gt;. I wanted to add photos of each candy, especially since &lt;a href=&quot;https://github.com/jgrowl&quot;&gt;Jon&lt;/a&gt; pointed out he didn’t know what some of the candies even were. I was faced with the conundrum that users could add their own candies, and I didn’t want to host a bunch of images or make the user enter image URLs. The Wikipedia gem let me add both a photo and a brief blurb about each candy, as pulled from the Wikipedia API:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2015/11/candyfair-wikipedia.png&quot; alt=&quot;Milky Way the galaxy or the chocolate bar?&quot; /&gt;
&lt;span class=&quot;caption&quot;&gt;Milky Way the galaxy or the chocolate bar?&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;There were a couple of hurdles: not every candy has its own Wikipedia page, most notably individual Little Debbie cakes, and not every candy can be found on a page of the same name on Wikipedia. So I added two extra fields to the candies table: &lt;code&gt;wikipedia_title&lt;/code&gt; and &lt;code&gt;skip_wikipedia&lt;/code&gt;. When you visit a candy’s page on Candyfair, it makes an AJAX request to my Rails app which uses the gem to hit up Wikipedia for a page for that candy. If &lt;code&gt;wikipedia_title&lt;/code&gt; is set, it will search for that, otherwise, it searches for the candy’s name. If &lt;code&gt;skip_wikipedia&lt;/code&gt; is set, no AJAX request is ever made and no Wikipedia info is shown.&lt;/p&gt;

&lt;p&gt;So that’s Candyfair, a fun little app I built between October 27 and November 3, so just a little over a week. The source code is all on Github and it’s deployed on Heroku if you want to try it out. &lt;a href=&quot;https://github.com/cheshire137/candyfair/pulls&quot;&gt;Pull requests&lt;/a&gt; accepted, if you want to contribute!&lt;/p&gt;
</description>
				<pubDate>Fri, 06 Nov 2015 00:00:00 -0600</pubDate>
				<link>/2015/11/06/candyfair-app/index.html</link>
				<guid isPermaLink="true">/2015/11/06/candyfair-app/index.html</guid>
			</item>
		
			<item>
				<title>Apple Music so far</title>
				<description>&lt;p&gt;I’m pretty fickle when it comes to music subscription services; I like to try them all. I’ve used Pandora, Rdio, Google Music, and Spotify. I had no particular reason to switch to Apple Music when it came out because Spotify works so perfectly. &lt;a href=&quot;https://www.spotify.com/us/legal/privacy-policy/?version=1.0.0-GB&quot;&gt;Then came&lt;/a&gt; &lt;a href=&quot;http://www.forbes.com/sites/thomasbrewster/2015/08/20/spotify-creepy-privacy-policy/&quot;&gt;the reports&lt;/a&gt; &lt;a href=&quot;http://www.bbc.com/news/technology-34016658&quot;&gt;about Spotify’s&lt;/a&gt; &lt;a href=&quot;http://musically.com/2015/08/21/daniel-ek-minecraft-notch-spotify-privacy-policy/&quot;&gt;recent privacy&lt;/a&gt; &lt;a href=&quot;https://news.spotify.com/us/2015/08/21/sorry-2/&quot;&gt;policy changes&lt;/a&gt;; I decided to try Apple Music after all.
&lt;!--more--&gt;&lt;/p&gt;

&lt;h2 id=&quot;what-i-like&quot;&gt;What I Like&lt;/h2&gt;

&lt;dl&gt;
  &lt;dt&gt;Radio stations&lt;/dt&gt;
  &lt;dd&gt;I often don’t know exactly what I want to hear, I just want something pleasant in the background while I work or drive. I use radio stations heavily on streaming music services for this reason. I think the quality of stations on Apple Music is very good. I’ve mainly played with built-in stations like Chill, Soundsystem, and Beats 1 so far, not custom stations based on artists and songs.&lt;/dd&gt;
  &lt;dt&gt;‘For You’ section&lt;/dt&gt;
  &lt;dd&gt;I like that hearting songs seems to result in more music suggestions in the For You section of iTunes. It’s very helpful for this to include full albums as well as playlists like “Intro to Justin Vernon”, “Inspired by Björk”, and “The Knife: Influences.” This section has been great when I want to quickly find something to play when I’m getting in the car in the morning, or when it’s my turn to control the upstairs speakers at work.&lt;/dd&gt;
  &lt;dt&gt;Siri support&lt;/dt&gt;
  &lt;dd&gt;It has been very helpful in the car to use Siri to play music. If I want to hear a particular song, or just any music by a given artist, I can speak into my iPhone much faster than having a passenger type and search through the app, or waiting till a stop light to do it myself. She’s pretty good at recognizing what I want. I was able to tell her “play churches” and she interpreted that correctly as “play CHVRCHES.” As long as I’m using an iPhone, Apple Music is going to rank higher than any other music app for this reason alone.&lt;/dd&gt;
  &lt;dt&gt;Music backup plus music streaming&lt;/dt&gt;
  &lt;dd&gt;I liked Google Music because it let me back up my local library as well as stream music I don’t own. Spotify, Rdio, and Pandora are just streaming only, and it turns out it’s nice to have all your music in one place. I have albums like &lt;a href=&quot;https://archive.org/details/AURAL01&quot;&gt;Vault Archives by Mark Morgan&lt;/a&gt; that you won’t find in any streaming catalogue, and I like not having to switch apps when I want to play it versus play the latest Halsey album that’s available to stream.&lt;/dd&gt;
  &lt;dt&gt;It generally works&lt;/dt&gt;
  &lt;dd&gt;Both iTunes on my Mac and the app on my iPhone are basically okay. It streams okay in the car and on my Mac at the office, despite the occasional halt in the music for no good reason. I’ve had really good suggestions in For You, and combined with New and Radio, I haven’t had trouble finding things I want to listen to.&lt;/dd&gt;
&lt;/dl&gt;

&lt;h2 id=&quot;what-i-dislike&quot;&gt;What I Dislike&lt;/h2&gt;

&lt;dl&gt;
  &lt;dt&gt;Too many steps to save stuff for later&lt;/dt&gt;
  &lt;dd&gt;In Spotify, I hit the little plus button next to a song that’s playing and it adds it to my library. I can view that as a playlist later and see the most recently added songs first. In Apple Music, the most prominent similar button is a heart, but all that seems to do is inform the songs suggested in For You. There’s no global list of all my hearted songs, and that sucks.&lt;/dd&gt;
  &lt;dt&gt;Songs grayed out on albums&lt;/dt&gt;
  &lt;dd&gt;I frequently see songs that are grayed out in an album even though I know Apple Music has that song available to play.&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2015/09/weeknd-itunes.png&quot; title=&quot;The Weeknd Earned It is grayed out&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2015/09/weeknd-itunes-400x0-055fb3.png&quot; alt=&quot;The Weeknd Earned It is grayed out&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2015/09/fifty-shades-itunes.png&quot; title=&quot;Earned It is available on Apple Music&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2015/09/fifty-shades-itunes-400x0-a25ab9.png&quot; alt=&quot;Earned It is available on Apple Music&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If I look on Spotify, they have the new Weeknd album and Earned It from that album is available to play:&lt;/p&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2015/09/weeknd-spotify.png&quot; title=&quot;Earned It is available on Spotify&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2015/09/weeknd-spotify-400x0-1fd946.png&quot; alt=&quot;Earned It is available on Spotify&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Can Apple not get the same deals as Spotify? Apple needs to step up their game, because it’s really annoying trying to listen to a full album and realizing some of the songs just won’t play. You have to make a playlist of most of the album plus the individual songs from elsewhere.&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Delays when adding to playlists&lt;/dt&gt;
  &lt;dd&gt;Sometimes when I add a song to a playlist on my Mac, if I go back and check the playlist, the song isn’t there. I have to choose Add to &amp;gt; My Playlist a few times before it happens. This is super frustrating because I can’t trust the service. I don’t want to have to tell it repeatedly to be sure it did a thing, nor do I want to keep checking up on it to ensure it did.&lt;/dd&gt;
  &lt;dt&gt;Mixups in albums&lt;/dt&gt;
  &lt;dd&gt;I bought 1989 by Taylor Swift off Amazon and added it to my iTunes Library. While listening to it on my iPhone, it was playing fine, then got to Shake It Off. For some reason, it was playing the karaoke version without lyrics. No way do I own the karaoke version of anything. I hit the previous track button, then hit the next track button, and suddenly it knew to play the correct version of Shake It Off. Likewise while listening to the Roseland NYC live album by Portishead, when it got to Mysterons, it switched to playing the studio version off of Dummy.&lt;/dd&gt;
  &lt;dt&gt;No ‘Shuffle All’ on iPhone&lt;/dt&gt;
  &lt;dd&gt;If I’m driving out in the boonies with no cell signal and I need to play offline-only music, it would be really helpful for me to have a Shuffle All button. I end up with individual songs available offline on my iPhone, and I don’t want to choose them one at a time to play. I’m down to the dregs so I’m not going to be picky here, just play me what you have, iTunes!&lt;/dd&gt;
  &lt;dt&gt;No Last.fm support&lt;/dt&gt;
  &lt;dd&gt;I’ve been scrobbling &lt;a href=&quot;http://www.last.fm/user/cheshire137&quot;&gt;since 2006&lt;/a&gt; and I don’t want to give up that history of music that I’ve built. Spotify has built-in Last.fm scrobbling support in its desktop and mobile apps, but Apple Music does not. On the desktop, I found an abandoned app called Bowtie that works well with iTunes, but I worry about it no longer working in the future. On iPhone, I found QuietScrob, but it only works with music in your library, and doesn’t work at all with radio stations in Apple Music.&lt;/dd&gt;
  &lt;dt&gt;No API&lt;/dt&gt;
  &lt;dd&gt;I have a lot of playlists in Rdio and Spotify that I’d love to migrate to Apple Music, but without an API, there’s no easy way to do so. I saw a couple third-party, paid apps that claim to do this, but I don’t quite trust them because they involve capturing some token from iTunes. I would rather there just be an official Apple Music API that lets me authenticate with OAuth and know exactly what access some third-party app is requesting. I also personally love building music apps myself, and I want to build some that let you do cool things with your Apple Music library.&lt;/dd&gt;
&lt;/dl&gt;

&lt;h2 id=&quot;verdict&quot;&gt;Verdict&lt;/h2&gt;

&lt;p&gt;I have the subscription in iTunes set to auto-renew. $10/month is what I’m used to paying for streaming music, and I’d like to see the improvements Apple will inevitably make — ‘Shuffle All’ is so obvious, they &lt;em&gt;have&lt;/em&gt; to add it, right? — plus Spotify still wigs me out with that privacy policy. “Local law may require that you seek the consent of your contacts to provide their personal information to Spotify” is what it says, “We’re going to use your contacts, lol, make sure we’re not breaking the law” is how it reads to me.&lt;/p&gt;
</description>
				<pubDate>Sun, 06 Sep 2015 00:00:00 -0500</pubDate>
				<link>/2015/09/06/apple-music-so-far/index.html</link>
				<guid isPermaLink="true">/2015/09/06/apple-music-so-far/index.html</guid>
			</item>
		
			<item>
				<title>my Windows 10 upgrade experience</title>
				<description>&lt;p&gt;I saw the little Windows 10 logo show up in my taskbar some few weeks ago, telling me I could reserve a copy of Windows 10 for free. Cool! I did so and waited with excitement for July 29 to come around. It came and went, and my reserved upgrade still wasn’t ready. I saw articles, &lt;a href=&quot;http://www.theguardian.com/technology/2015/jul/31/windows-10-microsoft-faces-criticism-over-privacy-default-settings&quot;&gt;privacy concerns&lt;/a&gt;, Tweets, and a &lt;a href=&quot;http://reddit.com/r/windows10&quot;&gt;whole subreddit&lt;/a&gt; come about, and I felt like &lt;a href=&quot;https://www.reddit.com/r/Windows10/comments/3foevq/is_anyone_still_stuck_waiting_for_their_reserved/&quot;&gt;the last person who wanted to upgrade but hadn’t yet&lt;/a&gt;.
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;Fortunately, the folks on the windows10 subreddit pointed me at the &lt;a href=&quot;http://www.microsoft.com/en-us/software-download/windows10ISO&quot;&gt;Windows 10 Media Creation tool&lt;/a&gt; which lets you upgrade your PC to Windows 10 immediately. It felt a little weird to short-circuit the reservation process, but everyone else seemed to have good luck with the media tool. The Get Windows 10 app had green check marks for everything about my PC, including how much memory I had, which apps I had installed, and other criteria that would affect my upgrade readiness. I went ahead and took the plunge this morning, upgrading my desktop Windows 7 64-bit Professional machine.&lt;/p&gt;

&lt;p&gt;The Media Creation tool downloaded pretty quickly and I chose to upgrade my PC. It went through a few screens of determining readiness, including a long one about “making sure you’re ready to install.” It then showed a summary and asked if I was ready to upgrade. Part of that summary said it was going to keep my files and apps, which sounded right but I had never chosen that option. I clicked for details on that but it just had a couple of options: keep your files and apps, or keep just one or the other. Oh, okay, yeah its default setting was what I wanted. I had to sit through the “making sure you’re ready to install” loading screen again for a few more minutes before I got the chance to start my upgrade.&lt;/p&gt;

&lt;p&gt;Once the upgrade started, it appeared to be a full-screen program in Windows 7 like any other installer. It warned me the computer would restart several times. Finally, the upgrade application closed and my computer restarted. When it booted back up, the Windows 10 logo displayed and it went into an upgrade screen.&lt;/p&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2015/08/windows-10-upgrade.jpg&quot; title=&quot;Windows 10 upgrade progress&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2015/08/windows-10-upgrade-400x0-7e3ac4.jpg&quot; alt=&quot;Windows 10 upgrade progress&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I babysat the upgrade for maybe half an hour this morning before I left for work. When it reached the “Installing features and drivers” portion of the upgrade, a window popped up to let me install some bloatware from Razer because I have a Razer mouse. It was a little unnerving hitting a button labelled “Quit” while in the middle of an operating system upgrade, but I assumed it was just to quit the install for this Razer mouse software that I didn’t want. That dumped me back out to the Windows 10 upgrade screen and things seemed fine. I then left for work, wondering if there’d be any other prompts that would delay the upgrade process until I could get home to handle them.&lt;/p&gt;

&lt;p&gt;When I got home, I was greeted with the Windows 10 login screen. Cool, the upgrade finished without any more hand-holding. I logged in with my local user account that I used in Windows 7. I chose to customize my settings rather than use the express settings so that I could turn off a bunch of the reporting and personalization options. Once I got through that, it put me at my desktop. My wallpaper was the same, my desktop was still covered with all my crap from before, but the taskbar was modern looking and black. It looked like the upgrade had succeeded! Then I tried opening some programs.&lt;/p&gt;

&lt;p&gt;I tried to open Chrome and 1Password 4 and got an error popup about some ‘Agile’ helper thing that I assume is related to 1Password. Fine, 1Password probably needs a reinstall. I noticed in my taskbar that the Dropbox icon was missing, so I tried to start Dropbox but it wouldn’t start. Okay, reinstall Dropbox too. My first task was to track down how to uninstall an application. I found it under the Start Menu &amp;gt; Settings and was able to sort of uninstall Dropbox. At least, I selected Dropbox and hit the Uninstall button. Nothing more seemed to happen. I didn’t get a confirmation, I didn’t see an uninstaller application launch, the list didn’t refresh after a few minutes to show that Dropbox was no longer there. Whatever, I figured I’d just install Dropbox and let it work itself out.&lt;/p&gt;

&lt;p&gt;I opened up the Microsoft store app and saw Dropbox prominently displayed. I clicked the Install button, but it prompted me to log into my Microsoft account in the store. I entered my credentials but got “we encountered an error, please try signing in again later.” Hm, those were the same Microsoft credentials that let met log into my account in the browser, why won’t it work in the store app? Fine, I decided to go directly to dropbox.com. Go there, click the download link… Nothing. Uh what? Go directly to the download link in a new tab, nothing. View in Internet Explorer, click the download link, nothing. Save Target As didn’t even produce a file browser window to let me choose where to save the file. This was seriously weird.&lt;/p&gt;

&lt;p&gt;So I was unable to sign into the store to download apps, and I was unable to download them in the web browser. This meant I was unable to download Chrome in the Edge browser, too. Basically, I was stuck with whatever partially working apps were on my machine. I tried searching around, using my MacBook because I noticed the Edge browser didn’t let me scroll with the wheel on my mouse–what decade is it again? I found &lt;a href=&quot;http://answers.microsoft.com/en-us/windows/forum/windows_10-windows_store/windows-10-store-login-error-we-encountered-an/deb605aa-43e8-4ebe-b99f-11282e7a03f4?auth=1&quot;&gt;a thread in the Microsoft Community&lt;/a&gt; about being unable to sign into the store, but no answer that worked for me. One guy mentioned a “Microsoft Account Sign-in Assistant” service that wasn’t running and starting it let him sign into the store, but I found that service in the Services list and it was already enabled and running.&lt;/p&gt;

&lt;p&gt;I opened an Explorer window to browse to my Downloads folder in case Chrome and Dropbox had been downloaded silently in the background. When I clicked to open my Downloads folder, though, I got a popup saying I didn’t have permission to access that folder, but I could gain access permanently by hitting Continue. Uh, what? All files and folders in my home directory should be owned by me, and they certainly were before the upgrade. I went ahead and gave myself access but neither application was in Downloads after all.&lt;/p&gt;

&lt;p&gt;At this point, I was hoping the kind folks of /r/windows10 could help me out again, so I made &lt;a href=&quot;https://www.reddit.com/r/Windows10/comments/3ft97g/help_cant_download_in_windows_10_cant_sign_into/&quot;&gt;another post&lt;/a&gt; asking for help. I added a few updates to it as I figured stuff out and got things working.&lt;/p&gt;

&lt;p&gt;A couple years ago, I had a problem running The Sims 3 in Windows 7. It seemed my registry keys dealing with The Sims 3 and its expansions were garbled and I couldn’t get the game to run. My solution at that time was to create a new user account called ‘fuckea’ and use it just to install and run The Sims 3 and its expansions. That worked like a charm. While my normal user account couldn’t run The Sims 3, fuckea had no problem. I wondered if the same approach might work here.&lt;/p&gt;

&lt;p&gt;I created a new user account on my computer just by telling it the email address of my Microsoft account. I didn’t have to specify a password. I signed out of my local account and saw the new account was listed. When I signed in, I used my Microsoft account password and it logged me in. I saw a clean desktop, the default Windows 10 background, and my taskbar at the bottom of the screen instead of on the left where I normally keep it. I opened the store app and saw that it was already signed in to my Microsoft account–excellent, that was one hurdle down. I opened up the Chrome site in Edge and it downloaded Chrome immediately. I saw a download progress bar instead of just nothing happening when clicking the link. I opened up Explorer and navigated to my Downloads folder, which I was able to access without having to grant myself access first. Things seemed to be set up right on this new user account.&lt;/p&gt;

&lt;p&gt;I switched back over to my local user and made my new Microsoft user an administrator, then signed out of the local user. Back on my Microsoft user, I found Dropbox in the store app and downloaded it without trouble. However, the Dropbox app didn’t seem like the Dropbox I was expecting. No Dropbox folder was created, no Dropbox icon appeared in my taskbar to show that my files were syncing. The Dropbox app in the store is apparently some thin client that wasn’t what I wanted, so I uninstalled it. I went to dropbox.com via Chrome this time and downloaded the &lt;em&gt;real&lt;/em&gt; Dropbox.&lt;/p&gt;

&lt;p&gt;Imagine telling someone less computer literate to install Dropbox on their Windows 10 computer. “Oh, I did.” “No, get the one from dropbox.com, not the one in that prominently displayed store app.” So dumb, why are there two different Dropboxes? I assume the one in the store is the Metro version, and it looks nice, but it really should have a different name. Dropbox Browser or Dropbox Lite or Fake-Ass Dropbox, maybe.&lt;/p&gt;

&lt;p&gt;Once I installed the dropbox.com Dropbox, I saw the familiar icon in my taskbar and it was syncing my files. I also ended up with a Dropbox folder in my home folder as expected. Once Dropbox finished syncing, I was able to set up 1Password on my new Microsoft account as well as set up Chrome, run Origin, and install Steam.&lt;/p&gt;

&lt;p&gt;Steam was a bit odd because it was definitely installed in Windows 7, but it did not show up at all when I searched in the Start menu for it. Maybe this was because I had Steam installed on my F drive, not the C drive where Windows is installed. When I downloaded the Steam client in my browser (no more of that store crap for me), it let me install it to the same place on my F drive again. It logged me in as soon as I started it, no credentials necessary. I have no idea how it knew who I was and didn’t prompt me for a password; the mysteries of Valve, I suppose.&lt;/p&gt;

&lt;p&gt;Both Origin and Steam show my games from before and seem to know which ones are already installed. I tried running Skyrim via the &lt;a href=&quot;http://skse.silverlock.org&quot;&gt;Skyrim Script Extender&lt;/a&gt;, which is necessary for some mods, and it sort of worked. Skyrim opened in a tiny window in the top left corner, but sound played and the graphics in that tiny window looked normal.&lt;/p&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2015/08/skyrim-tiny-window.png&quot; title=&quot;Skyrim in a tiny window in Windows 10&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2015/08/skyrim-tiny-window-400x0-7ab14e.png&quot; alt=&quot;Skyrim in a tiny window in Windows 10&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I tried opening The Sims 4 next, an Origin game, and it worked fine. Granted I ran it from my new Microsoft account on the computer instead of my old local user, so my saves and mods weren’t there; I’ll have to copy those over.&lt;/p&gt;

&lt;p&gt;I’ll keep trying other games as I get the desire to play them and find out which ones don’t quite work, like Skyrim. I haven’t had Windows 10 long enough yet to have a good impression of how I’ll like the operating system overall. The upgrade experience was a little bumpy, and it was super annoying not being able to download or install anything until I figured out the workaround of creating a new account. Otherwise, I love that I was able to upgrade my operating system in place and that it was a free upgrade, since OS X has gotten me used to those.&lt;/p&gt;
</description>
				<pubDate>Tue, 04 Aug 2015 00:00:00 -0500</pubDate>
				<link>/2015/08/04/my-windows-10-upgrade-experience/index.html</link>
				<guid isPermaLink="true">/2015/08/04/my-windows-10-upgrade-experience/index.html</guid>
			</item>
		
			<item>
				<title>Okami is lovely</title>
				<description>&lt;p&gt;I’ve been replaying Okami HD recently; coming back to it after several years of not playing made me notice anew all the little details that make the game so great. I really recommend the game on PS3, and I hope they rerelease it on the PS4 or make a proper sequel. I found the game originally because I enjoyed The Legend of Zelda: Twilight Princess and saw Okami listed as being a similar game, at least in so far as you got to play as a wolf. I would say now I prefer Okami to Twilight Princess.
&lt;!--more--&gt;&lt;/p&gt;

&lt;h2 id=&quot;things-i-like&quot;&gt;Things I Like&lt;/h2&gt;

&lt;dl&gt;
  &lt;dt&gt;Interesting mechanic&lt;/dt&gt;
  &lt;dd&gt;The Celestial Brush is really cool. You’d think painting with a regular controller would be hard, but it’s fine, at least for the simple painting you do in Okami. You get pretty fast at drawing slashes, circles, and squiggles to manipulate the world around you. I love that you freeze time when working the Celestial Brush. Dragon Age: Origins is another game that comes to mind when I think of pausing the action to consider strategy. In Okami, the whole screen changes to look like a black-and-sepia canvas with your brush poised over the world. You can rotate the view and find the best angle to slash through enemies, drag fire over to them from a torch across the room, or cover dead grass in ink to revive it. It’s so neat to paint over the world and have it react to your brush.&lt;/dd&gt;
  &lt;dt&gt;It’s beautiful&lt;/dt&gt;
  &lt;dd&gt;Okami is such a lovely game. I played it on the Wii initially and despite the crappy controls, I loved it. I was psyched when it got an HD re-release on the PS3 and I could play with a regular controller. &lt;a href=&quot;https://www.youtube.com/watch?v=1N0EX6jZsfA&quot;&gt;The music&lt;/a&gt;, the aesthetic, and the atmosphere of the game are beautiful. It’s a cel-shaded game and everything has a liquid, painted appearance.

    &lt;p&gt;It’s also cool as an American to recognize Japanese things I’ve seen in other games, most notably in Animal Crossing. Shops in Okami have a Lucky Cat statue as well as &lt;a href=&quot;https://en.wikipedia.org/wiki/Daruma_doll&quot;&gt;Daruma dolls&lt;/a&gt;. I recognize musical instruments that I remember collecting in Animal Crossing. The red rising sun gets splayed across the sky whenever you use your Sunrise technique. Cursed zones have floating kanji hovering in the air.&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2015/08/okami-shamisen.jpg&quot; title=&quot;Admiring a shamisen in Sasa Sanctuary&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2015/08/okami-shamisen-400x0-a1b09d.jpg&quot; alt=&quot;Admiring a shamisen in Sasa Sanctuary&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Reuse of areas&lt;/dt&gt;
  &lt;dd&gt;It’s cool that areas you traverse at the beginning of the game hold secrets you can only access much later. In one of the first areas you reach, Shinshu Field, there are cat statues that you can’t do anything with, then later you unlock a brush technique that lets you use them. Your traveling companion Issun even comments when you investigate them at first that they have the same vacant expression as you; he doesn’t give any hint that they’re artefacts you’ll later interact with. There are also rocky areas that clearly have treasure buried under them that you can’t get at because your paws aren’t strong enough… yet. Then there’s a crack in the wall that you just know you’ll be able to bust through later. A pond has a swirl in the middle that looks special, though initially you don’t know what it means. All these things are signs to anyone who’s played a video game before that you should come back later when you possess enough skill or the right tool.

    &lt;p&gt;Dragon Age 2 did nothing good with its reuse of areas. It suffered from a lack of diversity, and it showed when you’d go through the same cave fifteen times for different quests, and were supposed to believe that half those times you were in a completely different cave in the story, and it just happened to be identical to the one you explored before. Okami has an abundance of different areas, and it never tries to make you think one area is really a different one if they look the same. So when you go to Shinshu Field to lift the curse, then you come back to dig under the rock once you get that skill, then you come back to climb the cliff and call lightning, you’re just exploring further what Shinshu Field has to offer.&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2015/08/okami-hayate.jpg&quot; title=&quot;A side quest where you have to race and tackle this guy&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2015/08/okami-hayate-400x0-6a373d.jpg&quot; alt=&quot;A side quest where you have to race and tackle this guy&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Upgrades&lt;/dt&gt;
  &lt;dd&gt;Going hand-in-hand with the reuse of maps is the progression of new abilities. There are a couple of dojos where you can train and get new fighting techniques as well as improve existing skills. Areas you didn’t realize would ever be accessible suddenly become so because you learned how to double jump. New treasure can be found because you learn how to dig through solid rock instead of just dirt. The mirrors you’ve found scattered around the world that you thought were just used to save your game suddenly become waypoints because you enhanced one of your brush techniques.

    &lt;p&gt;The upgrades you can purchase or discover are spread out pretty well; I felt like I was learning new stuff at the right pace. There’s always something tantalizing that you can’t quite afford, too, whether it takes yen in the dojo or more Demon Fangs to trade to a collector. Many upgrades are required to progress the story, such as recovering your lost Celestial Brush techniques, but a lot are optional that you could blow right past if you were in a hurry. I find it rewarding when there’s a lot of optional gameplay; it feels like the developers took their time and considered what different people like to play.&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2015/08/okami-mika.jpg&quot; title=&quot;Talking with Mika&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2015/08/okami-mika-400x0-12bed9.jpg&quot; alt=&quot;Talking with Mika&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;It feels good&lt;/dt&gt;
  &lt;dd&gt;This game just makes you feel good. The world’s gone to crap because of a giant eight-headed monster, and you’ve got to save it. Poor little animals don’t have enough to eat, so you can buy feed bags for them. NPCs abound with problems ranging from having lost a beloved teacup to needing medicine to cure a sick father. Plants have withered, but you can rejuvenate them and beautify the landscape. Feeding animals, helping people, and restoring the greenery all earn Praise, which is used to level up.

    &lt;p&gt;It’s very satisfying to find a blank spot of grass with a monster gate in the middle, then when you defeat the monsters, suddenly trees and a pond and wildlife spring into existence. You’ll also find noxious purple areas with evil-looking kanji floating in midair; once you scribble over them, the ground bursts forth in bloom. One of the ways to heal yourself is to lie down for a while, and flowers grow around you while you nap. Flowers also spring up behind you while you run, getting more vibrant the faster you go.&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2015/08/okami-shishi-odoshi.gif&quot; title=&quot;Shishi odoshi fountain in Sasa Sanctuary&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2015/08/okami-shishi-odoshi-320x0-5e72a9.gif&quot; alt=&quot;Shishi odoshi fountain in Sasa Sanctuary&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Story progression&lt;/dt&gt;
  &lt;dd&gt;Every conversation in Okami involves a cut scene. You know something really important is happening, though, when the art style changes and the narration switches to third person. I liked these moments because it felt like I had accomplished something and could sit back for a second. The world was a bit safer, I had made it to some goalpost.

    &lt;p&gt;Okami’s story is crazy because when the game starts you think the big bad guy is Oroshi. Everything is focused on defeating him, and you go through several areas of the world before you finally get to the big battle. Things could have ended there and I would not have been surprised. Instead, after the big fight, you get one of these storyboards and are informed that the story is just beginning. Since the game is so pretty and enjoyable, it’s a treat to see that the show goes on.&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2015/08/okami-story-art.jpg&quot; title=&quot;Art after defeating a boss&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2015/08/okami-story-art-400x0-e0627b.jpg&quot; alt=&quot;Art after defeating a boss&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Satisfying fights&lt;/dt&gt;
  &lt;dd&gt;I like the variety of ways to fight monsters in Okami. There are three types of weapons and for each of those you’ll find better models as you progress. There’s Gold Dust that lets you increase the attack power of a single weapon. Weapons behave differently depending on how you’ve equipped them. Then you can use all your myriad Celestial Brush techniques in battle; I found myself using Power Slash, Veil of Mist, and Galestorm the most. Veil of Mist is easy mode: it slows down time for everyone else, and once you have a large enough inkwell (an upgrade you purchase with earned Praise), you can keep time slowed near constantly. Slow down time, wail on the bad guys with your weapon for a bit, maybe knock them out of the air or blow out their flames with Galestorm, and slash them up with Power Slash. Inferno, while powerful, uses a lot of ink, and Cherry Bomb is a little too hard to place while also taking a few seconds to draw.&lt;/dd&gt;
  &lt;dt&gt;Lots of ways to get around&lt;/dt&gt;
  &lt;dd&gt;As you explore the world more and the map opens up, you find numerous ways to get around. Some methods you’ll have to unlock to progress the game, like navigating water routes by drawing lilypads on them, but other methods are purely optional, such as enhancing Veil of Mist to travel via Origin Mirror. Since you’ll revisit areas to move the plot forward, it’s helpful not to have to run all the way back on foot. You can travel via Mermaid Spring and Origin Mirror directly to other Springs and Mirrors in the world. Usually wherever you need to go will have one or the other right in that zone. You also find alternate routes in and out of areas, like you reach Agata Forest via waterlilies on a stream, but you can leave via a tunnel in a cliff.&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2015/08/okami-sei-an-city.jpg&quot; title=&quot;About to cut line in Sei'an City&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2015/08/okami-sei-an-city-400x0-815adf.jpg&quot; alt=&quot;About to cut line in Sei'an City&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Little details&lt;/dt&gt;
  &lt;dd&gt;Every piece of loot you find, every powerup for fights, every collectible has a description. It sounds like such a little thing, but it’s something I appreciated in Dragon Age: Origins and found missing in both Dragon Age 2 and Dragon Age: Inquisition. I think it adds something to a game when there’s a bit of flavor text. It certainly matters in games like The Sims series where there’s a lot of humor to be found in descriptions of furniture you buy. I think it’s nice in Okami, too, where what would otherwise be a trinket you’d barely notice as you pick it up makes you pause because there’s a short summary of what makes it special in the game’s world. “This came all the way from the Dragon Palace? Where’s that? Will I ever see it? It says this statue is posed whimsically? Oh, it is pretty cute, actually.”

    &lt;p&gt;There are also objects that have nothing to do with the story, nothing you have to interact with at all to beat the game, but they’re there for you to inspect if you like. Just a little extra to make the world more immersive. Issun will make a comment about this being where Kushi grinds the rice to make sake, or how some small statue must have been there for ages because it’s so weathered. I like seeing small things like this, knowing the extra work that went into them: graphics, the idea of them, the extra translation work, the writing. When they’re not vital to the story, it makes me think they were added because the developers were passionate about the game they were making, which I appreciate.&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2015/08/okami-cicada.jpg&quot; title=&quot;Cicada shell on an acorn, seen while you're shrunk&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2015/08/okami-cicada-400x0-c1cedf.jpg&quot; alt=&quot;Cicada shell on an acorn, seen while you're shrunk&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;No inventory management&lt;/dt&gt;
  &lt;dd&gt;Some games have a very burdensome inventory system. Half my character’s life in Skyrim is spent agonizing over which piece of loot is more valuable so I know which one to leave behind and which one to sell. Okami avoids this problem by not having any kind of inventory limit. You find lots of sake that boosts your attack, slips of paper that boost your defense, fruit that builds up an extra life should you die, and special items that will come into play later. Not to mention all your weapons and the holy items you find that give you unique abilities. It’s a relief to know if you can buy an item, or when you find it in the world, you have room for it.

    &lt;p&gt;The lore of the game doesn’t even address storage: you’re a wolf, you don’t wear clothes, you don’t have any kind of backpack on you. You are, however, a god, so maybe that explains how you carry around all your stuff.&lt;/p&gt;
  &lt;/dd&gt;
  &lt;dt&gt;Callbacks to earlier achievements&lt;/dt&gt;
  &lt;dd&gt;You come across challenges in Okami that seem complete on their own, then later it turns out you need the reward you won to solve some other puzzle. I love seeing this kind of thing in books, television, and video games: an idea gets introduced early on, you think “oh okay that’s cool”, and don’t think any more of it. Then a situation arises later and it turns out you’ve had the solution all along, you just didn’t realize.

    &lt;p&gt;Sometimes in Okami, a solution to one puzzle winds up solving multiple problems. I stumbled across some moles playing a game in a field, so I joined in. I won the game and got a prize from the mole leader. “Well neat” I thought and went on my way. Then I come across a dude who’s all distraught because the moles stole something from him. Of course, what they stole is the exact item I won from the moles, so I gave it back to him and received Praise plus a different trinket with no obvious use. Since you don’t have to worry about inventory space, the item got tucked away and forgotten. Much later in the game, it turns out there’s another fellow with a different problem, the solution to which is this rare ingredient that he’ll never get his hands on… Except it’s what I had been carrying around for half the game without knowing what to do with it.&lt;/p&gt;

    &lt;p&gt;A similar thing happens with an old man you meet. You earn some Praise from him, he gives you a bit of info about the area, and reminisces about some girl. Then you get swept off defeating Orochi and you figure that’s all the guy was, a bit of interest added to that particular area. Turns out, you meet the girl he always talked about and you get to reunite the two.&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;h2 id=&quot;things-i-dislike&quot;&gt;Things I Dislike&lt;/h2&gt;

&lt;dl&gt;
  &lt;dt&gt;Weird toward women&lt;/dt&gt;
  &lt;dd&gt;There are some straight-up weird interactions with female NPCs in Okami. Issun is the little creature that stays with you the whole game and talks for you, the silent protagonist. He flirts overtly with every woman you meet, in some cases talking about their “melons” and how the lady is so “stacked.” The same lady who seems oblivious when Issun refers to her breasts as melons gets dubbed “Busty Babe.”

    &lt;p&gt;There’s some strangeness with your own gender as well. You’re Okami Amaterasu, called both “god” and “mother to us all.” At one point when you have to fight a dog, he says you’re going to fight “man-to-man.” When Issun points out how beautiful each new lady you meet is, Okami gets this awestruck look on her face as both she and Issun go slack-jawed over the woman’s beauty. There’s a skill you can buy that lets you pee on your enemies in battle, and you do so by lifting your leg like a male wolf. I’m not sure if Okami is meant to be androgynous and attracted to women, or if the writers were really just writing as if the player character is male like most adventure games.&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2015/08/okami-sakuya-butt.jpg&quot; title=&quot;Surely that's just a peach stuck to her dress...&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2015/08/okami-sakuya-butt-400x0-d7c21c.jpg&quot; alt=&quot;Surely that's just a peach stuck to her dress...&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Wordy&lt;/dt&gt;
  &lt;dd&gt;A friend of mine mainly plays arcade-style games because he doesn’t care for story. When a game does have dialogue, he skips through it all. Okami is not a game I would recommend to him. The opening cut scenes take a ridiculous amount of time to get through, in part because the dialogue goes at a set, slow pace and can’t be sped up, unlike most of the conversations during gameplay. Even when dialogue can be sped up or skipped, there’s a lot of it. Issun in particular is a chatty thing, taking several lines to say what could have been said in one.

    &lt;p&gt;The game can also be very hand-holdy, showing you a puzzle that looks obvious then, just as you go to solve it yourself, breaking into a cut scene where Issun calls attention to the obvious thing and makes an obvious suggestion about how to solve it. Sometimes I found myself rolling my eyes and wanting to just get &lt;em&gt;on&lt;/em&gt; with it.&lt;/p&gt;
  &lt;/dd&gt;
  &lt;dt&gt;Timing puzzles&lt;/dt&gt;
  &lt;dd&gt;I don’t like timing puzzles in any game, and Okami’s can be pretty frustrating. The most frequent kind involves digging underground to lead an NPC to something special on the lowest level. You have to use your brush techniques to get past water, spikes, and blocks. It’s doubly annoying because it’s an escort quest in addition to a timing puzzle: you have to shepherd the NPC along, blowing them over spikes in the floor and flipping them around when they’re going the wrong way. They walk along like a lemming and any time they get hurt, you get seconds removed from the clock.

    &lt;p&gt;Some of these digging puzzles are optional, but a couple are required to progress in the game. They always make me gnash my teeth; give me any number of fights or people to save, but spare me the timed obstacle courses. There’s one section of the game that has a series of timed trials that I find super frustrating, and they’re required to get to the end game. I wish those had been omitted entirely or left as an optional challenge to earn extra Praise.&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;&lt;a class=&quot;lightbox-link image-link width-400&quot; href=&quot;/uploads/2015/08/okami-himiko.jpg&quot; title=&quot;Accusing the queen while talking with the priestess&quot; data-lightbox=&quot;default&quot;&gt;&lt;img class=&quot;lightbox-image image&quot; src=&quot;/generated/uploads/2015/08/okami-himiko-400x0-a8ad83.jpg&quot; alt=&quot;Accusing the queen while talking with the priestess&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I love Okami and have played it through several times now, despite it being such a long game. When you beat it, you get the option of New Game+, letting you carry over your Praise-bought enhancements and most weapons, which lets you thoroughly trounce enemies and save up to buy even better items the second time around. I come back to the game every couple of years because it’s so satisfying to play. I grit my teeth and suffer through the handful of frustrating puzzles, because the rest of the game is worth it.&lt;/p&gt;
</description>
				<pubDate>Sat, 01 Aug 2015 00:00:00 -0500</pubDate>
				<link>/2015/08/01/okami-is-lovely/index.html</link>
				<guid isPermaLink="true">/2015/08/01/okami-is-lovely/index.html</guid>
			</item>
		
			<item>
				<title>Arel and tags</title>
				<description>&lt;p&gt;I love working out ActiveRecord and Arel queries in Rails apps. I thought I’d share some of the more fun queries I’ve designed in Arel, spread out over a few blog posts. We’ll start with one for fetching tags separated by account.
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;Say you have a Rails app with accounts. Different accounts have different data, and you want to keep that data separate, including the tags on that data. Say our data is stored in models Song, Book, and Video. Let’s say account #1 is Super Religious Church Group and account #2 is Sexxxy Porn Site. You can probably anticipate why users in account #1 never want to mistakenly see content or tags from account #2. It’s easy enough to keep the songs, books, and videos in your site separated by account because each song, book, and video record stores its &lt;code&gt;account_id&lt;/code&gt; right on it. A simple &lt;code&gt;Song.where(account_id: current_account)&lt;/code&gt; is sufficient, for example.&lt;/p&gt;

&lt;p&gt;If you’re using &lt;a href=&quot;https://github.com/mbleigh/acts-as-taggable-on&quot;&gt;ActsAsTaggableOn&lt;/a&gt; for tagging, however, you have a tags table with tag names and a taggings table that associates tags with your records. Unless you do something custom, there’s no account_id per tag or tagging, there’s just your record itself, stored as a polymorphic association called &lt;code&gt;taggable&lt;/code&gt; on the &lt;code&gt;ActsAsTaggableOn::Tagging&lt;/code&gt; model. So we need to somehow say “give me all the tags on all the kinds of content associated with the given account.”&lt;/p&gt;

&lt;p&gt;My usual technique when I start any Arel or ActiveRecord query is to first map out exactly what I want to get back, then start at that end result and trace backward to the parameters I have available, making a path from end goal back to known information. In this case, I want to get a list of &lt;code&gt;ActsAsTaggableOn::Tag&lt;/code&gt; records, and what I know is an account ID. Since I want the list of tags as my result, that’s the model that I need to start my query with:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line-numbers&quot;&gt;&lt;pre&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;constant&quot;&gt;ActsAsTaggableOn&lt;/span&gt;::&lt;span class=&quot;constant&quot;&gt;Tag&lt;/span&gt;.where(something)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;In an easy scenario, I could just do &lt;code&gt;ActsAsTaggableOn::Tag.where(account_id: account_id)&lt;/code&gt; and be done. But instead, since I know &lt;code&gt;account_id&lt;/code&gt; isn’t a field in the &lt;code&gt;tags&lt;/code&gt; table, I’m going to have to jump from &lt;code&gt;tags&lt;/code&gt; to another table. The &lt;code&gt;taggings&lt;/code&gt; table in my ActsAsTaggableOn setup is what actually ties a given tag to a piece of content, so I should join to &lt;code&gt;taggings&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line-numbers&quot;&gt;&lt;pre&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;constant&quot;&gt;ActsAsTaggableOn&lt;/span&gt;::&lt;span class=&quot;constant&quot;&gt;Tag&lt;/span&gt;.joins(&lt;span class=&quot;symbol&quot;&gt;:taggings&lt;/span&gt;).where(something)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;We’re one step closer to being able to filter by account: tags -&amp;gt; taggings -&amp;gt; content -&amp;gt; account. We need to flesh out this amorphous &lt;code&gt;something&lt;/code&gt; list of conditions. Since we’re calling &lt;code&gt;where&lt;/code&gt; on the tag model, these are conditions from the perspective of a tag. So we could describe them as “where the tag is applied to a piece of content in the given account.” How do we know if a tag is applied to a piece of content?&lt;/p&gt;

&lt;p&gt;Just by doing &lt;code&gt;joins(:taggings)&lt;/code&gt; we are filtering out tags that aren’t in use, because &lt;code&gt;joins&lt;/code&gt; results in an &lt;code&gt;INNER JOIN&lt;/code&gt;. One of the best tools for designing a complicated query is the Rails console. I specifically like calling &lt;code&gt;to_sql&lt;/code&gt; on queries that I’m working on to check that my SQL looks sane:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; bin/rails c
Loading development environment (Rails 4.2.2)
irb(main):001:0&amp;gt; puts ActsAsTaggableOn::Tag.joins(:taggings).to_sql
SELECT &quot;tags&quot;.* FROM &quot;tags&quot; INNER JOIN &quot;taggings&quot; ON &quot;taggings&quot;.&quot;tag_id&quot; = &quot;tags&quot;.&quot;id&quot;
=&amp;gt; nil
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So we see that an &lt;code&gt;INNER JOIN&lt;/code&gt; is produced, which means we’re making a one-to-one mapping from tags over to taggings, and this will exclude any tags that aren’t present in taggings.&lt;/p&gt;

&lt;p&gt;To check if a tag is applied to a piece of content, we need to consult the taggings table. We won’t be able to get all the data from &lt;code&gt;taggings&lt;/code&gt; alone, however, since &lt;code&gt;account_id&lt;/code&gt; lives in &lt;code&gt;songs&lt;/code&gt;, &lt;code&gt;books&lt;/code&gt;, and &lt;code&gt;videos&lt;/code&gt;. So we need to hop from &lt;code&gt;taggings&lt;/code&gt; over to each of those tables. Now comes the time to start setting some variables so things don’t get unwieldy:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line-numbers&quot;&gt;&lt;pre&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;
&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;
&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;
&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;taggings = &lt;span class=&quot;constant&quot;&gt;ActsAsTaggableOn&lt;/span&gt;::&lt;span class=&quot;constant&quot;&gt;Tagging&lt;/span&gt;.arel_table
songs = &lt;span class=&quot;constant&quot;&gt;Song&lt;/span&gt;.arel_table
books = &lt;span class=&quot;constant&quot;&gt;Book&lt;/span&gt;.arel_table
videos = &lt;span class=&quot;constant&quot;&gt;Video&lt;/span&gt;.arel_table
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;arel_table&lt;/code&gt; method is a method Rails adds on to your models that returns an &lt;a href=&quot;http://www.rubydoc.info/github/rails/arel/Arel/Table&quot;&gt;&lt;code&gt;Arel::Table&lt;/code&gt;&lt;/a&gt;. This is how you talk about particular fields in your tables when dipping from ActiveRecord down into Arel. For example, I can say &lt;code&gt;songs[:id]&lt;/code&gt; to get a reference to the &lt;code&gt;id&lt;/code&gt; field on my &lt;code&gt;songs&lt;/code&gt; table. I can then use a method like &lt;code&gt;eq&lt;/code&gt; to make comparisons between that field to other fields or values. &lt;code&gt;songs[:id].eq(1)&lt;/code&gt; will produce the SQL &lt;code&gt;&quot;songs&quot;.&quot;id&quot; = 1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ActsAsTaggableOn::Tagging&lt;/code&gt; model has a polymorphic relationship called &lt;code&gt;tagging&lt;/code&gt;, and it uses fields &lt;code&gt;taggable_id&lt;/code&gt; and &lt;code&gt;taggable_type&lt;/code&gt; to know whether a tag is applied to a &lt;code&gt;Song&lt;/code&gt;, &lt;code&gt;Book&lt;/code&gt;, or &lt;code&gt;Video&lt;/code&gt; record. We need to make use of both of these fields to know which table to join:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line-numbers&quot;&gt;&lt;pre&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;
&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;
&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;
&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;
&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;
&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;
&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;
&lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;
&lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;
&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;
&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;comment&quot;&gt;# &amp;quot;songs&amp;quot;.&amp;quot;id&amp;quot; = &amp;quot;taggings&amp;quot;.&amp;quot;taggable_id&amp;quot; AND &amp;quot;taggings&amp;quot;.&amp;quot;taggable_type&amp;quot; = 'Song'&lt;/span&gt;
taggings_to_songs = songs[&lt;span class=&quot;symbol&quot;&gt;:id&lt;/span&gt;].eq(taggings[&lt;span class=&quot;symbol&quot;&gt;:taggable_id&lt;/span&gt;]).
    and(taggings[&lt;span class=&quot;symbol&quot;&gt;:taggable_type&lt;/span&gt;].eq(&lt;span class=&quot;constant&quot;&gt;Song&lt;/span&gt;.name))

&lt;span class=&quot;comment&quot;&gt;# &amp;quot;books&amp;quot;.&amp;quot;id&amp;quot; = &amp;quot;taggings&amp;quot;.&amp;quot;taggable_id&amp;quot; AND &amp;quot;taggings&amp;quot;.&amp;quot;taggable_type&amp;quot; = 'Book'&lt;/span&gt;
taggings_to_books = books[&lt;span class=&quot;symbol&quot;&gt;:id&lt;/span&gt;].eq(taggings[&lt;span class=&quot;symbol&quot;&gt;:taggable_id&lt;/span&gt;]).
    and(taggings[&lt;span class=&quot;symbol&quot;&gt;:taggable_type&lt;/span&gt;].eq(&lt;span class=&quot;constant&quot;&gt;Book&lt;/span&gt;.name))

&lt;span class=&quot;comment&quot;&gt;# &amp;quot;videos&amp;quot;.&amp;quot;id&amp;quot; = &amp;quot;taggings&amp;quot;.&amp;quot;taggable_id&amp;quot; AND &amp;quot;taggings&amp;quot;.&amp;quot;taggable_type&amp;quot; = 'Video'&lt;/span&gt;
taggings_to_videos = videos[&lt;span class=&quot;symbol&quot;&gt;:id&lt;/span&gt;].eq(taggings[&lt;span class=&quot;symbol&quot;&gt;:taggable_id&lt;/span&gt;]).
    and(taggings[&lt;span class=&quot;symbol&quot;&gt;:taggable_type&lt;/span&gt;].eq(&lt;span class=&quot;constant&quot;&gt;Video&lt;/span&gt;.name))
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;Arel is nice because I can save bits of my query in variables like those above, and assemble my query piecemeal. Let’s make use of the join conditions defined above to connect &lt;code&gt;taggings&lt;/code&gt; to our content tables:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line-numbers&quot;&gt;&lt;pre&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;
&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;
&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;taggings.join(songs).on(taggings_to_songs)
taggings.join(books).on(taggings_to_books)
taggings.join(videos).on(taggings_to_videos)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;Note we’re using &lt;code&gt;join&lt;/code&gt; here instead of &lt;code&gt;joins&lt;/code&gt;. &lt;code&gt;join&lt;/code&gt; is used with Arel while &lt;code&gt;joins&lt;/code&gt; is for joining an ActiveRecord model to another table by giving the relationship name. For example, in our &lt;code&gt;Song&lt;/code&gt; model we have &lt;code&gt;belongs_to :account&lt;/code&gt;, so we can say &lt;code&gt;Song.joins(:account)&lt;/code&gt; and ActiveRecord generates SQL to do an &lt;code&gt;INNER JOIN&lt;/code&gt; to the &lt;code&gt;accounts&lt;/code&gt; table.&lt;/p&gt;

&lt;p&gt;Why were we joining to the individual content tables again? Because they’re where the &lt;code&gt;account_id&lt;/code&gt; field is stored, and that’s the field by which we want to filter tags. Having joined to the content tables, we can now write conditions using their fields:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line-numbers&quot;&gt;&lt;pre&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;
&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;
&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;
&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;
&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;
&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;taggings.join(songs).on(taggings_to_songs).
         where(songs[&lt;span class=&quot;symbol&quot;&gt;:account_id&lt;/span&gt;].eq(account_id))
taggings.join(books).on(taggings_to_books).
         where(books[&lt;span class=&quot;symbol&quot;&gt;:account_id&lt;/span&gt;].eq(account_id))
taggings.join(videos).on(taggings_to_videos).
         where(videos[&lt;span class=&quot;symbol&quot;&gt;:account_id&lt;/span&gt;].eq(account_id))
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;This is assuming we have an &lt;code&gt;account_id&lt;/code&gt; variable, maybe representing the account of the user who is currently logged into our app. Note that the &lt;code&gt;where&lt;/code&gt; here is not the same as the &lt;code&gt;where&lt;/code&gt; on an ActiveRecord model. Here, we pass in Arel conditions like &lt;code&gt;songs[:account_id].eq(account_id)&lt;/code&gt; instead of the usual hash or SQL string you’d pass to an ActiveRecord &lt;code&gt;where&lt;/code&gt; call, like &lt;code&gt;where(account_id: 1)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So we’re querying &lt;code&gt;taggings&lt;/code&gt; where the associated content is in the desired account, but we haven’t connected those taggings back to their tags yet. Let’s get the &lt;code&gt;tag_id&lt;/code&gt; off of the tagging record and stick that bit of SQL-to-be in a variable:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line-numbers&quot;&gt;&lt;pre&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;
&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;
&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;
&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;
&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;
&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;
&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;
&lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;
&lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;song_tags = taggings.join(songs).on(taggings_to_songs).
                     where(songs[&lt;span class=&quot;symbol&quot;&gt;:account_id&lt;/span&gt;].eq(account_id)).
                     project(taggings[&lt;span class=&quot;symbol&quot;&gt;:tag_id&lt;/span&gt;])
book_tags = taggings.join(books).on(taggings_to_books).
                     where(books[&lt;span class=&quot;symbol&quot;&gt;:account_id&lt;/span&gt;].eq(account_id)).
                     project(taggings[&lt;span class=&quot;symbol&quot;&gt;:tag_id&lt;/span&gt;])
video_tags = taggings.join(videos).on(taggings_to_videos).
                      where(videos[&lt;span class=&quot;symbol&quot;&gt;:account_id&lt;/span&gt;].eq(account_id)).
                      project(taggings[&lt;span class=&quot;symbol&quot;&gt;:tag_id&lt;/span&gt;])
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;project&lt;/code&gt; method lets you list which fields should be in the &lt;code&gt;SELECT&lt;/code&gt; part of the query. It’s like a &lt;a href=&quot;https://en.wikipedia.org/wiki/Projection_(relational_algebra)&quot;&gt;projection&lt;/a&gt; in relational algebra.&lt;/p&gt;

&lt;p&gt;If you call &lt;code&gt;to_sql&lt;/code&gt; on the &lt;code&gt;song_tags&lt;/code&gt; variable, assuming our &lt;code&gt;account_id&lt;/code&gt; is 1, you get the following:&lt;/p&gt;

&lt;div class=&quot;language-sql highlighter-coderay&quot;&gt;&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line-numbers&quot;&gt;&lt;pre&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;
&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;
&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;
&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;
&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;class&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;tag_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;keyword&quot;&gt;INNER&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;songs&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;keyword&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;songs&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggable_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;AND&lt;/span&gt;
&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggable_type&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;Song&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;keyword&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;songs&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;account_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;integer&quot;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;This is getting the ID of every tag that’s applied to a song in the given account. That’s a third of what we need; we also want any tag applied to a book or video in the given account. So we need to combine our &lt;code&gt;song_tags&lt;/code&gt;, &lt;code&gt;book_tags&lt;/code&gt;, and &lt;code&gt;video_tags&lt;/code&gt; SQL snippets somehow. Since we want to include a tag that has been applied to a song, book, or video, but not necessarily to one of each, we should use an &lt;code&gt;OR&lt;/code&gt; operator:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line-numbers&quot;&gt;&lt;pre&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;
&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;
&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;
&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;tags = &lt;span class=&quot;constant&quot;&gt;ActsAsTaggableOn&lt;/span&gt;::&lt;span class=&quot;constant&quot;&gt;Tag&lt;/span&gt;.arel_table
conditions = tags[&lt;span class=&quot;symbol&quot;&gt;:id&lt;/span&gt;].in(song_tags).
    or(tags[&lt;span class=&quot;symbol&quot;&gt;:id&lt;/span&gt;].in(book_tags)).
    or(tags[&lt;span class=&quot;symbol&quot;&gt;:id&lt;/span&gt;].in(video_tags))
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;These conditions will select tags that are applied to any song, book, or video in the specified account–that was our original goal! If we look at &lt;code&gt;to_sql&lt;/code&gt; of &lt;code&gt;conditions&lt;/code&gt;, we get:&lt;/p&gt;

&lt;div class=&quot;language-sql highlighter-coderay&quot;&gt;&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line-numbers&quot;&gt;&lt;pre&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;
&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;
&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;
&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;
&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;
&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;
&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;
&lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;
&lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;
&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;
&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;
&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;
&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;
&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;
&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;
&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;
&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;
&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;
&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;
&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;
&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;
&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;
&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;
&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;
&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;(
  (
    &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;IN&lt;/span&gt; (
      &lt;span class=&quot;class&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;tag_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;keyword&quot;&gt;INNER&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;songs&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;keyword&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;songs&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggable_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;AND&lt;/span&gt;
      &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggable_type&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;Song&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;keyword&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;songs&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;account_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;integer&quot;&gt;1&lt;/span&gt;
    ) &lt;span class=&quot;keyword&quot;&gt;OR&lt;/span&gt;
    &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;IN&lt;/span&gt; (
      &lt;span class=&quot;class&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;tag_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;keyword&quot;&gt;INNER&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;keyword&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggable_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;AND&lt;/span&gt;
      &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggable_type&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;keyword&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;account_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;integer&quot;&gt;1&lt;/span&gt;
    )
  ) &lt;span class=&quot;keyword&quot;&gt;OR&lt;/span&gt;
  &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;IN&lt;/span&gt; (
    &lt;span class=&quot;class&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;tag_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;keyword&quot;&gt;INNER&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;videos&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;keyword&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;videos&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggable_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;AND&lt;/span&gt;
    &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggable_type&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;Video&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;keyword&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;videos&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;account_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;integer&quot;&gt;1&lt;/span&gt;
  )
)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;Almost there. Now we can use these conditions in our original query, back at the ActiveRecord level. The nice thing is that we can just pass our &lt;code&gt;conditions&lt;/code&gt; variable to ActiveRecord’s &lt;code&gt;where&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line-numbers&quot;&gt;&lt;pre&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;constant&quot;&gt;ActsAsTaggableOn&lt;/span&gt;::&lt;span class=&quot;constant&quot;&gt;Tag&lt;/span&gt;.joins(&lt;span class=&quot;symbol&quot;&gt;:taggings&lt;/span&gt;).where(conditions)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;If we run this query, we definitely get back tags for the right account, but there may be duplicates. We can add a &lt;code&gt;.uniq&lt;/code&gt; at the end to add &lt;code&gt;DISTINCT&lt;/code&gt; to our &lt;code&gt;SELECT&lt;/code&gt; statement:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line-numbers&quot;&gt;&lt;pre&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;constant&quot;&gt;ActsAsTaggableOn&lt;/span&gt;::&lt;span class=&quot;constant&quot;&gt;Tag&lt;/span&gt;.joins(&lt;span class=&quot;symbol&quot;&gt;:taggings&lt;/span&gt;).where(conditions).uniq
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;While there is a &lt;code&gt;uniq&lt;/code&gt; method on enumerables in Ruby, ActiveRecord will use &lt;code&gt;uniq&lt;/code&gt; to modify our query so we leverage SQL to get unique results instead of filtering at the Ruby level. Here is the final SQL that is generated:&lt;/p&gt;

&lt;div class=&quot;language-sql highlighter-coderay&quot;&gt;&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line-numbers&quot;&gt;&lt;pre&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;
&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;
&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;
&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;
&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;
&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;
&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;
&lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;
&lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;
&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;
&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;
&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;
&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;
&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;
&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;
&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;
&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;
&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;
&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;
&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;
&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;
&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;
&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;
&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;
&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;
&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;
&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;
&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;
&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;class&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;DISTINCT&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.* &lt;span class=&quot;keyword&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;keyword&quot;&gt;INNER&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;keyword&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;tag_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;keyword&quot;&gt;WHERE&lt;/span&gt; (
  (
    &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;IN&lt;/span&gt; (
      &lt;span class=&quot;class&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;tag_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;keyword&quot;&gt;INNER&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;songs&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;keyword&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;songs&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggable_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;AND&lt;/span&gt;
      &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggable_type&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;Song&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;keyword&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;songs&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;account_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;integer&quot;&gt;1&lt;/span&gt;
    ) &lt;span class=&quot;keyword&quot;&gt;OR&lt;/span&gt;
    &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;IN&lt;/span&gt; (
      &lt;span class=&quot;class&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;tag_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;keyword&quot;&gt;INNER&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;keyword&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggable_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;AND&lt;/span&gt;
      &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggable_type&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;keyword&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;account_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;integer&quot;&gt;1&lt;/span&gt;
    )
  ) &lt;span class=&quot;keyword&quot;&gt;OR&lt;/span&gt;
  &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;IN&lt;/span&gt; (
    &lt;span class=&quot;class&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;tag_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;keyword&quot;&gt;INNER&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;videos&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;keyword&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;videos&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggable_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;AND&lt;/span&gt;
    &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggings&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;taggable_type&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;Video&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;keyword&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;videos&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;string&quot;&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;content&quot;&gt;account_id&lt;/span&gt;&lt;span class=&quot;delimiter&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; = &lt;span class=&quot;integer&quot;&gt;1&lt;/span&gt;
  )
)
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;We’re mostly hitting indexed fields here. &lt;code&gt;tags.id&lt;/code&gt;, &lt;code&gt;songs.id&lt;/code&gt;, &lt;code&gt;books.id&lt;/code&gt;, and &lt;code&gt;videos.id&lt;/code&gt; are all primary keys, while &lt;code&gt;tag_id&lt;/code&gt;, &lt;code&gt;taggable_id&lt;/code&gt;, and &lt;code&gt;taggable_type&lt;/code&gt; belong to other indices. Hopefully your &lt;code&gt;account_id&lt;/code&gt; fields in &lt;code&gt;songs&lt;/code&gt;, &lt;code&gt;books&lt;/code&gt;, and &lt;code&gt;videos&lt;/code&gt; are indexed as well, since they’re foreign keys by which you’ll be doing a lot of filtering.&lt;/p&gt;

&lt;p&gt;So there you have it. That’s how I construct a query in Arel or ActiveRecord. Start with where you want to end up and work your way backward, connecting in other tables whenever you need access to their data. In my next Arel post, I’ll cover how I filter records that the given user has permission to view.&lt;/p&gt;
</description>
				<pubDate>Fri, 19 Jun 2015 00:00:00 -0500</pubDate>
				<link>/2015/06/19/arel-and-tags/index.html</link>
				<guid isPermaLink="true">/2015/06/19/arel-and-tags/index.html</guid>
			</item>
		
	</channel>
</rss>
