使用link_to更新布尔字段的正确方法是什么。为TrueClass获取未定义的方法`model_name':Class

时间:2013-05-03 20:39:10

标签: ruby-on-rails ruby ruby-on-rails-3

我在我的rails应用程序的循环中有以下link_to

<%= link_to 'Up', Product.find(n.id).update_attribute(:opinion, true)%>

但是我无法更新它。因为它给了我错误

undefined method `model_name' for TrueClass:Class

所以,我想知道在这种情况下更新布尔字段的正确方法是什么?

2 个答案:

答案 0 :(得分:2)

点击链接后你没有更新意见,你在页面渲染时更新它。

假设您的页面只有以下代码:

<%= link_to 'Up', Product.find(n.id).update_attribute(:opinion, true)%>

当您点击该页面时实际发生的事情是<%= %>上包含的代码被执行并用于生成字符串,该字符串将成为您的HTML。因此,在简化表达式的同时,在执行的一个步骤中,您将获得以下代码:

<%= link_to 'Up', true %>

这将生成HTML

<a href="true">Up</a>

这不是你想要的。

解决方案

在产品控制器上创建一个接收产品ID的操作,更新产品并重定向回来。所以,像这样:

在你的route.rb

 resource :products do
   member do
     post 'update_opinion'
   end
 end

在您的products_controller.rb上:

 def update_opinion
   Product.find(params[:id]).update_attribute(:opinion, true)
   redirect_to :back
 end

在你看来:

<%= link_to 'up', update_opinion_project_path(n) %>

答案 1 :(得分:2)

您的代码与您似乎追求的内容有很大不同。

辅助方法link_to接受两个参数:链接文本和链接目标,可以是:

  • 一个字符串,例如:'http://stackoverflow.com';
  • 哈希,引用内部网址的所有单个组件,由routes;
  • 定义
  • 一个对象或一组对象。

作为第二个参数,您传递的是表达式:

Product.find(n.id).update_attribute(:opinion, true)

在代码第一次运行时(即渲染期间)进行评估。 表达式尝试立即更新属性,然后返回一个布尔值,表示操作是否成功:如果成功更新了属性,则为true,否则为false。

在您的情况下,它似乎成功:它返回true

现在,true更接近字符串或散列,因此它被视为对象,其类为TrueClass。因此它将其视为模型,但不是模型,它没有定义模型方法;因此错误。

您要做的是将代码放在controller中,并将相对于右侧控制器操作的URL作为link_to的第二个参数。