|
Rails is based around the idea that the simple cases don't need a lot of explanation to the computer. So, let's say that you have an Article model. class Article < ActiveRecord::Base
end
There's no need to do things like 1) tell it which database table to use; 2) tell it the setters and getters you want. Those can be inferred. Well, it's called Article so it'll use the articles table and we're going to want a setter and getter for each column.Now, that can be overridden. You can call set_table_name to explicitly tell it to use a table, you can add additional methods, you can override the default setters and getters, etc. That's the idea behind Rails. You need a programming language to describe the decisions you're making that affect how your application works, but for a lot of things you're doing the same thing over and over and there's no reason to keep doing the same thing over and over. Let's say that you wanted to (by default) order the articles by their creation date: class Article < ActiveRecord::Base
default_scope :order => "created_at DESC"
end
You've now defined some business logic so that when you call Article.all, you get them in that order. On the models, you can define any amount of logic you want by creating instance or class methods. In fact, all of those fancy keywords are just mix-ins - method calls that add methods to your class.This is why it looks like Rails is lacking a bit of business. When you call belongs_to :apple, the belongs_to method gets executed as the class is interpreted and that belongs_to method is something like: def belongs_to(associated)
define_method associated do
associated.to_s.camelize.constantize.find(send("#{associated}_id"))
end
define_method "#{associated}=" do |val|
send("#{associated}_id=", val.id)
end
end
Now, it's more complicated than that (since belongs_to adds some additional features), but that's the basic premise. You have this foreign key association and, most often, it's a simple association where you want to define a setter and a getter for that association. So, the belongs_to method takes the name and pops out two methods based on that name. The first is the getter and it makes the name you input into a camel-case and gets the constant with that name. It calls the find method on that constant and inputs the foreign key value to the find method. Likewise, the setter (setters in Ruby are methods that end with the equals sign) and sets the "name underscore id" attribute on the model to the id of the associated object.But you could just as easily define the methods yourself in the Article class rather than using the helper mix-in. Likewise, if you have business logic that doesn't fit in with what's already made, you can define any methods you want on your model classes. The same goes for controllers. Controllers can be pretty small. If you're just trying to get the latest 10 articles, there isn't a lot you have to do - you need to fetch them from the database and store them in a variable. This is another one of those areas where Rails doesn't ask you for things it can assume. Instance variables (which start with the "@" symbol) get passed to the template, local variables (which have no prefix) don't go to the template. The template that gets rendered is the one named "controller/action". Of course, you can override that and call render :template => "xyz/abc" if you like. I'm sorry if this seems a little all over the place, but I'm not sure what kind of business logic you're looking to implement. If you give me an example, I can provide some insight. However, from what you've said, it looks like you've just seen the basics of what models can do - and that's because a lot of the intro code is "let's build a blog" where there isn't a ton of business logic. But you can make any methods (class or instance) you like to do things to your data. Rails creates the basic cases for you - because the basic cases are well-understood. However, you can make them more complex: class Article < ActiveRecord::Base
def title
if Time.now.day == 1 and Time.now.month == 4
return title.reverse
else
return title
end
end
end
|