Showing posts with label views. Show all posts
Showing posts with label views. Show all posts

Wednesday, August 31, 2011

Alphabetical sort method in Rails

So the other day, frustrated with the complete lack of progress I'd made on trying to figure out how to link to a Background model from a Character's view, I decided the best thing to do is to work on some smaller problems until I either ran across a method that seemed like it would work, or INSPIRATO struck me, or I felt like battling that wily Background again.

One of the things I wanted to do is make it so when a user creates a list of Skills, they're displayed in alphabetical order. Sounds simple, right? And it is! Absolutely. But I had only the vaguest idea of how to write such a method (probably finding all the skills, then ordering them by name) and absolutely no idea how to call that method in the view.

So I headed over to Stack Overflow since this seemed like an easy enough problem that I could describe and get answered quickly enough. Who came riding over the hill like Gandalf, ready to save the day? normalocity! I have 0 idea who this guy is, but his method was clear, easy to understand and exactly what I was looking for. Have I mentioned how awesome the Rails community is, both locally and online? One of my favorite things about my learning process has been getting to know more people, and talking to more experienced programmers about Rails, coding and how things work in general.

So here's what I ended up doing. I first had to define the method in my skills_controller (which I had already done, and correctly too!) and then call that method in the view.

So here's the definition I came up with:

def index
  @character = Character.find(params[:character_id])
  @skill = @character.skills.build
  @sorted_skills = @character.skills.find(:all, :order => :name)
end

Not bad! But then I got stuck. How do I call it in the view? Is it a separate thing? I've already got code that iterates over each skill and then spits it back out to the view. So was it a second call? That doesn't seem logical. So what about editing the code I already have, and calling the new method I wrote instead of the previous method?

Just one little change here. We started off with:

<% @character.skills.reject {|skill| skill.new_record? }.each do |skill| %>

And changed it to:

<% @sorted_skills.reject {|skill| skill.new_record? }.each do |skill| %>

So this code is doing the same thing it did before, but instead of simply bringing up @character.skills, it's bringing up @sorted_skills, which has already been defined as @character.skills.find(:all, :order => :name.

And this is just one example. I've got a crazy idea for a way to sort by two variables. For example, a Character will have class and cross-class skills. What about a way to sort these skills both alphabetically and by class or cross class skills? Nutty, I know! I'm letting that one brew for a while, though. Or what about spells? It might make sense to sort spells both by spell level and alphabetically. But you see what I mean? It's kind of getting impossible for me to learn something new in Rails without a) wondering how else I can apply it and b) wondering how I can tweak it, change it, expand it, pose it, scroll it, click it, or zoom it.

It felt really good to figure this out tonight, and even though this one instance is just a tiny fix that literally took two seconds to code, the logic behind it and understanding that logic reaches quite a bit deeper. After all, I'm not learning Rails to build Dungeons and Dragons character databases. I'm learning Rails to understand 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.

Question:

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.

Sunday, May 15, 2011

Triumph of the heart

So Blogger was down for a day or two this week, which sucks because I really wanted to talk about the progress I've made with Manticore. Thanks to a ton of friendly advice from more experienced coders (UnixMonkey, jqr and a ton of guys on Stack Overflow) I finally fixed the problems I was having with the has_one relationship.

For people who are just tuning in, Manticore is the Dungeons and Dragons character database application I'm working on. I had created a Character and a Statistic model, where Character has_one Statistic and Statistic belongs_to Character. However, I had some issues with displaying the Statistic model on the Character page, and also ensuring there was only one instance of Statistic in use at any given time. But no more!

I was able to take the code David (UnixMonkey) showed me on github and extrapolate that to create new models that belong_to the Character model with a has_one relationship.

So far, I've got a working Character model, with models for character statistics, saving throws, armor class, hit points and speed. I'm beginning to see how I want all this information displayed. Eventually I want it to be a page with 5 tabs: Character, Equipment, Skills and Feats, Spells and Background. I see the Character tab as being a quick sheet with all the relevant information for playing a game, and the other tabs having more detailed information.

I'm also thinking about other things I can do with this app. For example, Armor Class is composed of several different numbers: values for armor worn, a shield, a character's dexterity modifier and more. So it would be pretty easy to ensure the total AC value is equal to all of the separate values and display an error message if this is not true.

I mentioned that I see the Character tab as being a quick page with combat information at the ready. Eventually, I'd like this page to contain some tools to make playing a game easy from that view: stand alone dice rollers and specialized dice rollers that a player can create and save. For example, your character has a short sword and you want to save an attack roll with the short sword. So this would create a button that generates a random number from 1 to 20 (the attack roll) then adds in any relevant modifiers (attack bonuses, weapon enhancements, etc) and spits out a total number.

I've also been thinking about tools specifically for Dungeon Masters. Things like a database of plot hooks to generate ideas for campaigns or short adventures, an NPC personality and description generator and so on.

A lot of Rubyists go on and on about how Ruby on Rails makes programming fun. While I'm beginning to see why that's true (since you spend most of your time building things and not trying to get the tools you need to build things to work) I really think it really opens you up to what's possible. Now that I've got some ideas of HOW to build things, I'm getting lots of inspiration for things TO build.

Monday, May 9, 2011

This code is...problematic

It's been a while since my last blog post. Dang, a whole week! Don't worry, though. I never stopped coding.

I'm still having trouble with my Manticore app. Basically, here's what I'm trying to do:

I have two models, Character and Statistic. Each Character will have_one Statistic, and Statistic belongs_to Character. So good so far, right? I want to be able to create the Statistic information from the Character view, then be able to edit that information once there's information to be edited. I want to only be able to create one instance of Statistic per Character, hence the has_one relationship.

One solution I got on Stack Overflow was to simply make a form in the Character view, but since I'll be extrapolating this code (once I finally understand it) to create other models like Equipment, Skills, Spells and so on, it doesn't make sense to load down the Character view with a ton of different forms.

I've been modeling the code for Manticore from this tutorial which has you create a blog. It was easy enough to see that Character could be substituted for the Post model, and Statistic could be substituted for the Comment model.

However, I've hit a wall. Now I get this error:

undefined method `build' for nil:NilClass

And I'm not sure why. I suspect it has something to do with the has_one vs. has_many relationship. Earlier, I'd followed the tutorial more closely, but I need to define the Character/Statistic relationship as has_one vs. has_many because I don't need multiple instances of Statistics per character. Any ideas where this error could be coming from? I'm not defining a build action, but this error never popped up before.

Here's some code, if that helps:

class Character < ActiveRecord::Base  
  has_one :statistic, :dependent => :destroy
end

class Statistic < ActiveRecord::Base
  belongs_to :character
end

As far as I can tell, the model code is fine. But I might be missing something pretty obvious.

Here's code from the Statistics controller.

def create
  @character = Character.find(params[:character_id])
  @statistic = @character.statistics.create.new(params[:statistic])
  redirect_to character_path(@character)
end

I may have something wrong here, but like I said, this has worked in the past and has tied the Statistic to the specific Character (something I was struggling with before this mess!)

This is from the Statistics _form partial:

<%= form_for([@character, @character.statistic.build]) do |f| %>
  <div class="field">
    <%= f.label :strength %>
    <%= f.text_field :strength %>
  </div>
...
    <%= f.submit %>
  </div>
<% end %>

I suspect my troubles may be coming from this code, but I don't get why. I'm following the tutorial and this has worked before, and all I've changed is the has_many relationship to a has_one.

In other less concrete news, I feel pretty dumb for just not getting this. However, in the course of trying to figure it out, both on my own, through people I know and asking and reading questions on Stack Overflow, I've got a much better grip on other things, like the overall MVC hierarchy, how partials work, how views work and so on.

I think part of what's keeping me interested in Ruby and Rails is how difficult it is for me. Coding is not something I have a great natural talent for, so I really have to work to make progress. Still, I'm proud of what I've learned so far and there is no shortage of great, helpful people in addition to a treasure trove of information available, so I'm confident I'll get where I want to be. Sooner or later.

Another problem I've had is describing exactly what I want to do. I think in the future, I'll benefit greatly from mapping projects out better beforehand as well as learning how to describe my ideas better.

Tuesday, March 22, 2011

Swear to blog

I just finished up the Blog tutorial I've been working on the last few days. It was clear, easy to understand and a great introduction to views, models and controllers, as well as building a functional Ruby on Rails application.

I know people always go on and on about how easy Ruby is and I'm starting to see why. I still don't have a grasp on writing my own code, but I get why something is done. I feel like I've got a good understanding of the basics, which is absolutely important for proceeding.

I'm also amazed at how easy it is to add new functionality to an existing program. Initially I built the blog and was able to create, view and destroy posts. Then I went back and added comments with the ability to create and destroy them as well. THEN I went back and added tags.

So I'm getting it. I've gotten over feeling overwhelmed (to be fair, I got over that a while ago) and I just feel excited about learning. More coding!

I think my next step will be to return to Beginning Ruby and skip over chapter 13 altogether. I'll probably read through it for reference, but it used MySQL a lot and I really got hung up on that crap for a while. Still, that book has been a great resource and finishing it up will be worthwhile.