Tuesday, August 16, 2011

Validation errors in Rails

Whoa! I've been chugging along with Manticore the last 5 days or so and making some good progress. However, I've hit another wall (can you believe it?)

Basically here's the problem. I have a model Ac that creates Armor information for a Character. I've created some methods to calculate various data from fields from a Character's Ac model, and to avoid any errors when doing these calculations I need to validate presence_of and numericality_of several fields.

So my problem is two-fold. First off, when creating the Ac, all of the validation errors appear before the user has attempted to enter any data. Furthermore, the user can still create an Ac with no data at all. Clearly my validation isn't working.

Here's the code itself from my Ac model:

class Ac < ActiveRecord::Base
belongs_to :character
validates_presence_of :base_ac, :armor, :shield, :dex, :size, :natural, :misc, :deflection validates_numericality_of :base_ac, :armor, :shield, :dex, :size, :natural, :misc, :deflection

...
end


And the code from my AcsController:

class AcsController < ApplicationController
def new
  @character = Character.find(params[:character_id])
  @ac = @character.create_ac(params[:ac])
end

def edit
  @character = Character.find(params[:character_id])
  @ac = @character.ac
end

def create
  @character = Character.find(params[:character_id])
  @ac = @character.ac(params[:ac])
  redirect_to character_path(@character), :notice => 'Armor Class was successfully created.'
end

def update
  @character = Character.find(params[:character_id])
  @ac = @character.ac
  if @ac.update_attributes(params[:ac])
    redirect_to character_path(@character), :notice => 'Armor Class was successfully updated.'
  else
    render :action => "edit"
    end
  end

end

I'm not sure what could be causing this problem. I've got similar validation for the Character model and it works fine. Any advice? The form_for a new Ac is rendered from a partial in the Character show page, but I'm not sure if that would have an effect on this.

Also, on a slightly tangential note, when rendering a form like this, is that what's meant by a "nested form" ? I've seen this term a few times while searching for a solution and I'm unclear as to what it means.

Here's a link to the project on Github: https://github.com/illbzo1/Manticore

Thursday, August 11, 2011

Adding two columns in a table with Rails

I figured out a way to calculate totals from two different columns in a table, but I'm having trouble extracting that logic and moving it out of my view. In this case, an Initiative's total is the sume of the Dexterity and Miscellaneous modifiers. Here's the code I've got so far:

Initiative Total:
<%= (@initiative.dex + @initiative.misc) %>

Pretty easy, right? But I'd like to just call this something like init_total and call it that way, but I'm not quite sure how to write that code. Also, does it matter if I throw a .to_s on the end of this? I noticed it displays the same either way, but I don't know if a .to_s is strictly required. I'm guessing since this information is already a string, converting it to a string is redundant.

Just a quick update. Feels good to be making daily progress on Manticore, especially since I spent a long time spinning my wheels.

Wednesday, August 10, 2011

Implementing new methods in Rails

I think it's important that every time (or nearly every time) I sit down to code that I try to do something I don't know how to do. I'm making good progress with using the code I've figured out and applying it to other similar things. For example, with my Manticore app I can use the same methods to create Items to also create Special Abilities and Spells.

But what I want is a way to sum totals from different columns in a table, then display that total in the view. I was messing around with the sum and count methods I found in the Rails API, but haven't quite gotten this figured out. The result is a pleasant headache, and that's what I'm going for. I can't just rest on what I know, I need to be stretching my boundaries when I code.

I think the end result will be I'll learn new things faster and be able to work around road blocks more quickly when they DO arise. My ultimate goal isn't simply to build this or that application; I want to understand how Rails applications work, how they go together and how they're built.

Also, I'm going to start blasting out my rails blog posts in Google+ in addition to Twitter, so if you're seeing this twice? Sorry about your luck!

Tuesday, August 9, 2011

If and Unless Methods in Rails

Sometimes shit just works.

Sometimes I sit down to code for an hour or two and everything I try either works right away, or is broken in such a way that the first fix I attempt works.

Today was one of those days! I had some minor successes straight off the bat, such as moving Delete methods into Edit methods, moving Edit methods into the Menu partial along with navigation and changing the Show method for Characters in the Index view to display character.name instead of a generic 'Show'.

But here's the big triumph of the heart tonight.

You may recall in my last post I was talking about how in the menu partial I didn't want to display pages that didn't apply to all characters. I don't want a spell tab in the menu for a character that doesn't learn spells, for example. So I figured out a way to solve this problem, and the really beautiful thing is the solution was maybe two lines of code. Why did I think this would be such a big deal?

Here's what I had originally:

<%= link_to_unless_current 'Special Abilities', character_specials_path(@character) %>

Changing this code so the Special Abilities page only shows up if it's been created is easy enough:

<%= link_to_unless_current 'Special Abilities', character_specials_path(@character) if @character.specials.exists? %>

But then I run into a problem. With the previous code, it was simple enough to create a Special Ability, since you just clicked on the Special Ability link and the show page would render the form, allowing you to create a Special Ability, or edit a previous Special Ability. So obviously I need to land a link to create that page somewhere.

The Character show page seems a logical choice, since it will exist before a Special Ability will, and a Special Ability's existence will depend upon a Character's existence, right? So let's wire that up:

<%= link_to 'Create Special Abilities Page', character_specials_path(@character) unless @character.specials.exists? %>

Making pretty good use of those if and unless methods!

I know Rails programmers often talk about how they can't believe something is so easy to do with Rails, but shit, I can't believe this was so easy to do. And it feels good to make this much progress on my own, because I feel like a lot of the time I'm just asking for help. This is a pretty good indicator that I'm figuring out how things work, where things go and how to make Rails sing and dance for me.

Monday, August 8, 2011

Working on personal Rails projects

So I've made some pretty serious progress with Manticore. So far, here's what I've got:

The ability to create a new character, with several attributes includine statistics, hit points, armor information and so on.
The ability to create and destroy items that belong to said character.
The ability to create and destroy special abilities that belong to said character.

Not bad! I feel like I'm making some real progress here. Here's a few screen shots:




When I work on a Rails application (and especially when I work on one for myself) I like to keep a to-do list of features I want to implement. It feels GREAT to have a roadmap when working on any project, and Rails is no exception. Here's what I've got so far:

Add Skills - Every character will need skills, and I haven't started to tackle this yet because I'm not quite sure how to do it. I think simplest would be to make Skill a model with several defining attributes that belongs_to Character, with a has_many relationship. This would allow users to create skills as necessary, and not add Skills they either don't have or don't use. Actually, you know what? I just talked myself into doing it this way. BINGO!

Add Feats - Feats are going to be similar to Special Abilities, and I'm not sure if I want them to be in their own tab in the menu partial or lumped in with Special Abilities. I like the idea of keeping them separate, because some characters won't have Special Abilities, though most (if not all) characters will have Feats. I also don't want that menu partial to get too bulky.

Add Animal Companions / Spells - Here's another thing I want to do. As of right now, my menu partial displays the same things for all Characters (although some of these are just placeholder text) - Character | Items | Skills | Special Abilities | Spells - and it struck me the other day that I shouldn't be displaying these pages if the character doesn't have them yet. After all, a fighter doesn't learn spells or gain an animal companion, so why show them in the menu partial? So once I get some of these other relationships hammered out, I'll be looking for a way to add these, perhaps from the Character's view page, and have pages populate into the menu partial only if they've been created. Eventually I'll want the ability to drag and drop these to organize them by user preference, but let's not get too deep into the styling woods just yet.

And finally, I'll want to clean up the actual code I'm using. @unixmonkey showed me a way to get what I want done, but said it was messy and he was right. Still, it's more valuable to me right now to have code that works and not the most efficient code possible.

Remember when I said I find myself focusing more on my own projects than the tutorials and books I've been using? That still holds true.

Sunday, July 31, 2011

More Routing Issues in Rails

I've made some progress with Manticore this weekend, but I've hit another wall. Surprise!

Thanks to @unixmonkey and @jqr, I can now add, view and destroy items, linking to the items index page from a menu partial that is called from the character's show page. Success! However, I thought it might be handy to be able to edit items. And that's where my problem comes in. For a while, I was getting a routing error. Then I edited the code and now I'm getting this old chestnut again:

undefined method `item' for #<Character:0x103f0ce50>

What gives? I thought I'd gotten rid of this guy when I defined the character in the items controller.

Here's my edit method from the items controller:

  def edit
   @character = Character.find(params[:character_id])
   @item = @character.item
  end

  def update
    @character = Character.find(params[:character_id])
    @item = @character.statistic
    if @item.update_attributes(params[:item])
      redirect_to character_items_path, :notice => 'Item was successfully updated.'
    else
      render :action => "edit"
    end
  end

And here's how I'm calling it from the partial I created for creating and editing items:

<%= link_to 'Edit', edit_character_item_path(@character, item) %>

Any more tips? I'm pretty sure I'm just not writing this correctly. This code is based on what I've got for my other models (statistics, armor class, etc) but I wonder if it might be different based on a couple of things. For one thing, those other models have a has_one relationship with Character, while Items has a has_many. For another, the has_one models are all displayed in the Character show page, while Items is being created from the Items index page. Am I on the right track here? Any advice as to how to solve this issue?

On a less begging for help note, I've spent a good 5 hours working on Manticore this weekend. I notice when I'm working on a personal project and not a tutorial, I can focus for longer periods of time and I find the work more interesting. When doing a tutorial, I feel like it's a valuable use of my time but it's not an interesting use of my time. Does that make sense? Regardless, I absolutely lose track of time when working on my own projects, even if it's just repeatedly butting my head up against trying to get a goddamn edit method to work.

Saturday, July 30, 2011

Models, forms and view pages in Rails

I'm back to working on Manticore after a couple months away doing tutorials. I've made some progress this afternoon, but now I've run into a snag.

Here's what's going on: I have two models, Character and Item. I've created a form_for new Items that belong to a Character. The form works fine when displayed in the Character view, but what I want to do is move the form and Item listing out of the Character view and into the Index page of Item, so I can link to it from the Character view. I've got a _menu partial that I'll be using to display other views relating to Character, such as Skills, Spells, Items and so on. I'm not sure what the issue is, but simply transplanting the code as is gives me this error:

undefined method 'items' for nil:NilClass

Here's the exact code I'm using:

<h2>Add an item:</h2>

<%= form_for ([@character, @character.items.build]) do |f| %>
  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :type %><br />
    <%= f.text_field :type %>
  </div>
  <div class="field">
    <%= f.label :location %><br />
    <%= f.text_field :location %>
  </div>
  <div class="field">
    <%= f.label :description %><br />
    <%= f.text_area :description %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

<table>
<% @character.items.each do |item| %>
  <tr>
    <td><%= item.name %></td>
    <td><%= item.type %></td>
    <td><%= item.location %></td>
    <td><%= item.description %></td>
  </tr>
  <table>
<% end %>

Like I said, this works just fine in the character/show page, but does not work when placed in item/index and linked to from my _menu partial. Any ideas?

Here's a link to my git repository: