在 Rails 视图中显示虚拟字段

Posted

技术标签:

【中文标题】在 Rails 视图中显示虚拟字段【英文标题】:Show virtual field in rails view 【发布时间】:2014-12-30 23:12:35 【问题描述】:

我一直在使用此处的信息 (http://ngauthier.com/2013/08/postgis-and-rails-a-simple-approach.html),以便可以根据距离显示我的应用中的搜索结果。

我列出了所有任务及其相关的项目信息 - 一个项目可以有多个任务

我的 Project 控制器中有以下 AR 查询:

@results = Task.select('tasks.*') # .select('tasks.*') required for pg_search
               .joins(:project => :user)
               .includes(:project => :user)
               .merge(Project.enabled_only.filter_by_location(@geo).search(params[:q]))
               .order_results(sort)

在我的Project 模型中,我有:

scope :distance_from, ->(latitude, longitude) 
  select(%
    ST_Distance(
      ST_GeographyFromText(
        'SRID=4326;POINT(' || projects.longitude || ' ' || projects.latitude || ')'
      ),
      ST_GeographyFromText('SRID=4326;POINT(%f %f)')
    ) AS distance
   % [longitude, latitude])

scope :near, ->(latitude, longitude, distance_in_meters = 1000) 
  where(%
    ST_DWithin(
      ST_GeographyFromText(
        'SRID=4326;POINT(' || projects.longitude || ' ' || projects.latitude || ')'
      ),
      ST_GeographyFromText('SRID=4326;POINT(%f %f)'),
      %d
    )
   % [longitude, latitude, distance_in_meters])


def self.filter_by_location(geo_location)
  scoped = self.all
  if geo_location.present?
    scoped = scoped.distance_from(geo_location[:lat], geo_location[:lng])
    scoped = scoped.near(geo_location[:lat], geo_location[:lng])
  end
  scoped
end

然后我的Task 模型中有以下内容:

scope :distance_order, ->  order('distance') 

def self.order_results(sort)
  # order scopes are appended
  scoped = self.all.reorder('')
  # check sql for search and distance fields
  search_performed    = scoped.to_sql.downcase.include?(' pg_search_rank')
  distance_calculated = scoped.to_sql.downcase.include?(' distance')
  if sort == 'rel'
    # rel,dist
    scoped = scoped.search_rank_order if search_performed
    scoped = scoped.distance_order    if distance_calculated
  else
    # dist,rel
    scoped = scoped.distance_order    if distance_calculated
    scoped = scoped.search_rank_order if search_performed
  end
  scoped = scoped.name_order
  scoped
end

这适用于我的应用按邻近度对结果进行排序。

距离是 AR 查询生成的 sql 选择中的列之一,与 tasks.* 一起,距离被正确用于对结果进行排序,但我不确定如何在我的视图中显示距离。

如果我做<%= result.distance.to_s %>,它说距离是一个未定义的方法。我对<%= result.project.distance.to_s %> 也不满意。而 <%= result.task_field %><%= result.project.project_field %> 工作正常。

我在 RoR 世界中没有看到太多同时使用 .joins().includes(),但它确实让我减少了 db 调用的数量,同时仍然产生了正确的 sql select 语句。 .无论如何,在我的情况下 - 这就是它们都被使用的原因。

我错过了什么吗?

是因为我的 AR 查询的复杂性造成的吗?

我是否在我的 ProjectTask 模型中遗漏了一些东西以允许显示虚拟/计算距离场?

谢谢

【问题讨论】:

【参考方案1】:

复杂的结构被数据库视图所取代。

有关如何执行此操作的更多详细信息,请参阅本教程 (http://pivotallabs.com/database-views-performance-rails/) 和我的其他 SO 问题之一 (Connecting database view with polymorphic model in rails)。

【讨论】:

以上是关于在 Rails 视图中显示虚拟字段的主要内容,如果未能解决你的问题,请参考以下文章

在视图中创建 Ruby on Rails 矩阵表

Ruby on Rails 使用视图助手中的变量在视图中动态生成字段名称

Rails - 调用模型的方法时在视图中获取对象的字段

仅在 Rails 中搭建视图文件。可能的?

Rails 视图 - 用户输入分钟,我们节省秒?

如何在 Rails 中执行 AJAX-y 条件显示/隐藏表单字段?