Showing posts with label models. Show all posts
Showing posts with label models. Show all posts

Wednesday, September 21, 2011

Instance variables and local variables in Rails

I've got a lot to learn about local and instance variables. I already knew 'character' meant a local instance of character, but I thought '@character' referred to another model, and not an instance of the Character model. I knew that sometimes if Rails was complaining about an unidentified local variable, putting an @ in front would often fix the problem, but I didn't know why. I think I've got a better handle on this, but I think the time has come to do some serious background reading to try and patch up some of the holes in what I know and what I think I know.

On the other hand, thanks to help from @jqr and a healthy does of trial and error, I've gotten that pesky statistic bonus problem figured out. This is what ended up working:

def total
  fortitude_base + character.statistic.con_modifier + magic + misc
end

And here's the con_modifier definition from my Statistic model:

def con_modifier
  (constitution.to_i - 10) / 2
end


I'm keeping it as .to_i now, as a fix for a case where a player tries to create a Fortitude save before a Constitution score has been entered. The .to_i translates a nil record to 0, so Rails does a temporary calculation (which isn't shown) rather than displaying an error. Not sure if there's a better way to handle this (perhaps simply checking that statistic.constitution.present? before performing any calculations) but it works for now.

More importantly than simply figuring this one instance of how to define logic in one model and then call it in the view of another is understanding HOW it works. I can extrapolate these methods and apply them to other things: skills, attack rolls, armor class, etc, etc. Once again, Manticore proves to be a useful learning tool! SUCCESS!

Wednesday, September 7, 2011

More has_one model work in Rails

When it comes to coding, it seems like I've got good days, bad days, and frustrating days. Sometimes the Venn diagrams of these days overlap quite a bit. Take today for example.

I've been coding now for a little over 2 hours and I've finally gotten a problem straightened out. If you'll recall, I was attempting to build a Background for a Character, have it show up in my menu partial, and editable from there. I had a method that would build models with a has_many relationship to Character, but Background will have a has_one relationship and it was proving a bit trickier. I've more or less got it straightened out now (at least it's working on my local machine) so I've thrown it up on Heroku.

Manticore on Heroku

I've also done some more work, simplifying the data that's actually displayed in the view, while still allowing users to manipulate that data with an edit action. My reasoning is a user may always want to know what his total Armor Class is, but how often do you need to know what your Deflection modifier is? Not often, that's how! So basically, if you're rarely going to need it, why display it all the time? I think eventually I'd like to have an arrow users can click on that might expand that information, while displaying the bare minimum by default. I'm not sure what I'd use for this, but it sounds like a problem for Javascript.

Also, don't mind those saving throws! They refuse to work. What a lazy model! This merits a bit of examination. And I actually just realized it's not working when creating a new character on Heroku. Thanks, Heroku!

Still, it feels good to have this problem figured out. I've been wrestling with it for a while, and now I can move on to wrestle with other, more interesting problems! Like this mysterious SAVING THROW problem that's arisen. What could be going on here?

Absolutely LOVE crossing things off my list. Although I appear to have added several more. As usual.

Monday, September 5, 2011

Difference between build_model and create_model in Rails

I keep a note pad with features I want to add, things I need to fix and other reminders to myself whenever I'm coding an application. I've got a few methods defined in my models that will calculate totals. Needless to say, these methods aren't going to do anything but complain if the data fields they use to calculate a total either don't exist or aren't integers. What to do?

Validation to the rescue! But I had a problem. A minor problem. The models I speak of all belong to a main Character model. Take my Initiative model for example. It belongs_to Character, and Character has_one Initiative. I have a few fields in Initiative: :dex, :misc, and :speed. These refer to a Character's Dexterity modifier, any miscellaneous modifiers and how many feet that Character can move in a round. So I have this method defined in Initiative.rb:

def total
  dex + misc
end


This way, I can simply call Initiative.total in a view and Rails will calculate the total for me. Cool, right? And this is where validation comes in handy. However, here's the issue I had. My validation worked, but it was showing an error BEFORE any data had been entered. Definitely better than not working, or allowing a user to enter a B instead of an 8, but I'd rather not show an error message if no error has been made. So what was the solution?

First, the validation I wrote, in my Initiative model.

validates_presence_of :dex, :misc, :speed
validates_numericality_of :dex, :misc, :speed

This all looks good. I suspected the error was in the way my new method was written in Intiatives controller, but I couldn't figure it out, so I asked for help on StackOverflow. User m_x was kind enough to point me in the right direction.

def new
  @character = Character.find(params[:character_id])
  @initiative = @character.create_initiative(params[:initiative])
end


This bit of code was the culprit. Easy enough to fix, though.

def new
  @character = Character.find(params[:character_id])
  @initiative = @character.build_initiative(params[:initiative])
end


It turns out the reason my validation was being called before a user had entered any data is because the create method creates a new object and attempts to save it. In this case, it wasn't saving because it failed the validation, because nothing had been entered yet. On the other hand, the build method creates a new object, but does NOT save it. Easy enough to remember! As an added bonus, this gives me some ideas on how to tackle another problem I've been thinking about.

This mistake feels like something I should have known before hand, considering how much time I've spent reading through the Rails API, but I have a hard time holding on to information until it becomes practical. But now that I've used this, and cemented exactly what the difference is between build_model and create_model, I won't make the same mistake again.

One less thing, right?

Thursday, May 19, 2011

WTF is an attribute

So I've run into another wall in my work on Manticore. Basically, here's where I'm at right now:

I have the Character model, with several models with a has_one association: Statistic, Fortitude, Reflex, Will, Armor, Hp and Initiative. These are all displayed on the Character show page.

What I want to do is create a horizontal menu bar that link to other pages with further information. The first one I want to do is an Items page, with various items such as Weapons, Armor, Magic Items, Gear and Treasure. I'm seeing these as separate models that belong_to the Character model, but I'm unsure how to go about building this.

Look, I made some visual cues (mostly because I am awful at explaining what I'm trying to do)


Here's a rough idea of how the final, styled application might look. At the top, you'll see "Items." This will be a link that takes a user to a new page, like so:


So now for more questions!

When I asked about this on Stack Overflow, several people said the models I've created for Character (Hp, Armor, Statistic, etc) should really be attributes. I'm not clear on how an attribute differs from a model. Can a user edit an attribute from the view the way a user can edit the model, the way I've built it? Am I creating too much complexity here? My thinking was that things that change (relatively) often, such as Items, Spells, Statistics, should be Models for ease of editing, styling and displaying, whereas things that don't change, such as a character's name, class, race, etc, would be created as columns in the Character model.

Should these be attributes instead of columns? Are columns attributes? I'm not entirely sure what attributes are, and it's hard to find concrete information.

In other news, I've been reading through the archives of railstips.org. I found an article about 12 great rails tutorials, but the problem is the article it linked to is 6 years old. What! So if you've got any great tutorials that are more recent, lay them on me.

Onward!

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.

Monday, May 2, 2011

Mo models, mo problems

So I've made some more progress with Manticore, thanks to the help of the internet at large and my friend Eli. I've finally gotten the problem of each character sharing the same set of statistics straightened out. I restarted the project and kept the old code so I could compare it. This time around I'm using partials to render and display the statistics in the character view and it's keeping everything much tidier.

Keeping my old code was a good idea, because I'm still referencing it. So far, I'm able to create a new character, then create statistics for each character. However, I'm still having a couple of problems. Each character can still have multiple statistics and I don't have a way to simply update that characters' statistics. Tomorrow I'm going to look through the old code because the first time around I generated a scaffold for statistics and it generated a method for editing.

I've been a bit discouraged because I didn't make much progress this weekend. And in the application I'm building with Agile Web Development, I hit a wall because I edited the code to force users to log in before proceeding without creating a user first. So now I can't view the changes I've made until I either create a user somehow or undo the last dozen or so edits. Needless to say, I've been discouraged from working any further on this project.

Is there a way to simply add a user to a database? Maybe with rails console? I might look into that, but for now I'm focused on working on Manticore again, especially since I'm making some progress.

A few more questions. I'm still unclear on has_one vs. has_many. For example, I have this code for the character model:

class Character < ActiveRecord::Base   validates :name, :presence => true
  validates :profession, :presence => true
  validates :level, :presence => true

  has_many :statistics
end

Is has_many the correct association to make here? The statistic model is a table with 6 separate stats. So does it count as one table, or six individual elements? has_many is working, but I thought if I wrote it as has_one, I might avoid the problem of having multiple instances of the statistic model.

And how does sqlite3 handle foreign keys? I'm still unclear on exactly WHAT a foreign key is. Here's my guess:

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

In this code from the statistics controller, I'm assuming the foreign key is @character in the @character.statistics.create declaration?

I kind of feel like some very basic stuff is giving me trouble, but I'm still learning and having fun, so onward!

Monday, April 11, 2011

Dungeon Roller progress

So I'm not entirely at a loss here. I've got the main Character model and three other models associated with Character: Statistic, Safe and Combat. Here's what the Character screen looks like:


Once you click through on a character, this is what you see:


Now say you want to click through on Statistics:


But here's the problem. The individual characters are all using the same instance of the Statistic model. I haven't worked with the other models yet, but I'm assuming this would be true for them as well. How do I need to edit the code so each Character has a separate Statistic, instead of the same Statistic being shared?

Here's my code from the routes.rb file:

DungeonRoller::Application.routes.draw do
  resources :combats

  resources :saves

  resources :statistics

  resources :characters do
    resources :combats
    resources :saves
    resources :statistics
  end

And some code from the models:

class Character < ActiveRecord::Base   has_many :statistics   has_many :combats   has_many :saves end And each of the other models have: class Statistic < ActiveRecord::Base

  belongs_to :character

end

I thought associating these as has_many would solve the problem, but apparently I was wrong. Any input on this would be greatly appreciated!

Saturday, April 9, 2011

Model misbehavior

I've been trying to get a handle on models and associating them with other models this weekend. Here's what's going on:

I'm working on Dungeon Roller and I've created two models: Character and Statistic. What I want to do is have Statistic display under Character. So logically I need to associate these models such that Character has_one Statistic model and Statistic belongs_to Character, right? These associations (has_one, has_many, belongs_to and has_and_belongs_to_many) all refer to how many of those models can display the model they're associated with, right?

If I can get this relationship figured out, and make it so that Statistic will display on Character and remain separately editable, I can use that as a template to hammer out other models I've got planned. I'll eventually have 7 or 8 models that belong to the main Character model. I ran into some trouble earlier when I named Character as Characters, not realizing that is not the way to do things. I also ran into some trouble with reserved keywords. I had "class" as a string in the Character model and eventually figured out I couldn't use it.

So while today's been frustrating because I haven't made as much progress as I'd like to, I got those two things figured out at least.

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.