Posts [ 1 to 20 of 46 ]

Topic: Building a Glossary from a Legacy DB

I have to rebuild a simple glossary for a client and am not sure of the cleanest way to do it.

Right now the glossary is built in Textpattern, a PHP CMS which we have outgrown. For the record, Textpattern has quite a few columns in its article table, but all I need are the Title, Body & Section fields to be mapped to :title, :body and :section_id

I know for sure I will need a sections table, model, controller and views. I am also positive that each section has_many :articles and that my articles table will need a section_id column.

The biggest problem here is that textpattern stores the actual name of the section with each article instead of its numerical ID. WIth such a huge inconsistency, I dont know how I can get around assigning the section ids of all 4,000 articles by hand (argh!)

For the sake of positive thinking, lets assume that this is stupidly easy to fix. Once I have imported this legacy data I am then faced with the task of how to structure these sections in Rails, with clean URLs that look like this:

Where I get confused is how to pass a range of values as an argument. One of the glossary sections is just numbers 0-9, so should I pass a * into the original argument?

Also, from a maintenance standpoint, am I going in the right direction? You folks are always talking about stinky code, and something about having 26 actions in one controller doesn't smell too good. Perhaps I can abstract this even further, but I'm not sure how.

The LEFT sql method will return the first character. Using the "IN" command allows you to do something really cool: allow ranges. Which means you can create an action to handle the number range in the controller. For example:

Re: Building a Glossary from a Legacy DB

Ok so Im still a bit in the dark on how I can get my code to jive with that params hack of yours. I also dont see the point in defining custom routes if I can get those routes automatically by defining the 26 actions. Seems to be the same amount of code, though probably not the best practice.

What do you think? If i did use the params, I still dont understand the following:

1. How I can pass letters to that in my routes2. How to link to letters in my views3. How to index for each letter

Now at first I was concerned that this might not be so DRY, but then I remember what you were saying about real vs fake duplication. Since the behavior of each letter can easily be changed from one private action, I dont see the harm in having these 27 simple actions just to take care of my routes.

As always I am open to refactoring suggestions as I find them highly educational. But for now, this is working splendidly.

Re: Building a Glossary from a Legacy DB

pimpmaster wrote:

Now at first I was concerned that this might not be so DRY, but then I remember what you were saying about real vs fake duplication. Since the behavior of each letter can easily be changed from one private action, I dont see the harm in having these 27 simple actions just to take care of my routes.

Nah, this isn't good duplication. True, it could be worse since at least you are calling a private letter method. But the question is: why? There is no benefit to separating each letter out into a separate action. This should be done in the routes.

I don't understand how you want the routes to behave so it's hard to give a recommendation. What is the 2nd parameter, the ":id" in your case, used for? Here's how I would do it. Add these two routes to the top of your routes file:

Re: Building a Glossary from a Legacy DB

Here is the deal with numbers. As you can see, I tried to setup a custom query to account for entries starting with periods. At first I was returning all my entries but after tinkering a bit, now I am returning zero

Re: Building a Glossary from a Legacy DB

Yup, this was exactly my problem. Removing the REST from my routes and views has all my actions triggering where they should be. All is 90% perfect. Except now I am getting the same problem as before. My numbers method is returning all my entries for some reason

[4;36;1mGlossary Load (0.107206)[0m [0;1mSELECT * FROM glossaries WHERE (LEFT(title, 1) IN ('.',0,1,2,3,4,5,6,7,8,9)) ORDER BY title ASC[0m

The query looks fine to my untrained eyes. No idea what could be wrong.

Re: Building a Glossary from a Legacy DB

Re: Building a Glossary from a Legacy DB

There is one minor pitfall of using params to set the find method. if people enter in some random url text that is not A-Z or the string 'numbers' I get a blank page with no query results. Gonna investigate how I can make this more airtight

Re: Building a Glossary from a Legacy DB

Wow..Im so close I can taste it!

The only thing left is to gracefully handle these routing exceptions, which I am guessing is outside the realm of my routes.rb file. This looks like a job for my controller for sure. Since all my glossary actions render through my index action, that seems like the obvious place to catch exceptions...

Re: Building a Glossary from a Legacy DB

Setting a requirement in the routes doesn't even call the action, it just moves onto the next route if it doesn't meet the requirements. If no route is found it raises that "no route" error. To me this makes more sense, but if you want to provide a different error than 404 then you can remove the requirements from the routes and do the check in the controller:

if params[:letter] =~ /^[a-z]$/i # good letterelse # bad letterend

Untested.

pimpmaster wrote:

Which raises another question. My logs show this as a 404, so I assume I will only see this message in development mode and production should reroute to my 404 page. Correct?