The holidays and a one day bout with food poisoning did slow me down more than I expected. I am in Atlanta for New Year’s and the following week which has also slowed my work somewhat. I have a pile of technical posts I want to write, this is the first.
I’m not certain how obvious this is to Ruby veterans or people that regularly use Sinatra and datamapper, but I figured this out on my own. I learned how to set up classes with datamapper and use them with Sinatra from this nettuts tutorial. Prior to discovering Sinatra I had learned some basics about Ruby from several sources. There were some differences between the way the netuts tutorial directed me to create a new instance of a class and how I learned to do that from other Ruby documentation and tutorials. It actually took a couple weeks before I really put “two and two” together and realized the discrepancy. It’s a pretty simple solution and again, maybe it’s obvious to you guys, but it wasn’t to me for a couple weeks.
Essentially it boils down adding a method into your class definition called initialize(). I realize that you do not need parenthesis when calling methods in Ruby, but I will use them when referring to methods in the body my posts to make it easier to identify them. Apparently initialize() is some sort of special or protected method name which Ruby looks for anytime you call the new() method on a class. In the nettuts tutorial the author sets up a class using the datamapper syntax as such:
class User include DataMapper::Resource property :id, Serial property :name, String property :created_at, DateTime end
In the netuts tutorial they were setting up a class called “Notes” with some added properties, but none of that is important for the purposes of this post. This User class is enough. The Sinatra code to create a new instance of the User class using the same structure as netuts would be:
post '/' do u = User.new() u.name = params[:name] u.created_at = Time.now u.save end
Each property is filled directly in the code block in the Sinatra code. This “params” array is data passed from the HTML form with the action attribute set equal to ‘/’. If this is confusing, just look through the nettuts tutorial for the explanation of how to use HTML forms with Sinatra.
As I was beginning to develop my site I realized that there could be more than one place I want to add a new instance of a class from and this would require me to rewrite this block of code multiple times. Additionally, it just makes this “routing” Sinatra file more difficult to read in my opinion, containing details of the classes that really have nothing to do with the routing of URL requests.
I experimented with defining a method in my class definition called initialize(). To my delight, after I defined initialize() for a class, it became the method that was called when creating a new instance of a class. Now my User class definition looks like this:
class User include DataMapper::Resource property :id, Serial property :name, String property :created_at, DateTime def initialize params self.name = params[:name] self.created_at = Time.now self.save end end
and the Sinatra code looks like this
post '/' do User.new params end
For this super-simple example this change doesn’t seem to get you much aside from keeping model details completely inside of the model definitions. When you are dealing with more complex models with lots of properties and detailed logic governing their creation and also having your application creating them for different locations, it is a good bit better to use the initialize method. Also, this is the standard way for defining classes in Ruby, so you might as well stick with it when using Sinatra and datamapper.
One technical post down with some unkown number more to go. I plan on writing a post about the details of the following/follower logic. I may write a post about the geolocation features in EventReview so that the events are filtered based on your location or a location you search. I have a pretty cool form for inputting new events where I use a bunch of jQuery and jQuery-UI in concert with Sinatra and datamapper, the details of which some people would find interesting. Finally, I will most likely write a post about the technical details and philosophy behind the incentives and community moderation features I recently added.
Until then, have a happy new year.