1

I'm developing a Ruby on Rails app where one of my database tables has 10 columns (pile_1 through to pile_10). It would be convenient to access these columns in the model as a 10-element Array.

It feels like I should be able to coerce composed_of into doing what I want, but I can't figure out how. Can anyone enlighten me, or suggest a better tactic?

2
  • Is it in your power to change the schema? Commented Jan 6, 2010 at 17:17
  • Yes. This is a personal development, so I have full control of it. Commented Jan 6, 2010 at 18:43

2 Answers 2

6

Would

def piles
    (1..10).map{ |num| self[ "pile_#{ num }"]}
end

not suffice?

Sign up to request clarification or add additional context in comments.

2 Comments

Hah. That's neat. In this case, yes, that should do all I need, because I don't expect to need to /write/ to piles_n at any point. Presumably Model.[](<string>) is a method of ActiveRecord::Base?
For clarity you might want to use read_attribute("pile_#{num}") instead, but the square-brackets accessor is functionally similar.
2

Since you have the power to change the schema, you should. Storing an array as separate columns in a table is denormalized. Whether or not your schema is normalized might not matter to you, but your current difficulty is a direct result of a denormalized schema.

What you ought to do is to create a new table, piles, like so. I'll use postgres syntax, since that's what I know. I don't know the name of the table which currently contains all of the piles* columns, so I'll call it "foo":

create table piles (
  id serial primary key,
  foo_id int not null references foo(id),
  value text not null,
);

Every column you now have in foo exists instead as a row in piles. In the model for piles, add:

belongs_to: foo

and in the model for foo, add:

has_many: piles

In your controller, once you have a foo in hand, you can access its piles with foo.piles

2 Comments

Well, I am doing this somewhat to teach myself RoR, so I should probably teach myself properly and do it like this (although Farrel's solution is tempting in simplicity). What would be the best way to grab input values for the Piles objects in a Foo creation page, in this case? form_for(@foo) presumably won't Just Work; do I want a loop over <% for @pile in @foo.piles %> creating <fieldset>s within my form_for? I can't figure out the right syntax. ... should I be creating a new question for this?
Having futzed about with a lot of plausible variants, I can't get this to work, and it seems complex. I'm going to mark this answer as Correct (although I may end up resorting to Farrel's less architectural simple solution), and ask a new question about forms.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.