存储过程从名为SETOF
的表中返回行数组ACCOUNTS
及其关联的续集模型Account
:
[1] pry(#<Psql::CalculateMasterBalancesTest>)> DB.select(Sequel.lit('*')).from{ |o| Sequel.function(:get_master_accounts, DB.row_type(:accounts, @accounts['A/1/1'].values)) }.all
=> [{:id=>1651, :parent_id=>1649, :ban=>nil, :risk=>nil, :custom_attributes=>nil, :created_at=>2017-05-17 19:33:09 +0200, :updated_at=>2017-05-17 19:33:09 +0200},
{:id=>1649, :parent_id=>1647, :ban=>nil, :risk=>nil, :custom_attributes=>nil, :created_at=>2017-05-17 19:33:09 +0200, :updated_at=>2017-05-17 19:33:09 +0200},
{:id=>1647, :parent_id=>nil, :ban=>"A Master", :risk=>nil, :custom_attributes=>nil, :created_at=>2017-05-17 19:33:09 +0200, :updated_at=>2017-05-17 19:33:09 +0200}]
为了使这个游戏与其他应用程序保持良好,我想将这个值哈希数组实例化为Account
模型实例的数组。
如果我只是将.map{|hash| Account.new(hash)}
添加到上一个表达式的末尾,我会得到一个
Sequel::MassAssignmentRestriction: id is a restricted primary key
错误。
如果我欺负这一点并手动设置ID列,那么我猜测由于persisted?
逻辑,某些东西很可能会让某些东西咬我(如果可能的话,会出现一些奇怪的边缘情况)在Sequel的某个地方(我只是猜测,这是ActiveRecord发生的事情,这似乎是一个常见的设计问题),
在续集中有没有一种惯用的处理方式?
答案 0 :(得分:1)
有时写一个问题会给你一个答案:
Account.from{ |o| Sequel.function(:get_ancestry, DB.row_type(:accounts, @accounts['A/1/1'].values)) }.all
作品。
实际上,这真的非常非常好,因为它的行为就像任何数据集一样,你可以加入它,“在哪里”,对它进行排序等等,一切都表现得非常好。
DB.register_row_type(:accounts)
def ancestry_dataset
Account.from do |o|
Sequel.function(:get_ancestry, DB.row_type(:accounts, values))
end
end
然后:
def test_me
acc = @accounts['A/1/1']
pd = acc.ancestry_dataset
assert pd.is_a?(Sequel::Postgres::Dataset), 'expected a postgres dataset'
assert_equal 2, pd.count, 'count returned funny'
assert_equal 2, pd.all.count, 'all.count returned funny'
assert_equal 1, pd.where(parent_id: nil).count, 'where(...).count returned funny'
assert_equal 1, pd.where(parent_id: nil).all.count, 'where(...).all.count returned funny'
assert_equal [:id], pd.select(:id).first.keys, 'when I restrict the select statement columns, the keys are funny'
end
没有hickups它可以很好地工作,并且是处理分层数据的一个很棒的powertool。
为了将来参考,get_ancestry
功能是:
CREATE OR REPLACE FUNCTION get_ancestry(_acct Accounts)
RETURNS SETOF Accounts AS $$
DECLARE
cur_acct Accounts%ROWTYPE;
BEGIN
-- we start from the parent of _acct
SELECT INTO cur_acct *
FROM Accounts
WHERE id = _acct.parent_id;
WHILE (cur_acct.id IS NOT NULL) LOOP
RAISE NOTICE 'get_ancestry: returning %', cur_acct.id;
RETURN NEXT cur_acct;
SELECT INTO cur_acct *
FROM Accounts
WHERE id = cur_acct.parent_id;
END LOOP;
END;
$$ LANGUAGE plpgsql;
答案 1 :(得分:0)
&#34; id是受限制的主键&#34;是因为你正在传递记录的:id
。
在尝试实例化新帐户之前,从值中删除:id
。
.select(Sequel.lit('*'))
不应该是必要的。续集会自动选择*
:
require 'json'
require 'sequel'
DB = Sequel.sqlite
DB.create_table :items do
primary_key :id
String :name
Float :price
end
items = DB[:items]
items.insert(:name => 'abc', :price => rand * 100)
class Item < Sequel::Model(:items)
end
Item.dataset.sql
# => "SELECT * FROM `items`"