好吧,像往常一样,我把自己绑在另一个带有轨道和逻辑的结上,并且感到非常沮丧。
如果我可以在常规SQL中将其删除,则需要:
module.exports = {
app_uri: 'http://localhost:3000',
redirect_uri: '/redirect',
id: 'user1',
secret: "client_secretValue",
...
};
我似乎无法在rails中模仿此查询的输出。我似乎能够希望的最好的是:
SELECT points.genus, types.type_name
FROM types, points
WHERE types.id = points.type_id and genus='Malus';
很好,我可以通过在我的`point.rb'中添加Point
.select(:genus, :type_id)
.where("genus = 'Malus'")
.joins(:type)
条目来依赖rails关联在我的视图中输出正确的值。一切都出来了。
但是,我需要将types.type_name传递给模型中的某些代码。如果我使用belongs_to :type
(除了获取值而不是我需要的字符串),一切都按预期工作。我已经尝试:type_id
和'types.type_name'
两者都生成了NIL。 :type_name
生成以下错误:
未定义的方法`type_name' for:types:Symbol
作为旁注,我没有创建代码,我试图将字符串传递给模型。它是从我传递的变量构建JSON,并不关心它是一个字符串或数字,也不关心我传递了多少变量。
- 根据@ Dan的要求更新以添加实际代码而非理论 -
:type.type_name
create_points.rb
class CreatePoints < ActiveRecord::Migration
def change
create_table :points do |t|
t.string :genus
t.string :species
t.string :cultivar
t.string :common_name
t.references :type, index: true, foreign_key: true
t.timestamps null: false, default: Time.now
t.multi_point :geom, srid: 4326
end
end
create_types.rb
class CreateTypes < ActiveRecord::Migration
def change
create_table :types do |t|
t.string :type_name
t.timestamps null: false
end
plants_controller.rb
class PlantsController < ApplicationController
def map
@points = Point
.select('points.genus, points.species, points.cultivar, points.common_name, types.type_name')
.where("types.type_name like 'Tree-%' or types.type_name like 'Shrub-%' or types.type_name like 'Perennial' or types.type_name like 'Fern' or types.type_name like 'Vine-%'")
.order(:id)
.eager_load(:type)
feature_collection = Point.to_feature_collection @points
@geojson = RGeo::GeoJSON.encode(feature_collection)
respond_to do |format|
format.json { render json: @geojson }
format.html
end
type.rb
class Type < ActiveRecord::Base
has_many :points
end
point.rb
class Point < ActiveRecord::Base
belongs_to :type
include Featurable
featurable :geom, [:genus, :species, :cultivar, :common_name, :type_id]
end
concerns/featurable.rb
在module Featurable
extend ActiveSupport::Concern
module ClassMethods
def featurable geom_attr_name, property_names = []
define_method :to_feature do
factory = RGeo::GeoJSON::EntityFactory.instance
property_names = Array(property_names)
properties = property_names.inject({}) do |hash, property_name|
hash[property_name.to_sym] = read_attribute(property_name)
hash
end
factory.feature read_attribute(geom_attr_name), self.id, properties
end
end
# turns a collection of models to a feature collection
# All models in the collection should implement the to_feature method
def to_feature_collection models
factory = RGeo::GeoJSON::EntityFactory.instance
features = models.map(&:to_feature)
factory.feature_collection features
end
end
end
行中,我想使用type.type_name的值而不是point.type_id。
- 更新2以重新发布featurable :geom, [:genus ...
-
point.rb
答案 0 :(得分:1)
我想说你不应该尝试从同一语句中的不同表中检索所有必需的列,尽管作为一个面向SQL的人我理解这种本能。
我认为关键是改为:
featurable :geom, [:genus, :species, :cultivar, :common_name, :type_name]
...然后让Point实例以适当的值响应#type_name。你可以用:
来做到这一点delegate :type_name, to: :type
您应该只需要加载或加入:输入@points的定义以提高效率。
编辑:由于使用了read_attribute,您可能必须在Point中定义自己的to_feature方法。
def to_feature
factory = RGeo::GeoJSON::EntityFactory.instance
property_names = [:genus, :species, :cultivar, :common_name, :type_name]
properties = property_names.inject({}) do |hash, property_name|
hash[property_name] = self.send(property_name)
hash
end
factory.feature geom, self.id, properties
end
答案 1 :(得分:-1)
您可以尝试:
Point
.select('points.genus, types.type_name')
.where("genus = ?", "Malus")
.joins(:type)