Rails" logic"似乎暗指我

时间:2016-11-29 18:02:11

标签: ruby-on-rails-4 activerecord rails-activerecord

好吧,像往常一样,我把自己绑在另一个带有轨道和逻辑的结上,并且感到非常沮丧。

如果我可以在常规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

2 个答案:

答案 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)