-->

Correct Model Data Structure? (My 1st Rails App)

2020-07-30 06:22发布

问题:

I'm about to build my first Ruby on Rails application (and first anything beyond xhtml and css), and I'm looking for some helpful feedback on my model structure.

I've included a mockup to help visual the application.

The only models I'm sure I need so far are:
1. a movie model (to serve as the main model, named movie so URL's will look like, "sitename.com/movies/1-Willy-Wonka") and
2. a user model

Other than those, I don't know what to make the others; like 'filming locations', 'actors', and most importantly, the attributes like 'willy wonka' and 'johnny depp'.

Should I make all of those models, even the attributes? If so, is it possible, and recommended, to let people create models as attributes?

I try to see the app as data created by forms and stored in databases, and with that pov I can't decide how to connect attributes (character <=> actor) to sections (actors, filming locations, artwork, etc.) inside a movie listing; while allowing the attributes themselves to be hyperlinks to related attributes/movies/even sections: clicking on 'steven speilberg' would bring you to a page with movies he's acted in, films he's directed, produced, written, etc.

Thoughts?

回答1:

I would recommend getting your data model clear first. You can then start with one rails model per database table. This is not always the case, but it's a reasonable place to start.

Let's focus on the movies and actors:

Some assumptions:

  • movies can have a many-to-many relationship to the other entities
  • you want to store the character information as part of the relationship between an actor and a movie

You might then model your relationships like this:

# movies.rb
class Movie < ActiveRecord::Base
  has_many :roles
  has_many :actors, :through => :roles
end

# actor.rb
class Actor < ActiveRecord::Base
  has_many :roles
  has_many :movies, :through => :roles
end

Normally, you can rely on Rails' magic to handle the join model without creating one yourself. In this case we want to store the character information as attributes of the join model, so we create it explicitly.

# role.rb
class Role < ActiveRecord::Base
  belongs_to :movie
  belongs_to :actor
end


回答2:

Start with models Movie, Actor, FilmLocation, and Character. Movie and Actor have a many-to-many relationship(A Movie has many actors, an actor worked on many movies). FileLocation and Movie also are many-to-many. Character(Willy Wonka) and Actor are many-to-many as well.



回答3:

If this is your first anything as far as web development then I suggest you start with writing a simple web app that just lists movies and allows your to add, edit and delete them. Just store the title, a synopsis and maybe the URL of the movie poster/dvd cover. Then work on adding Actors and associating them with the Movie.

Creating an "IMDB-like" site is not a trivial project. You're going to have a lot complex relationships beyond just associating an actor with a movie. Actors have Roles in Movies. And you might want to get even more abstract than that and say that a Person has Job in a Movie which would allow you to also track things like the Directors, Producers, Key Grips, Casting Directors.

Not only should you work on your data model, but work on a plan about what you want the site to consist of and what order you should create those features in (based on need) and take small steps to get to that final goal.



回答4:

Further elaboration. The migrations for the models listed above might look like this:

class CreateMovies < ActiveRecord::Migration
  def self.up
    create_table 'movies' do |t|
      t.string  'title', :null => false
      t.timestamps
    end
  end

  def self.down
    drop_table 'movies' 
  end
end

class CreateActors < ActiveRecord::Migration
  def self.up
    create_table 'actors' do |t|
      t.string  'first_name', 'last_name', :null => false
      t.timestamps
    end
  end

  def self.down
    drop_table 'actors' 
  end
end

The movie_id and actor_id fields below correspond to the belongs_to associations in the Role model above and are the foreign keys that allow the roles table to join actors and movies. As I have proposed modeling it, the character_name is a property of this relationship, and is thus an attribute of the role. It's your call whether you allow NULL in the character_name. I'm leery of NULL, but in this case I've allowed it as one could make the argument that in practice you often wish to store the fact that an actor is in a given movie but don't know or care about the character name.

class CreateRoles < ActiveRecord::Migration
  def self.up
    create_table 'roles' do |t|
      t.integer 'movie_id', 'actor_id', :null => false
      t.string 'character_name'
      t.timestamps
    end
  end

  def self.down
    drop_table 'roles' 
  end
end


回答5:

It might be worthwhile to read up on database normalization: http://en.wikipedia.org/wiki/Database_normalization



回答6:

In general, yes. I like my models to be as granular as possible. This makes things much clearer for someone who isn't familiar with the application and makes it easier to reuse code.

It's helpful to have a firm grasp of ActiveRecord associations before writing a complex application. Make sure you know all of the associations by heart and what they actually generate in terms of SQL tables. Sometimes it can seem like magic, and magic isn't necessarily a good thing. If you know what's behind it things fall in to place.

Also, don't be afraid to scrap everything and start over while experimenting. It's Ruby, so it won't take long to get back to where you were.