6.3. Defining Associations

That doesn't look too good, now, does it? The problem lies in the fact that the appviewscomments ew.html.erb template that's generated by scaffold expects Comment model objects to have an article method. This is not automatically the case because you have not specified an association between the Article and Comment models. To do that, edit the Article model to include the following highlighted line:

class Article < ActiveRecord::Base
  has_many :comments

  # ... other existing code ...
end

Similarly, the Comment model, located in appmodelscomment.rb, should look like the following:

class Comment < ActiveRecord::Base
  belongs_to :article
end

Starting with Rails 2.2 belongs_to is automatically populated for you when scaffolding. In earlier versions it had to be manually specified.

The highlighted lines employ methods to define associations between models that in turn represent relationships between the respective tables in the database. In this case, you defined a one-to-many relationship between Article and Comment.

As you can see, the syntax of these associated methods is very straightforward. Each of them receives a symbol that indicates the associated object (plus optional arguments). They end up reading like common speech: an article "has many comments" and a comment "belongs to an article."

Notice how the symbol passed to the has_many method is plural, whereas the argument for belongs_to is singular. Other association methods are has_one (for one-to-one relationships) and has_and_belongs_to_many (for many-to-many relationships).

Including that single line for each model automatically adds a series of methods that allow you to effortlessly work with the related tables. For example, you'll be able to use the comments method on any Article object to obtain a list of associated comments. For instance, you'll just issue Article.find(42).comments to obtain an array of Comment objects whose article_id attribute is set to 42. Likewise, you can now use the method article to obtain the Article object that a comment "belongs to."

Having added these associations, the Comment model now has an instance method article so you can reload the page http://localhost:3000/comments/new without seeing any errors, as shown in Figure 6-4..

By the way, errors like the one shown in Figure 6-3 are for troubleshooting purposes and are not displayed when Rails is running in production mode.

While you are at it, you can also add validation for the Comment model. Its code becomes:

class Comment < ActiveRecord::Base
  belongs_to :article

validates_presence_of :name, :email, :body
  validates_format_of :email, :with => /A([w.-+]+)@((?:[-a-z0-9]+.)+[a-z]{2,})/i
end

You require name, email, and body for each comment. Then you use validates_format_of to verify that the email address inserted by the end user is valid. That scary looking thing is a regular expression literal. The i after the slash indicates that it should not be case sensitive. Despite its size, this is used to perform only a basic validation of the conformity of email addresses. Regular expressions, which are compliant with RFC 822, are even larger.

You can take a look at a slow implementation here: http://www.ex-parrot.com/~pdw/Mail-RFC822-Address.html. In general it is not a good idea to try to come up with your own very strict regular expression for validating emails. For a discussion on the topic, check out this post: http://www.rorsecurity.info/2007/04/16/ruby-regular-expression-fun, which the preceding regular expression comes from, and http://www.regular-expressions.info/email.html. Using a library like the one pointed out by the rorsecurity.info site may be a good idea.

Figure 6.4. Figure 6-4

Notice in Figure 6-4 that you don't have a convenient drop-down list of possible articles to choose from. Scaffold gives you a text field, where you can enter the article_id, but that's it. Even if it provided us with a list to choose from, this would still be far from what you want in a blog.

In your blog you'll need to make the following three adjustments:

  1. If you run rake routes, you'll see a bunch of /comments paths due to the fact that scaffold added map.resources :comments to the project's routes file. You don't really want people to be able reach http://localhost:3000/comments/new, because a comment is always associated with a given article. Instead, it would be nice to have nested routes, so as to reflect this logical hierarchy in the URL as well (for example, http://localhost:3000/articles/42/comments/new).

  2. You shouldn't see a field for article_id, but rather the new form should appear beneath an article and be automatically associated with it.

  3. A look and feel that is consistent with what you have for the articles. Ideally, you should be able to embed comments in that same layout.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.12.157