0

我有三张桌子;Area,MovieMovieArea. 在 Rails 中,我希望能够MovieArea基于area_id. Movie然后,我想使用来自的字段返回一个复合 json 对象Movie,并将同名的字段替换为来自MovieArea.

我有以下数据库结构:

在此处输入图像描述

以及以下型号:

class Movie < ActiveRecord::Base
    attr_accessible :title, :synopsis, :grossing, :director, :year, :facts
    has_many :movie_areas, :class_name => 'MovieArea'
end

class Area < ActiveRecord::Base
    attr_accessible :name
    has_many :movie_areas, :class_name => 'MovieArea'
end

class MovieArea < ActiveRecord::Base
    attr_accessible :movie_id, :area_id, :synopsis, :facts

    belongs_to :area, :class_name => 'Area', :foreign_key => :area_id
    belongs_to :movie, :class_name => 'Movie', :foreign_key => :movie_id
end

最后,我一直在尝试通过使用模型方法和更改 JSON 响应来创建这个对象。向模型添加:

def grossing
    self.movie.grossing
end
def year
    self.movie.year
end
def title
    self.movie.title
end

等等。在控制器中:

@results = MovieArea.where(:area_id => @area.id)

最后,在视图中:

<%= @results.to_json(:methods => [:grossing, :year, :title] ).html_safe -%>

这很好,我得到了我想要的 JSON 对象的类型:

[
   {
      "id":1,
      "area_id":1,
      "movie_id":1,
      "synopsis":"Area relevant movie synopsis",
      "facts":"Area relevant movie facts",
      "grossing":"$9001M",
      "year":"1999",
      "title":"Movie title",
   },
   .....
]

所以问题是:有没有更好的方法来做到这一点?例如,我可以从模型中输出它并调用类似的东西MovieArea.where(:area_id => @area.id).some_function_to_respond吗?或者我可以将逻辑移动到控制器,以便在它简单调用的视图中@results.to_json()

谢谢!

4

2 回答 2

0

最近有一集 RailsCasts 涵盖了你想做的事情。看看这里

于 2013-03-12T13:02:32.923 回答
0

我最终使用了RABL - 感谢shweta的推荐。我通过将以下内容添加到我的 Gemfile 并运行bundle install安装它来安装它。

gem 'rabl'
gem 'oj'

movie_areas.json.rabl然后我在一个文件夹中创建了以下 RABL 模板views/rabl

object @movie
attributes :id, :synopsis, :facts
glue :movie do
  attributes :title, :grossing, :director, :year
end

上面的代码从表中获取id, synopsisand ,然后从父级中添加,和 and 。factsmovie_areatitlegrossingdirectoryearmovie

为了在视图中直接渲染 JSON,我需要在主干.js 中使用,我调用:

<%= Rabl.render(@results, 'rabl/movie_areas').html_safe -%>

@results我的问题中定义的变量 ActiveRecord 查询在哪里并rabl/movie_areas引用了movie_areas.json.rabl模板。

要直接从控制器输出 API,我使用:

def movies
    @area = Area.find_by_slug(params[:slug])
    @results = MovieArea.where(:area_id => @area.id)
    render :inline => Rabl::Renderer.json(@results, 'rabl/movie_areas')
end

希望这将有助于将来的人!

于 2013-03-13T09:22:24.973 回答