我正在尝试在我的模型中翻译原始SQL查询以使用ActiveRecord查询接口。我认为我正确地翻译了查询,但我无法将其转换为数组以进行渲染。
这是我的模特:
class Pgdb < ActiveRecord::Base
self.abstract_class = true
self.table_name = 'test'
if Rails.env.development?
establish_connection :pg_development
end
def self.getInfo(name)
get = Pgdb.where(city: "New York")
get_a = get.to_a
get_a
end
end
我能够呈现的原始SQL查询是:
get = connection.query("SELECT * FROM test WHERE city = "New York")
如上面的代码所示,我正在访问外部PostgreSQL数据库并试图使用#to_a
将ActiveRecord对象转换为数组,但这不起作用。当我尝试在我的视图中渲染它时:
<% @info.each do |row| %>
<tr>
<% row.each do |element| %>
<td><%= element %></td>
<% end %>
</tr>
<% end %>
我收到错误:undefined method 'each' for #<Pgdb:0x007fd37af79040>
。我尝试在代码中不同位置的对象上使用to_a
,但没有任何效果。
控制器
def index
end
def new
@thing = Thing.new
end
def create
@info = Pgdb.getInfo(@thing.something)
render :index
end
答案 0 :(得分:2)
您收到undefined method 'each'
实例的错误Pgdb
,因为您的代码正在尝试迭代此行中实例的数据属性:
<% row.each do |element| %>
ActiveRecord实例不是您可以迭代的属性集合。相反,它们是响应为其属性命名的消息的对象。换句话说,你可以这样做:
p = Pgdb.first
p.city # because the underlying table has a `city` attribute
但你不能这样做:
p.each { |attribute| puts attribute }
但是,ActiveRecord为这件事提供了attributes
访问器。 attributes
方法返回一个哈希值,您可以使用each
方法迭代该哈希值。因此,可以执行此操作:
p.attributes.each { |key, value| puts "#{key}: #{value}" }
在您的视图中,您可以使用以下内容替换内部循环:
<% row.attributes.each do |key, value| %>
<td><%= "#{key}: #{value}" %></td>
<% end %>
这应该为您的Pgdb
实例提供属性。
顺便说一句,没有必要将where
的结果投射到Array
中的Pgdb::getInfo
。 where
查询会返回ActiveRecord::Relation
个对象,该对象会响应each
以及Enumerable
和map
等其他select
个消息,类似于阵列。在您的代码中,您成功地遍历
<% @info.each do |row| %>
无论您是否在to_a
中使用getInfo
,这都会有效。 不将结果集转换为数组是有充分理由的。例如,ActiveRecord::Relation
对象具有其他功能,例如作用域,您可能经常需要使用它。
希望有所帮助。快乐的编码!
答案 1 :(得分:1)
将rails连接到外部数据库的正确方法是使用config/database.yml
文件:
# SQLite version 3.x
# gem install sqlite3
#
# Ensure the SQLite 3 gem is defined in your Gemfile
# gem 'sqlite3'
#
defaults: &defaults
adapter: postgresql
encoding: utf8
template: template0
# used for test & development
local:
host: localhost
username: j_random_user # change this!
password: p4ssword # change this!
development:
<<: *defaults
<<: *local
database: my_app_development
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *defaults
<<: *local
database: my_app_test
production:
<<: *defaults
host: "my_app_something.rds.amazonaws.com" # change this!
username: my_amazon_db_user # change this!
password: my_amazon_user # change this!
reconnect: true
port: 3306
您可能希望使用本地postgres数据库进行开发,并使用pgbackup镜像生产数据库。
但是你的主要问题是,在创建rails应用程序时,你几乎都做错了。这看起来像一个PHP示例,其中一些无能的灵魂正在重新发明第1000次数据库管理器。
模型反映域中的对象。假设我们有一个宠物店应用程序。
我们当然需要宠物模型:
$ rails g model Pet name:string
$ rake db:migrate
这会在数据库中创建一个pets
表和一个Pet
类。请注意,表名是复数,模型名称是单数。
# app/models/pet.rb
class Pet < ActiveRecord::Base
end
然后我们可以通过以下方式访问宠物:
Pet.all
Pet.find(1) # find pet where id is 1
# ... etc
我们可以通过以下方式制作宠物:
pet = Pet.create(name: "Spot")
大多数basic rails tutorials都涵盖了所有这些内容。
ActiveRecord::Base.establish_connection
con = ActiveRecord::Base.connection
res = con.execute('SELECT * FROM foo')
虽然如果你实际上没有使用每个表的模型并且稍微遵循MVC约定,那么使用ActiveRecord并没有多大意义。这是可能的,但它根本没有给你带来任何好处。
同样地做没有MVC的Rails是可行的,但重点是什么?
让我们假设你有一个遗留数据库,但是有些人虽然使用了匈牙利应用程序数据库专栏(耸肩),却很酷:
persons:
intPersonID: Integer, Autoincrement, Primary Key
并且您希望将其映射到Rails模型
class User < ActiveRecord::Base
self.table_name 'persons'
self.primary_key 'intPersonID'
end
或者在你的情况下:
class Test < ActiveRecord::Base
self.table_name 'test' # since it's not "tests"
end
Test.where(city: "New York")