4

I'm currently creating a web application with Ruby on Rails and I'm facing an conceptual problem about the MVC pattern.

If I need to check, for example, if the name of a data that I want to add in the database exists in a given an array, where do I need to do this? In the controller or the model?

I read everywhere that the model only has to care about the database stuff so I guess it's the controller job.

But with Rails the model seems to do more stuff like the data validation (validate, :presence...) so I'm wondering if it's finally the model which does that?

If it's the model job, it means that I need to pass a controller attribute to the model (the array comes from an API), is it weird?

As asked I give you more details:

My application gets a list of items from an API. I include this list in a form (like in a select tag) and then when the form is submitted I get id of the selected item to finally add it in the database with other information from the form.

Before adding the data to the database I just want to be sure that the id of the item is valid (that's why I need to check if it is present or not in the array - in case of the user modify manually the HTML from his browser...).

5

This is an ancient debate really. It goes all the way back to the first databases and the notion of "referential integrity", which in turn is a variation of the strong-typing / weak-typing debate.

Who's job is it to make sure that data is stored in a consistent and "known good" manner? MVC purists will tell you it's the controller's job. Database architects will tell you it's the model's job (or even the database's job). Ux people might even tell you it's the view's job! Big Data guys may say "It's the person using the data's job."

After being a software engineer / architect / developer for 20+ years, I've come to the conclusion that often the concern is important, but how you solve it is less important, so long as you decide on an approach and maintain it. So, my advice would be something like: rather than asking for people's opinions on dogma about it, think through solving the "who owns validation?" discussion using three different approaches: model, view, and controller. Think about how your app will behave if you solve it those three different ways. Will your end users be satisfied with all three approaches? Chances are, depending on where you put this, your end users will experience something different. Do they have an opinion? Also, which route costs you the most in terms of time and money? Which will be easier to maintain and explain to new people? What about security? All of these things are important considerations when designing a system, and dogmatic answers don't factor these things in -- they substitute a common pattern for your precise context. Sometimes that's a good idea, sometimes it's a shoe-horn disaster. Only you can figure out which applies.

1

Take maxims such as "thy model shall only care about the database stuff" with a grain of salt. Dogma has no place in engineering.

In order to answer this question you need to first understand the nature of this validation array, and whether it fits conceptually with the model or with controlling the model.

The fact that these names are stored inside an array is inconsequential; you could be sending names out to a serial port and receiving back "yes" or "no" answers for all you care. This could still legitimately be part of your model. The question is: does the task of validation sound to you more like "controlling" the model, or like querying the model?

You have not provided enough details about this mysterious array, but I am tempted to believe that it is 100% part of the model. The names that it contains could have easily been stored in the database, but for some reason someone decided not to. If you narrowly think of "the model" as "the database", you might be mislead to think that they don't belong to the model, but if you realize that your model is your representation of all of your entities and the relationships between them, then perhaps it might begin to make sense that the contents of that array are simply describing a relationship which for some reason was not encoded in the database.

After the amendment to the question, I would say with even greater confidence that the list of items (and therefore the list of their ids) is part of the model, though I still cannot say it with complete confidence, since it is still not clear to me what is the nature of these entities and what is the domain that the database describes.

It seems to me, however, that what you are missing is an abstraction layer which combines the database and the API and whatever else you might have into a uniform model which looks homogeneous and spares the rest of your code from having to be concerned about different sources for different subsets of the information that it works with. Conceptually, if these entities have ids, and these ids are stored in the database, then they are all part of the same model, regardless of where they come from.

  • I updated my post to give you more details about what I'm doing. – gaetanm Apr 29 '15 at 14:04
  • @gaetanm I amended my answer. – Mike Nakis Apr 29 '15 at 15:01
  • @MikeNakis So to summarise, I have to check this stuff in the model right? – gaetanm Apr 29 '15 at 15:06
  • 1
    Oh, you don't have to do anything. Practicality and pragmatism might require that you leave things the way they are, if it already works and if altering it would be a lot of work. But if you want to follow best practices, then: all of the information (including the items that you currently get from some API) should come from the model, and the model should of course do the validation. – Mike Nakis Apr 29 '15 at 15:09
0

A code example would help, but in rails, validations belong in the model. Check out validates_inclusion_of.

Also, you should be aware that models dont nescessarily have to be backed by persistence. There are lots of times when it's appropriate to use plain ruby objects. In general, its best to keep as much functionality out of the controller as possible, largely because controllers test are often slow to run, and awkward to write.

  • validates_inclusion_ofseems to be what I need. But it means that I have to pass the array from the controller to the model. Isn't it weird? – gaetanm Apr 29 '15 at 14:09
  • Is there a reason I'm missing why this array needs to be defined in the controller? – Rorshark Apr 29 '15 at 15:09
  • Because the controller makes the request to get the API response (by using a dedicated module). – gaetanm Apr 29 '15 at 15:38
0

If you only want to check that the name exists, yes it belongs to the model.

From wikipedia:

A controller can send commands to the model to update the model's state (e.g., editing a document). It can also send commands to its associated view to change the view's presentation of the model

You are not doing any of those. You are checking if the name already exists in the database. Think of it as an extra validation.

  • I think you don't really understand what I'm trying to do. I updated my post to give more details about what I'm doing concretely. – gaetanm Apr 29 '15 at 14:16
  • How is your database build? I don't see why checking for the uniqueness of the id of the item is no valid, based on what you wrote. Rails has ways to make that kind of query to the database. You don't need to pass a controller attribute to the model. – cauchy Apr 29 '15 at 14:25
  • I just want to check if the id of the selected item chosen in the form exists in the array coming from the API. There is nothing about uniqueness. – gaetanm Apr 29 '15 at 14:29
  • You are right. There is nothing about uniqueness. – cauchy Apr 29 '15 at 14:34
-1

IMHO and in my understanding, You are validating the data from the given array, not from the database.

So I strongly believe you should do it in the controller.

the general rule of thumb is to only write database interactions inside model.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.