rails覆盖关系的默认getter(belongs_to)

时间:2010-03-23 14:44:01

标签: ruby-on-rails activerecord associations default-value

所以我知道如何使用

覆盖ActiveRecord对象属性的默认getter
def custom_getter
  return self[:custom_getter] || some_default_value
end

我正在尝试为属于关联而实现同样的事情。例如。

class Foo < AR
  belongs_to :bar

  def bar
    return self[:bar] || Bar.last
  end
end

class Bar < AR
  has_one :foo
end

当我说:

f = Foo.last

我希望方法f.bar返回最后一个Bar,而不是nil,如果该关联尚不存在。

然而,这不起作用。原因是self [:bar]总是未定义的。它实际上是自我[:bar_id]。

我可以做一些天真的事情:

def bar
  if self[:bar_id]
    return Bar.find(self[:bar_id])
  else
    return Bar.last
  end
end

然而,即使已经获取了Bar,这也总是会进行db调用,这当然不是理想的。

是否有人了解我如何建立关系,以使belongs_to属性仅加载一次,如果未设置则具有默认值。

3 个答案:

答案 0 :(得分:71)

alias_method是你的朋友。

alias_method :original_bar, :bar
def bar
  self.original_bar || Bar.last
end

这样做的方法是将默认的“bar”方法别名为“原始栏”,然后实现自己的“bar”版本。如果对original_bar的调用返回nil,则返回最后一个Bar实例。

答案 1 :(得分:19)

我发现使用&#34; super&#34;是最好的方式

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for gender
-- ----------------------------
DROP TABLE IF EXISTS `gender`;
CREATE TABLE `gender` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

-- ----------------------------
-- Records of gender
-- ----------------------------
INSERT INTO `gender` VALUES ('1', 'Action');
INSERT INTO `gender` VALUES ('2', 'Musical');
INSERT INTO `gender` VALUES ('3', 'Sci Fi');

-- ----------------------------
-- Table structure for movies
-- ----------------------------
DROP TABLE IF EXISTS `movies`;
CREATE TABLE `movies` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `year` varchar(255) DEFAULT NULL,
  `gender_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;

-- ----------------------------
-- Records of movies
-- ----------------------------
INSERT INTO `movies` VALUES ('1', 'Alien', '1979', '1');
INSERT INTO `movies` VALUES ('2', 'Aliens', '1986', '1');
INSERT INTO `movies` VALUES ('3', 'Moulin Rouge', '2001', '3');
INSERT INTO `movies` VALUES ('4', 'Guys and Dolls', '1955', '3');
INSERT INTO `movies` VALUES ('5', 'Mama Mia', '1970', '3');
INSERT INTO `movies` VALUES ('6', 'Starman', '1984', '1');
INSERT INTO `movies` VALUES ('7', 'Tron', '1982', '1');
INSERT INTO `movies` VALUES ('8', 'The Matrix', '1988', '2');

-- ----------------------------
-- Table structure for movies_has_rating
-- ----------------------------
DROP TABLE IF EXISTS `movies_has_rating`;
CREATE TABLE `movies_has_rating` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `movie_id` int(11) NOT NULL,
  `vote_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=156 DEFAULT CHARSET=latin1;

-- ----------------------------
-- Records of movies_has_rating
-- ----------------------------
INSERT INTO `movies_has_rating` VALUES ('1', '1', '1');
INSERT INTO `movies_has_rating` VALUES ('2', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('3', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('4', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('5', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('6', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('7', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('8', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('9', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('10', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('11', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('12', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('13', '1', '1');
INSERT INTO `movies_has_rating` VALUES ('14', '1', '1');
INSERT INTO `movies_has_rating` VALUES ('15', '1', '1');
INSERT INTO `movies_has_rating` VALUES ('16', '1', '1');
INSERT INTO `movies_has_rating` VALUES ('17', '1', '1');
INSERT INTO `movies_has_rating` VALUES ('18', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('19', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('20', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('21', '1', '3');
INSERT INTO `movies_has_rating` VALUES ('22', '1', '3');
INSERT INTO `movies_has_rating` VALUES ('23', '1', '3');
INSERT INTO `movies_has_rating` VALUES ('24', '1', '3');
INSERT INTO `movies_has_rating` VALUES ('25', '1', '3');
INSERT INTO `movies_has_rating` VALUES ('26', '1', '3');
INSERT INTO `movies_has_rating` VALUES ('27', '1', '1');
INSERT INTO `movies_has_rating` VALUES ('28', '1', '3');
INSERT INTO `movies_has_rating` VALUES ('29', '1', '3');
INSERT INTO `movies_has_rating` VALUES ('30', '1', '3');
INSERT INTO `movies_has_rating` VALUES ('31', '1', '3');
INSERT INTO `movies_has_rating` VALUES ('32', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('33', '1', '1');
INSERT INTO `movies_has_rating` VALUES ('34', '1', '1');
INSERT INTO `movies_has_rating` VALUES ('35', '1', '1');
INSERT INTO `movies_has_rating` VALUES ('36', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('37', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('38', '1', '1');
INSERT INTO `movies_has_rating` VALUES ('39', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('40', '1', '3');
INSERT INTO `movies_has_rating` VALUES ('41', '1', '2');
INSERT INTO `movies_has_rating` VALUES ('42', '1', '3');
INSERT INTO `movies_has_rating` VALUES ('43', '1', '1');
INSERT INTO `movies_has_rating` VALUES ('44', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('45', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('46', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('47', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('48', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('49', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('50', '2', '1');
INSERT INTO `movies_has_rating` VALUES ('51', '2', '1');
INSERT INTO `movies_has_rating` VALUES ('52', '2', '1');
INSERT INTO `movies_has_rating` VALUES ('53', '2', '1');
INSERT INTO `movies_has_rating` VALUES ('54', '2', '1');
INSERT INTO `movies_has_rating` VALUES ('55', '2', '1');
INSERT INTO `movies_has_rating` VALUES ('56', '2', '1');
INSERT INTO `movies_has_rating` VALUES ('57', '2', '1');
INSERT INTO `movies_has_rating` VALUES ('58', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('59', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('60', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('61', '2', '3');
INSERT INTO `movies_has_rating` VALUES ('62', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('63', '2', '3');
INSERT INTO `movies_has_rating` VALUES ('64', '2', '3');
INSERT INTO `movies_has_rating` VALUES ('65', '2', '3');
INSERT INTO `movies_has_rating` VALUES ('66', '2', '3');
INSERT INTO `movies_has_rating` VALUES ('67', '2', '3');
INSERT INTO `movies_has_rating` VALUES ('68', '2', '3');
INSERT INTO `movies_has_rating` VALUES ('69', '2', '3');
INSERT INTO `movies_has_rating` VALUES ('70', '2', '3');
INSERT INTO `movies_has_rating` VALUES ('71', '2', '3');
INSERT INTO `movies_has_rating` VALUES ('72', '2', '3');
INSERT INTO `movies_has_rating` VALUES ('73', '2', '3');
INSERT INTO `movies_has_rating` VALUES ('74', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('75', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('76', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('77', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('78', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('79', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('80', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('81', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('82', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('83', '2', '2');
INSERT INTO `movies_has_rating` VALUES ('84', '2', '1');
INSERT INTO `movies_has_rating` VALUES ('85', '3', '1');
INSERT INTO `movies_has_rating` VALUES ('86', '3', '1');
INSERT INTO `movies_has_rating` VALUES ('87', '3', '1');
INSERT INTO `movies_has_rating` VALUES ('88', '3', '1');
INSERT INTO `movies_has_rating` VALUES ('89', '3', '2');
INSERT INTO `movies_has_rating` VALUES ('90', '3', '3');
INSERT INTO `movies_has_rating` VALUES ('91', '4', '2');
INSERT INTO `movies_has_rating` VALUES ('92', '4', '1');
INSERT INTO `movies_has_rating` VALUES ('93', '4', '2');
INSERT INTO `movies_has_rating` VALUES ('94', '4', '2');
INSERT INTO `movies_has_rating` VALUES ('95', '4', '2');
INSERT INTO `movies_has_rating` VALUES ('96', '4', '3');
INSERT INTO `movies_has_rating` VALUES ('97', '4', '3');
INSERT INTO `movies_has_rating` VALUES ('98', '4', '1');
INSERT INTO `movies_has_rating` VALUES ('99', '4', '1');
INSERT INTO `movies_has_rating` VALUES ('100', '4', '1');
INSERT INTO `movies_has_rating` VALUES ('101', '4', '1');
INSERT INTO `movies_has_rating` VALUES ('102', '4', '2');
INSERT INTO `movies_has_rating` VALUES ('103', '4', '3');
INSERT INTO `movies_has_rating` VALUES ('104', '4', '2');
INSERT INTO `movies_has_rating` VALUES ('105', '4', '3');
INSERT INTO `movies_has_rating` VALUES ('106', '4', '3');
INSERT INTO `movies_has_rating` VALUES ('107', '4', '3');
INSERT INTO `movies_has_rating` VALUES ('108', '4', '2');
INSERT INTO `movies_has_rating` VALUES ('109', '4', '2');
INSERT INTO `movies_has_rating` VALUES ('110', '4', '2');
INSERT INTO `movies_has_rating` VALUES ('111', '5', '2');
INSERT INTO `movies_has_rating` VALUES ('112', '5', '2');
INSERT INTO `movies_has_rating` VALUES ('113', '5', '2');
INSERT INTO `movies_has_rating` VALUES ('114', '5', '2');
INSERT INTO `movies_has_rating` VALUES ('115', '5', '2');
INSERT INTO `movies_has_rating` VALUES ('116', '5', '2');
INSERT INTO `movies_has_rating` VALUES ('117', '5', '2');
INSERT INTO `movies_has_rating` VALUES ('118', '5', '2');
INSERT INTO `movies_has_rating` VALUES ('119', '5', '2');
INSERT INTO `movies_has_rating` VALUES ('120', '5', '3');
INSERT INTO `movies_has_rating` VALUES ('121', '5', '3');
INSERT INTO `movies_has_rating` VALUES ('122', '5', '3');
INSERT INTO `movies_has_rating` VALUES ('123', '5', '3');
INSERT INTO `movies_has_rating` VALUES ('124', '6', '3');
INSERT INTO `movies_has_rating` VALUES ('125', '6', '3');
INSERT INTO `movies_has_rating` VALUES ('130', '8', '3');
INSERT INTO `movies_has_rating` VALUES ('131', '8', '1');
INSERT INTO `movies_has_rating` VALUES ('132', '8', '1');
INSERT INTO `movies_has_rating` VALUES ('133', '8', '1');
INSERT INTO `movies_has_rating` VALUES ('134', '8', '1');
INSERT INTO `movies_has_rating` VALUES ('135', '8', '1');
INSERT INTO `movies_has_rating` VALUES ('136', '8', '1');
INSERT INTO `movies_has_rating` VALUES ('137', '8', '1');
INSERT INTO `movies_has_rating` VALUES ('138', '8', '2');
INSERT INTO `movies_has_rating` VALUES ('139', '8', '3');
INSERT INTO `movies_has_rating` VALUES ('140', '8', '2');
INSERT INTO `movies_has_rating` VALUES ('141', '8', '2');
INSERT INTO `movies_has_rating` VALUES ('142', '8', '2');
INSERT INTO `movies_has_rating` VALUES ('143', '8', '2');
INSERT INTO `movies_has_rating` VALUES ('144', '8', '3');
INSERT INTO `movies_has_rating` VALUES ('145', '8', '3');
INSERT INTO `movies_has_rating` VALUES ('146', '8', '3');
INSERT INTO `movies_has_rating` VALUES ('147', '8', '3');
INSERT INTO `movies_has_rating` VALUES ('148', '8', '3');
INSERT INTO `movies_has_rating` VALUES ('149', '8', '3');
INSERT INTO `movies_has_rating` VALUES ('150', '8', '3');
INSERT INTO `movies_has_rating` VALUES ('151', '8', '3');
INSERT INTO `movies_has_rating` VALUES ('152', '8', '3');
INSERT INTO `movies_has_rating` VALUES ('153', '8', '3');

-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1;

-- ----------------------------
-- Records of users
-- ----------------------------
INSERT INTO `users` VALUES ('1', 'Name user 1', '1@1.com');
INSERT INTO `users` VALUES ('2', 'Name user 2', '2@2.com');
INSERT INTO `users` VALUES ('3', 'Name user 3', '3@3.com');

-- ----------------------------
-- Table structure for votes
-- ----------------------------
DROP TABLE IF EXISTS `votes`;
CREATE TABLE `votes` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;

-- ----------------------------
-- Records of votes
-- ----------------------------
INSERT INTO `votes` VALUES ('1', 'Very good');
INSERT INTO `votes` VALUES ('2', 'Good');
INSERT INTO `votes` VALUES ('3', 'Regular');

我希望这会对你有所帮助:D

答案 2 :(得分:10)

Randy的答案很明显,但使用alias_method_chain可以更轻松地编写它:


def bar_with_default_find
  self.bar_without_default_find || Bar.last
end
alias_method_chain :bar, :default_find

这会为bar_with_default_find方法创建两种方法 - bar_without_default_findbar以及别名with。这样你就可以明确地调用其中一个,或者只保留默认值。