My name is Tyler. I'm learning Ruby on Rails. This is a blog for me to talk about what I've learned. I'm no longer completely new to Ruby and while I don't feel comfortable calling myself a coder or programmer yet, I am absolutely a Ruby Enthusiast and a Rails Fancier. I've been working with Ruby on Rails since February 1, 2011. You know that song about "lovin' every minute of it?" Bingo.
Monday, September 26, 2011
Updating to Rails 3.1 and Ruby 1.9.2
Here's where it stands now: A whopping 14 models. 14! Why, Tyler? Why did you do that?
Back when I first started working on this project (in April or May I believe) making things that belong_to a Character, such as Hit Points, Armor Class, Statistics and the like, into separate models made more sense to me because they would be easier to edit. It didn't occur to me that if I only wanted to edit a Character's Hit Points, that I could simply render a form that ONLY had that field on it, and edit the record that way.
So after about 3 hours of talking and eating delicious cinnamon buns, @jqr showed me how to think about the problem in a different way. Rather than having modifiers that are specifically called from Statistics and applied to things like Fortitude Saves, or Attack Rolls, I'll have one method for ALL Modifiers, not a thousand different kinds of modifiers. I'm still rolling this around, trying to get a grip on it, but now that I've begun thinking about Manticore in a different way, I think I'll be able to make much more progress going forward. I already GET how to define methods and call them, as well as how to render partials and views that do a variety of tasks, so I'm most of the way there already, right?
Most of my time tonight was spent trying to get Rails 3.1 and Ruby 1.9.2 installed and cooperating. I was getting a ton of BOGUS errors, about Gems that Rails couldn't find. Turns out you have to install a bunch of crazy stuff for 3.1, like Sass, Sass-Rails, Coffee-Script and so on. WEIRD, right?
One cool thing I noticed: I went ahead and created a scaffold for my Character model, and made statistics into attributes of Character. All the statistics are integers, so when it pops up on the form, you get an automatic drop down that just inputs numbers. I'm guessing this is to get around people entering non-integers, and I bet I can pretty easily limit the scope of these attributes.
I don't think updating to Rails 3.1 and Ruby 1.9.2 was strictly necessary, but this seems like a good time to make a change. Also seems like a good time to get more comfortable (re: comfortable at all) writing and running my own tests, considering that's something I've woefully neglected.
Wednesday, September 21, 2011
Instance variables and local variables in Rails
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
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!
Sunday, September 18, 2011
Nil can't be coerced into Fixnum in Rails
I'm trying to figure out a way to calculate bonuses or penalties from a Character's Statistics, and then apply that method in other Models' views to calculate things like Fortitude saves, attack bonuses and so on. I've been working with a modifier for Constitution and here's what I've got so far.
The logic for calculating a Statistic bonus/penalty is (statistic - 10) / 2. So for a score of 14, we get 2, and for a score of 8, we get -1. Not bad so far!
So I define this method in Statistic controller:
def con_modifier
(constitution.to_i - 10) / 2
end
@con_modifier = @character.statistic.con_modifier
Here's the logic for calculating a total in my Fortitude model right now:
def total
fortitude_base.to_i + ability.to_i + magic.to_i + misc.to_i
end
def total
fortitude_base.to_i + @con_modifier + magic.to_i + misc.to_i
end
nil can't be coerced into Fixnum
Tuesday, September 13, 2011
Validating integer ranges in Rails
Here's what I had before:
class Initiative < ActiveRecord::Base belongs_to :character validates_presence_of :dex, :misc, :speed validates_numericality_of :dex, :misc, :speed def total dex + misc end end
And I've changed it to:
class Initiative < ActiveRecord::Base
belongs_to :character
validates_numericality_of :dex, :misc, :speed
validates_inclusion_of :dex, :misc, :in => -10..20, :message => "must be between -10 and 20."
validates_inclusion_of :speed, :in => 20..200, :message => "must be at least 20."
def total
dex.to_i + misc.to_i
end
end
A pretty minor change, but here's what this is doing. First off, there's no need to validate both for presence_of and numericality_of an object. Validating numericality_of an object will in effect also validate_presence_of that object, since it must be an integer to pass validation.
Secondly, I've added a validates_inclusion_of to ensure that all integers make sense within Dungeons and Dragons rules. For example, :speed refers to how many feet a character can move per round. The vast majority of characters are going to be either 20 or 30, so I set 20 as the base. However, there are ways to get higher speeds, through class benefits, spells, magical items and so on, so I set the upper limit at 200. I don't use this object to make any calculations, but it's nice to have information that makes sense for a Dungeons and Dragons character, since Manticore is a Dungeons and Dragons character database program.
Lastly (and I think this might be a bit of overkill) I added .to_i to my logic, which will ensure all objects are integers before attempting to perform calculations. Am I right about this one? It also sets nil to 0, right? Pretty handy, considering I was wanting a way to set nil to 0 a while back.
I started to bang out a question, but as I was writing I got an idea of how to do what I want to do, so I'll give it a shot before asking for help
Monday, September 12, 2011
Code abstraction and models in Rails
However, last night as I was writing some partials, I noticed I was loading quite a bit of logic into my view and it felt wrong, somehow. I felt...dirty. I was on the right track when I assumed there was a way to collect this logic into a method, then just call that method in the view, rather than having all the logic piling up, making an untidy mess of my code.
But I didn't quite get how to define a method in a model. Sure, I've defined methods such as:
def foo
bar
end
But usually I got this code by following a tutorial, or reading through a book and so forth. It was never my code, and I think that was the reason I didn't really understand it. Now that a situation has arisen that I needed to learn how to write logic into a model and then call it in the view, I understand it. Funny how that works, huh?
Also, I don't think I'm quite as done with Manticore as I thought last night. I'm obviously still learning from working on it, and that's what I'm after. I've got some big ideas that are frankly a bit intimidating (user account creation and log-in, differing account types and permissions for dungeon masters and players, to name just two) but what's the best way to get over being intimidated by coding? By getting excited about coding. It's brought me this far, anyway!
Sunday, September 11, 2011
Code abstraction with partials in Rails
I thought so, but here was the problem. I had some text that said "Add:" with links for items, spells, skills and so forth. I didn't want either the text or the link showing up unless the page hadn't been created. Only showing a link_to method if that page hasn't been created is easy, but I couldn't figure out a simple way of only displaying some text if all pages that could be created hadn't been created. An easier solution would have been just to axe the "Add:" text altogether, but I like it as a bit of guidance and separation.
This may be a case of me understanding partials well, so every problem appears to be a problem that can be solved with partials, but here's how I wrote the code.
First, I created a new partial, called "_menu_create" and threw it in the Characters view folder.
Here's the code for the partial:
Add:
<%= link_to 'Items Page', character_items_path(@character) unless @character.items.exists? %>
...
<%= link_to 'Background Page', new_character_background_path(@character) unless @character.background %>
And here's the method for rendering the partial:
<% unless @character.items.exists? and @character.skills.exists? and @character.specials.exists? and @character.spells.exists? and @character.background %>
<%= render 'characters/menu_create'%>
I feel like this is a bit over-engineered, especially since all it does that's different is not display the "Add:" text, but it works and I'm pleased with the result.
What's your opinion? Is there an easier way to do this? Is there also an easier way to group several conditionals together, so instead of writing the code as:
<% unless @character.items.exists? and @character.skills.exists? and @character.specials.exists? and @character.spells.exists? and @character.background %>
I could group all of these into a grouping called "conditions", and call something like:
<% unless @character.conditions? %>
Which would have the same effect? I'm guessing there IS something like this, and I just haven't run into it. I'm also getting the feeling I'm ready to move onto another project pretty soon, maybe running through more tutorials, or getting another book, or working on another personal project. Any suggestions? Should I keep working on Manticore? It's kind of hard to get a feeling for WHAT I should be working on, just that I should be working on SOMETHING. Crafting Rails Applications isn't quite what I was looking for, either. I was expecting something closer to Agile Web Development and it's more like a series of mini-tutorials, mostly for serious customization and I'm not quite ready for that jelly.
Wednesday, September 7, 2011
More has_one model work in Rails
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.
Wednesday, August 31, 2011
Alphabetical sort method in Rails
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
Just one little change here. We started off with:
<% @character.skills.reject {|skill| skill.new_record? }.each do |skill| %>
<% @sorted_skills.reject {|skill| skill.new_record? }.each do |skill| %>
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.
Tuesday, August 16, 2011
Validation errors in Rails
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
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
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.
Tuesday, August 9, 2011
If and Unless Methods in Rails
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
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
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>
Saturday, July 30, 2011
Models, forms and view pages in Rails
Sunday, May 15, 2011
Triumph of the heart
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.


