为了在某些站点上存储用户定义的书签,我有一个包含复合键的表:
CREATE TABLE bookmarks (
user_id int not null,
book_id int not null,
page_id int,
...
);
CREATE UNIQUE INDEX ON bookmarks(user_id, book_id, page_id);
请注意,page_id 可以为 NULL,而 user_id 和 book_id 不能。当 page_id 为 null 时,为整本书设置书签,否则 - 为特定页面。
对应的ActiveRecord类定义了一些关系:
public function relations() {
return array(
"user" => array(self::BELONGS_TO, "User", "user_id"),
"book" => array(self::BELONGS_TO, "Book", "book_id"),
"page" => array(self::BELONGS_TO, "Page", "page_id"),
);
}
和一个 primaryKey() 方法::
public function primaryKey() {
return array("user_id", "book_id", "orig_id");
}
现在我想为某个用户获取整本书的所有书签。所以,我这样做:
$bookmarks = Bookmark::model()->findAll(array(
"condition" => "t.user_id = :user_id AND t.page_id IS NULL",
"params" => array(":user_id" => 1),
));
效果很好,返回了 4 条记录,但显然,我想使用 books 表中的一些相关数据:
$bookmarks = Bookmark::model()->findAll(array(
"with" => "book",
"condition" => "t.user_id = :user_id AND t.page_id IS NULL",
"params" => array(":user_id" => 1),
));
现在我得到 0 条记录 (count($bookmarks) == 0),尽管生成的 SQL 语句选择了所有需要的数据,但 CActiveRecord 类无法识别它。另一件奇怪的事情是,当我尝试获取所有页面书签时,一切正常:
$bookmarks = Bookmark::model()->findAll(array(
"with" => "book",
"condition" => "t.user_id = :user_id AND t.page_id IS NOT NULL",
"params" => array(":user_id" => 1),
));
我做错了什么?如何让第二个例子中的表达式返回一些数据? PHP 5.4.0、Yii 1.1.8、PostgreSQL 9.1.4、+32°C 外部。
最佳答案
您的问题可能会这样解决:
将代理 PK 添加到书签 表(例如自动增量序列)。
删除 primaryKey() 函数。
您还可以使用更方便的代码:
public function relations()
{
return array(
//...
'wholeBook' => array(self::BELONGS_TO, 'Book', 'book_id', 'on'=>"page_id IS NULL", 'joinType'=>'INNER JOIN'),
//...
);
}
然后在 Controller 中:
$bookmarks = Bookmark::model()->with('wholeBook')->findAllByAttributes(array('user_id'=>1));
事实上,使用 UNIQUE 键而不是 PRIMARY 和 primaryKey() 您可以使用 hack 来避免在复合 PK 中使用 NULL 列的可能性。
ActiveRecord 是一种 ORM,因此 SQL 中的任何逻辑都必须翻译成 AR(Yii 自动加载 DB 模式),并且它必须是正确的逻辑。
如果我是你,我会将 SQL 规范化为如下形式:
因为它们是具有不同关系的两种不同类型的书签。您应该只在 View 逻辑中加入它们,而不是在关系结构中。恕我直言
关于php - 用于具有 NULL 值的复合键的表的关系 Yii ActiveRecord,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11827849/
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm
我正在使用Rails3.1并在一个论坛上工作。我有一个名为Topic的模型,每个模型都有许多Post。当用户创建新主题时,他们也应该创建第一个Post。但是,我不确定如何以相同的形式执行此操作。这是我的代码:classTopic:destroyaccepts_nested_attributes_for:postsvalidates_presence_of:titleendclassPost...但这似乎不起作用。有什么想法吗?谢谢! 最佳答案 @Pablo的回答似乎有你需要的一切。但更具体地说...首先改变你View中的这一行对此#
当我使用has_one时,它工作得很好,但在has_many上却不行。在这里您可以看到object_id不同,因为它运行了另一个SQL来再次获取它。ruby-1.9.2-p290:001>e=Employee.create(name:'rafael',active:false)ruby-1.9.2-p290:002>b=Badge.create(number:1,employee:e)ruby-1.9.2-p290:003>a=Address.create(street:"123MarketSt",city:"SanDiego",employee:e)ruby-1.9.2-p290
我的问题的一个例子是体育游戏。一场体育比赛有两支球队,一支主队和一支客队。我的事件记录模型如下:classTeam"Team"has_one:away_team,:class_name=>"Team"end我希望能够通过游戏访问一个团队,例如:Game.find(1).home_team但我收到一个单元化常量错误:Game::team。谁能告诉我我做错了什么?谢谢, 最佳答案 如果Gamehas_one:team那么Rails假设您的teams表有一个game_id列。不过,您想要的是games表有一个team_id列,在这种情况下
我在破坏脚本的字符串中出现了一些奇怪的字符。据我所知,通过putbadstring到控制台,它们是"\0\0\0\0"。我想对此进行测试,以便我可以忽略它们...但是如何呢?以为这就是blank?和empty?的用途?!?:>badstring="\0"=>"\u0000">badstring.blank?NoMethodError:undefinedmethod`blank?'for"\u0000":Stringfrom(irb):97from/Users/meltemi/.rvm/rubies/ruby-2.0.0-p195/bin/irb:16:in`'>badstring.em
📢博客主页:https://blog.csdn.net/weixin_43197380📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!📢本文由Loewen丶原创,首发于CSDN,转载注明出处🙉📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨文章预览:一.分辨率(Resolution)1、工业相机的分辨率是如何定义的?2、工业相机的分辨率是如何选择的?二.精度(Accuracy)1、像素精度(PixelAccuracy)2、定位精度和重复定位精度(RepeatPrecision)三.公差(Tolerance)四.课后作业(Post-ClassExercises)视觉行业的初学者,甚至是做了1~2年
我从用户Hirolau那里找到了这段代码:defsum_to_n?(a,n)a.combination(2).find{|x,y|x+y==n}enda=[1,2,3,4,5]sum_to_n?(a,9)#=>[4,5]sum_to_n?(a,11)#=>nil我如何知道何时可以将两个参数发送到预定义方法(如find)?我不清楚,因为有时它不起作用。这是重新定义的东西吗? 最佳答案 如果您查看Enumerable#find的文档,您会发现它只接受一个block参数。您可以将它发送两次的原因是因为Ruby可以方便地让您根据它的“并行赋
RSpec似乎按顺序匹配方法接收的消息。我不确定如何使以下代码工作:allow(a).toreceive(:f)expect(a).toreceive(:f).with(2)a.f(1)a.f(2)a.f(3)我问的原因是a.f的一些调用是由我的代码的上层控制的,所以我不能对这些方法调用添加期望。 最佳答案 RSpecspy是测试这种情况的一种方式。要监视一个方法,用allowstub,除了方法名称之外没有任何约束,调用该方法,然后expect确切的方法调用。例如:allow(a).toreceive(:f)a.f(2)a.f(1)