Suppose I have a class that represents a list of movies, belonging to a user:
class User < ActiveRecord::Base
has_one :movie_list
end
class MovieList < ActiveRecord::Base
belongs_to :user
has_many :movie_list_movie_relationships
has_many :movies, :through => :movie_list_movie_relationships
end
class Movie < ActiveRecord::Base
has_many :movie_list_movie_relationships
has_many :movie_lists, :through => :movie_list_movie_relationships
end
class MovieListMovieRelationship < ActiveRecord::Base
开发者_高级运维 belongs_to :movie
belongs_to :movie_list
end
Is there any way to have a method on MovieList that returns a MovieList containing only movies with, for example, a specific release year. I want something like:
class MovieList < ActiveRecord::Base
....
def for_year year
movies.where(:year => year)
end
end
EXCEPT that I want the result to be a MovieList itself, whereas this returns an array of Movies. So I could do, for example:
list = User.first.movie_list.for_year(1999)
list.id # would give the id of the MovieList = User.first.movie_list.id
list.movies.first.id # would give the id of the first movie in list
I have a feeling that I'm either a) faced with this problem because my design is bad, and it would be great if someone could explain how I should design this, or b) asking for something relatively mundane but I just don't know the right terminology.
Thanks!
Edit
I have specific reasons for wanting a MovieList and not an array of Movies. For one, I've written the question with User has_one :movie_list but in reality a User has_many :movie_lists (e.g., "Movies I have on DVD", "Movies I want to see", etc). That's why I don't just use a simple join between User and Movie. I want a MovieList because I want the id of the list to get passed around to make it easy to add a movie to a specific list; I have a MovieListMovieRelationshipController. I think what I'm going to end up having to do is fetch the movies as an array and just pass around the list id manually.
Edit 2
Here's what I ended up doing, as per @normalocity and the ensuing comments. Any further comments/suggestions are appreciated :)
class MovieList
...
def limit_to_year year
new_list = MovieList.new(self.attributes)
new_list.id = self.id
new_list.movies = []
limited_movies = movies.where(:year => year)
new_list.movies = limited_movies
return new_list
end
end
You can't do what you're hoping for directly, no, but it's simple enough to create an empty MovieList, and then add the array of movies from your for_year method to the new MovieList. You can even make the query for the array of associated Movie objects faster/simpler via a named_scope.
- Create a named scope to get all Movies from a specific year:
In Movie class:
named_scope :for_year, lambda { |year| {:conditions => ["year = ?", year]} }
Now, every time you call Movie.for_year("1945") you get back an array of Movie objects from that year.
Then...
- Create a new
MovieList(that belongs to NO user), and add the results from #1 to the list
This might work:
movies1945 = MovieList.create(:movies => Movie.for_year("1945")
If it doesn't work, you might have to split up the creation of the new MovieList object, and the assignment of values to the Movie collection.
If you need to distinguish between a simple list of Movies (what's the difference between that and an Array, I don't know, but if that distinction is necessary), and the Movies that a particular user has in their collection, then you could separate your classes into MovieList (just a list of movies) and a Collection (the movies that a given user has).
If you don't need that, then the 1945 movie list could either have a nil user, or (say your web site is called imdb.com) you could create a dummy user account called "imdb", and have the list belong to that user.
加载中,请稍侯......
精彩评论