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.
Sunday, October 2, 2011
Using Ruby to Solve Problems
I work full-time doing SEO for an e-commerce site, and a while back we ran into a problem on our site with duplicate content. We needed a simple tool for entering two blocks of text and calculating how similar they were as a raw percentage. We eventually found some tools, but they weren't quite what we needed and weren't that great.
So I got the idea of building something using Ruby to do just this and spoke to my friend Eli about it. I still haven't actually BUILT this little program (and I'm sure it WOULD be little, at least at first) and part of the reason was that I didn't have a great idea of HOW to build it. I assumed I might have one model, say Text, with two textarea fields that could be compared, then spit out a percentage for similarity.
Obviously, I'd be using Ruby to make this calculation and that would be a matter of defining a word, counting instances of words, and then making a comparison between both blocks of text.
I've been doing a lot of work using Ruby to open and edit files, so it's obvious I could do similar operations to open and compare files, then generate a report based on that comparison. Not an elegant solution, since users would want to paste text into fields and compare them, not upload files to compare. But I'm sure it's doable. So that might be my next project.
I kind of tend to bounce around between projects, but I'm learning the entire time, so I don't feel bad about it. That's what these projects are for, right?
I also tend to think of an idea, and immediately think of ways to expand it even before I have the original idea working. For example, I'm already thinking of how this project could be expanded to do other things with text, such as identifying words that are used too frequently, identifying passive voice, identifying and suggesting replacements for adverbs and so on. In this case, I think it's because the original problem seemed to be "How can we identify content that's too similar in terms of SEO?" but I've begun thinking of it as "How can we write better content for the web?"
From my limited experience and understanding of web development, programming and computer science in general, it seems to be a matter of identifying a problem and then finding a solution. Am I far off the mark here?
Tuesday, September 27, 2011
Learn Ruby the Hard way
Learning Ruby the Hard Way
I've been meaning to beef up my Ruby skills, and although this site is largely review for me, I think it's GOOD review. I'm definitely getting in the habit of commenting on my code, which is something I've been meaning to do for a while now. I'm already through the first four exercises, so I don't anticipate this taking very long to get through.
When I first started learning with Beginning Ruby, I read through a bunch of Ruby code, but it wasn't very practical, since I had yet to get my filthy mitts on Rails. And now I've been hitting Rails pretty hard for a few months, and while I've used Ruby here and there, I've been feeling like I needed to get better acquainted with it. So here we are!
This is a good resource, and I wish I'd found it (or it had been available) when I got started. It's well written, engaging and doesn't hold your hand too much. The author assumes you can do some basic things, such as researching terms you aren't aware of and figuring out why an error happens when it does.
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!