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

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)

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!


  1. Wow, lots of questions here, let me break these down.

    RE each character will have multiple statistics.
    I think you will find there may be a simpler way to deal with this in code. I would have to understand the problem better but it seems quite likely you may prefer the ease of a statistic model that has many columns for statistics instead of many statistics. Both can work, one is more flexible, and one is easier to code. I would tend toward one statistic model per character.

    RE forced login
    This may be a good opportunity to make a user signup page.

    Also, you can create a user from the console with ease. User.create(:email => '', ...). Your authentication system will have other options that are required I'm sure but that's the gist. If you made a signup/register page the controller undoubtedly makes this call and you can probably look at it to see how it works.

    Another solution is to simply disable the forced login. Just comment out the before_filter.

    RE multiple stats instances
    This is completely up to you, but as I said before I would tend towards a has_one statistic. It's easier to develop and use, but less flexible than has_many statistics.

    RE sqlite3 foreign keys
    It handles it roughly the same as all SQL databases. Chances are you're not using foreign key constraints (not recommended here), so in fact it is identical to all other databases in this respect.

    The foreign key is the "key from one piece of data that points you at another(foreign) one." In this case, the foreign key is character_id on statistics. Without this key, the data would not be associated.

    When creating a model through an association (@character.statistics.create) this foreign key should be set for you already. Imagine you called Statistic.create, the code it would have no idea which character to associate it to, but by calling it through the association you make it clear to ActiveRecord that this foreign key should be set.

  2. I would have to understand the problem better but it seems quite likely you may prefer the ease of a statistic model that has many columns for statistics instead of many statistics.

    Yeah, this is how I coded it to begin with. The statistic model has 6 columns. It's not a matter of having separate models for Strength, Intelligence, etc. But you can still use has_one in this case, correct? The number of columns isn't referenced by has_one or has_many, it's the instances of the model? So if I had a statistic model with one column for each statistic, I'd need to use has_many, but if I have one statistic model with 6 columns, I can use has_one?

    Another solution is to simply disable the forced login. Just comment out the before_filter.

    I didn't think of doing this as a workaround and it sounds like the right solution. I've got a tendency to make small problems seem larger than they are! See also: foreign keys.

    Thanks again for the advice. Sucks I'm stuck at work for another 4 hours. MUST CODE!

  3. Technically has_one and has_many are the same thing, but has_one is just limited to 1 row.

    In this case it will make interfaces to this code significantly easier to develop.