лучший способ вызвать метод в рельсах - PullRequest
0 голосов
/ 31 мая 2018

У меня есть некоторые проблемы, и я не знаю, каков наилучший способ их решения.

У меня есть метод, и я хотел бы помочь этому в двух видах: poi.views и track.index

Метод:

@distance_a_to_b = Track.find_by_sql(
  ["SELECT
    ST_Distance(line::geography, pta::geography) +
    ST_Distance(line::geography, ptb::geography) +
    ST_Length(ST_LineSubstring(
        line,
        least(ST_Line_Locate_Point(line, pta), ST_Line_Locate_Point(line, ptb)),
        greatest(ST_Line_Locate_Point(line, pta), ST_Line_Locate_Point(line, ptb)))::geography)  AS dst_line
    FROM (
      SELECT
        'SRID=4326;LINESTRING(1.457834243774414 43.597960902821576,1.462029218673706 43.59636807591895)'::geometry line,
        'SRID=4326;POINT(1.457994 43.598124)'::geometry pta,
        'SRID=4326;POINT(1.461628 43.596128)'::geometry ptb
    ) data"
  ])

Мне нужно вызывать этот метод в двух видах ....

poi.show = расстояние между A и poi (точка ())

и

track.index = расстояние для каждой точки (точка ())

Этот метод требует 3 аргумента:

a = начальная точка(запрос параметров) в виде Point ()

b = конечная точка в виде Point ()

и строки linestring или строки слияния

Как я могу опубликовать эти аргументы вэтот метод?

Как:

 @distance_a_to_b = Track.find_by_sql(
  ["SELECT
    ST_Distance(line::geography, pta::geography) +
    ST_Distance(line::geography, ptb::geography) +
    ST_Length(ST_LineSubstring(
    line,
    least(ST_Line_Locate_Point(line, pta), ST_Line_Locate_Point(line, ptb)),
    greatest(ST_Line_Locate_Point(line, pta), ST_Line_Locate_Point(line, ptb)))::geography)  AS dst_line
  FROM (
    SELECT
    '@track.path'::geometry line,
    '@poi.lonlat'::geometry pta,
    'query: params'::geometry ptb
) data"
])

Как я могу опубликовать переменные из каждого представления?Как я могу получить результат от этого метода, из каждого представления?по методу вызова?

Таблица Pois:

t.geography "lonlat", limit: {:srid=>4326, :type=>"st_point", :geographic=>true}

Таблица треков:

t.geometry "path", limit: {:srid=>4326, :type=>"line_string"}

Треки has_many Pois Poi принадлежит к треку

Редактировать

Следуя совету, вот что я сделал

В контроллере poi (просто для определения данных):

def index
  track = Track.friendly.find(params[:track_id])
  @pois = Poi.where(track_id: track)
  @track =  Track.find_by id: 1
  @poi = Poi.find_by id: 1

  respond_to do |format|
    format.html
end

В модели poi:

 def distance_along_track_to(poi2, track)
   distance_sql = <<-SQL
    SELECT
      ST_Distance(tr.path::geography, pta.lonlat::geography) +
      ST_Distance(tr.path::geography, ptb.lonlat::geography) +
      ST_Length(ST_LineSubstring(
        tr.path,
        least(ST_Line_Locate_Point(tr.path, pta.lonlat::geometry), ST_Line_Locate_Point(tr.path, ptb.lonlat::geometry)),
        greatest(ST_Line_Locate_Point(tr.path, pta.lonlat::geometry), ST_Line_Locate_Point(tr.path, ptb.lonlat::geometry)))::geography)  AS dst_line
      FROM tracks tr, pois pta, pois ptb
      WHERE tr.id = #{track.id}
      AND pta.id = #{self.id}
      AND ptb.id = #{poi2.id}
   SQL
   Poi.find_by_sql(distance_sql).dst_line
end

В индексном представлении:

<% @pois.each do |poi| %>
  <div>
    <%= poi.name %>
    <%= poi.track_id %>
    <%= @poi.distance_along_track_to(poi, @track) %> %>
 </div>
<% end %>

А теперь у меня появляется это сообщение об ошибке:

undefined method `dst_line' for [#<Poi id: nil>]:Array

Я не понимаю, почему @poi = nil?

1 Ответ

0 голосов
/ 01 июня 2018

Предположим, у вас есть @poi1, @poi2 и @track, вы можете написать свой метод следующим образом:

class Track  

  def distance_between_two_pois(poi1, poi2) 
    distance_sql = <<-SQL 
      SELECT
        ST_Distance(tr.path, pta.lonlat) +
        ST_Distance(tr.path, ptb.lonlat) +
        ST_Length(ST_LineSubstring(
          tr.path,
          least(ST_Line_Locate_Point(tr.path, pta.lonlat), ST_Line_Locate_Point(tr.path, ptb.lonlat)),
          greatest(ST_Line_Locate_Point(tr.path, pta.lonlat), ST_Line_Locate_Point(tr.path, ptb.lonlat)))::geography)  AS dst_line
       FROM tracks tr, pois pta, pois ptb
       WHERE tr.id = #{self.id}
         AND pta.id = #{poi1.id}
         AND ptb.id = #{poi2.id} 
    SQL 
    Track.find_by_sql(distance_sql).first.dst_line
  end 
end 

и затем вы можете вызвать его следующим образом

@track.distance_between_two_pois(@poi1, @poi2)

Не уверенкакой лучший API?Я также могу представить, что пишешь что-то вроде?

@poi1.distance_along_track_to(@poi2, @track) 
...