Saturday, June 4, 2011

A little Saturday morning code jam

Here's my latest trouble with Manticore.

Eli showed me this code for a menu partial, which I put at the top of the Character view page. It allows you to switch to the view of a different model that belongs_to Character.

<%= link_to_unless_current 'Character', character_path(@character) %>
<%= link_to_unless_current 'Armor', character_armor_path(@character, @character.armor) %>

So this links to Armor's view page. Pretty awesome, except it doesn't work if Armor hasn't been built yet, which will be the case whenever creating a new character. Ops! I thought putting a method for creating a new instance of Armor if one didn't exist would fix this problem, but I couldn't get that to work, either. Also, I'm not convinced that's the best way to handle this problem. For another thing, I want to link to an Item page, not an Armor page, since I see Armor as being an Item.

I updated that code and here's what we've got now:

<%= link_to_unless_current 'Character', character_path(@character) %>
<%= link_to_unless_current 'Items', character_item_path(@character, @character.item) %>

However, this gives me a new error.

No route matches {:controller=>"items", :action=>"show", :id=>nil, :character_id=>#<Character id: 7, name: "Test" ... updated_at: "2011-06-04 15:43:59">

I'm not sure why I'm getting a routing error. Here's my route code:

resources :characters do
  resources :statistics
  resources :items

Here's what I'm trying to do with this menu partial. I'll want to have 5 links: Character, Items, Skills and Feats, Spells and Background. Much like the code David showed me for creating Statistics, I know I can use this method for all of them once I have it down.

And here's what I want the links to do. Clicking on Items will allow a user to create various types of items associated with that character: weapons, armor, pimp canes and so on. At this point I'm assuming Item will need to be a separate model, because it will have a belongs_to relationship with Character, right? Even though it's just going to be used as a view that displays forms for creating other models?

And Character should have a has_one relationship with Item, right? It's just going to be a single page, and while a Character can have many weapons, armors and pimp canes, I'll only be working with one Item view.

I'll have a day where everything I try to do works and I'm making great progress and I'll feel like the champion of code, then the next day I'll switch gears slightly and feel like I'm adrift on a hostile sea of errors. Anyone else have this same experience when you were learning Rails?

Wednesday, June 1, 2011

A little one-on-one with jqr

So last night my friend Eli calls me up, interrupting my special video game time and tells me to get my ass over to his house for a little side-by-side code action.

You want to talk about productive? In about an hour, Eli had shown me ways to solve both of the problems I've been having with Chorenivore and Manticore (I promise not all of my projects will end in an -ore sound) as well as digging into some more abstract theory stuff.

Basically what I've got now is a hidden_field and a couple of image_submit_tags that mark a task as finished or unfinished. We grabbed a couple of placeholder images, just so I could see how it worked and fired it up. BOOM! Marking a task as Finished displayed a nice little check mark, whereas marking a task as Unfinished displayed a little boxy box.


Here's the code for my hidden field in the Task view:

<%= f.hidden_field :finished, :value => !task.finished %>

From this syntax, my understanding is the hidden field is marking the task as finished or unfinished without being displayed to the user. Is this correct? How else is a hidden_field used?

After work, I decided I'd fire up Illustrator and Photoshop and see if I couldn't make a couple nicer looking little icons. Here's what I came up with at first:

What? Are you drunk? Look, I like big icons as much as the next guy, but 80 x 80 is just egregious. Let's shrink that down a little, son.

Aha! Now it's starting to come together. Plus, to use these images, all I had to do was throw them in the public/images folder, then call either 'finished.png' or 'unfinished.png'.

Not bad for Chorenivore!

Here's a little recap of the problem I ran into with Manticore a while back. David had shown me how to create instances of related models from my Character view that are tied to my main Character model. But once I got everything straightened out that I want displayed in the Character view (hit points, combat information, statistics, saves) I hit a wall. I wanted a way to link to another page within the same application that would display different information. For example, every Character will have Items. Items will be broken down into Weapons, Armor, Magical Items, Gear and Treasure.

The solution was this:

<%= link_to_unless_current 'Armor', character_armor_path(@character, @character.armor) %>

See, I KNEW I could do something like this, but the exact syntax was giving me trouble. But now that I know how to link to the view of a model that belongs_to another model, I can design the navigation fairly easily. You just throw that bad boy into a partial and call it macaroni!

I know working on functionality before worrying about style is the way to go, but I still have a hard time not thinking about how I want an application to be navigated.

So what did I take away from this, besides concrete Rails techniques? The internet is a great and valuable resource, but actually hanging out with and talking to people about projects is irreplaceable. Not only did Eli show me how to do some things I've been struggling with for about a month, but I also talked to all the Fastest Forward guys about projects they're working on. It's awesome to see people excited about what they're doing.

Tuesday, May 31, 2011

More work on Chorenivore

I'm still working on Chorenivore, my to-do list application. Nothing major to report, but I'm still wrestling with a way to update the Finished? status from the view.

What I've read suggests I should have two methods in the Tasks controller, called Finish and Unfinish. This makes sense, because then a user could toggle this status from the Tasks view with either a button_for or a link_to.

So here's the code I've got so far:

def finish
  { redirect_to(tasks_path, :notice => 'Task completed!') }

def unfinish
  { redirect_to(tasks_path, :notice => 'Did you forget something?') }

I haven't quite thought out HOW this method will be called, but I want a user to be redirected to the Tasks list once a Task has been marked as finished or unfinished. Am I thinking about this in the right way? What I want is to be able to mark something as finished, then have that change reflected in the view, and also to be able to change it back, in case you change your mind. Whoops! Is creating two methods the best way to do this?

I've also got this little number in the Tasks view:

<%= task.created_at.strftime("%b %d, %Y") %>

After some srs googling, I was able to find a way to display when a Task was created and format that information in a way I found acceptable. My only question is this: is this too much logic to load into a view? Couldn't I create another method in the Controller, then call it from the View?

Monday, May 30, 2011

Gettin my git on

Oh so you want to know about Memorial Day weekend coding? First off, at my friend Eli's insistence, I've been getting more familiar with keyboard shortcuts in TextMate. Who no longer digs through files to find what he's looking for? This guy. Who keeps everything in a project, then performs a little search magic with CMD+T? THIS GUY!

I also started using Git Hub, after almost three years of having an account. I understand how commits and pushing changes work, but I had some trouble last night. I was able to create a repository and upload the readme file, but then I couldn't get the entire project uploaded.

So here's what I think happened. I'm working with Chorenivore (my to-do list application) and I created a new directory at users/tylermoore/chorenivore, ran git init, tossed a README file in there and pushed it to git. Then when I went to upload the whole project, I was trying to push from users/tylermoore/code/chorenivore. Obviously having duplicate directories is a stupid idea!

So if I want to make a folder into a Git directory, ready for upload, all I have to do is navigate to that directory in terminal and use git init? Or do I need to make a brand new directory every time, then copy all my code into it? It seems like I should just be able to set up the necessary files with an existing directory. Also, what does git touch do? Can you just enter git touch . to touch everything in the directory?

In more concrete code-related news, Chorenivore is coming along pretty well. After creating the initial files with a scaffold (something my friend Matt says is a bad idea, even at early stages, and while I DO agree with him, I'm still finding it useful) I was able to edit the default code to do a few things I wanted to do. For example:

After creating a new Task, the user is taken back to the Task index page. A user is also taken back to the Task index page after deleting a Task and a flash :notice is displayed.

Creating a new Task does not allow a user to mark a Task as complete, but Editing a Task DOES allow this. Since scaffold generates New and Edit actions that use the same form, I simply copied the code and modified it so the boolean column for Finished? wasn't included.

Not bad! I've definitely got an application that works and functionality that makes sense. I think I've been good about thinking about how things should work, but actually making that happen is getting easier.

Oh, here's my git profile.