开发者

What is the proper way to handle "types" in Rails?

sorry if this question has been asked before, I searched but wasn't sure on the proper name for what I'm looking for.

I'm pretty much a newcomer to rails and development in general, I've done some hacky programming but I wouldn't say I know what I'm doing. I've always been at a loss on how to define "types" in my Rails models and in databases in general.

For example, say I have a model "Car" and it has the property "Colour", where Colour is chosen from a known set rather than an RGB value or whatever. Something tells me that there should be another table (and associated model) for Colour and then have some kind of relationship between the two, but which relationship is appropriate? A car doesn't BELONG to its colour, or vice versa.

Or of course I could just store an integer and l开发者_如何学Cook it up in code, but this feels wrong to me.

What did I miss? :)


Color may be a complex object or may be a very simple one, depending on what you need.

  • Simple: Integer subsequently converted to any other format, or hex value like "a3ab34" stored in a string.
  • Complex: You want to map colors to certain human titles.

For simple you'll just have a column in cars named color, and override the reader method to return whichever color format you desire, like so.

class Car < ActiveRecord::Base
  def color(format = :integer)
     case format
     when :integer: super
     when :hex: # ... hex conversion code
     # ... more conditions ...
     end
  end
end

If we're talking about complex case, then it's different. You should then have a separate model called Color. Then Car would belongs_to :color like thenduks said above. It would be more semantically correct to say Car has_one :color but then you're forcing colors table to store car_id which would be kind of backwards. In our case, Car will be storing color_id. So make sure you make a migration that adds color_id to table cars.

Then you should create the migration for colors table, which would include id, title and code for example, and which you'd have to pre-populate yourself using rails seeding stuff. (see http://railscasts.com/episodes/179-seed-data)


A car has only 1 color, so you would say a Car instance belongs_to its Color. Still, your second idea of just storing the color as a number and having those colors defined as constants somewhere is probably more sensible... as long as you dont need to add/remove/edit colors within the app (in other words, 'live').


My experience of types in Ruby is that rather than thinking about what something is you have to think about what something does. It's very jQuery in that regard, don't ask what browser the user is using, as whether their browser can do certain things that we need it to do.

I know that wasn't the brunt of your question but it seemed an appropriate analogy considering the title and my own experiences learning Ruby and dealing with duck typing.

To you answer, the only time you really want to define a new object like color is if it's something you're going to let customers define. In the case of a car this could be totally valid, many cars only have certain colors and they have really particular colors. So indeed a color has_many cars and a car would belong_to the color.

The naming was always slightly odd to me too, the way I just learned was that belongs_to is the model that has the id number. It has its reasons but it's easier to just memorize that one fact than to try to untangle the logic each time. That's all you really have to keep straight and you'll do just fine. :)


For this example I don't think it's appropriate to store a car's colour in a separate model. Colour is a property of a car, so a column in the cars table is the solution.

If you wanted to limit the choice of colours to a finite list, you can use a validation

class Car < ActiveRecord::Base
  validates_inclusion_of :colour, :in => %w( red orange yellow green blue indigo violet )
end

If this is too simplistic for your use case, I recommend you look at ActiveRecord::Aggregations::ClassMethods.composed_of. I do not think an ActiveRecord model is the solution here.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜