当我的对象通过HAML调用时,它试图触发活动记录,而不仅仅是调用一个方法



在构造要发送给用户的电子邮件时调用了以下HAML代码段。

%p
  Please <a href="#{base_url}/verify/#{user.primary_email.email}/#{user.registration_token}">click this link to confirm your email address</a>. You will then be logged in and can choose a password and continue the process of confirming your identity.

用户对象定义了方法primary_email

def primary_email()
  result = self.emails.first(:conditions => {:primary => true})
  puts "DEBUG: No Primary Email address found." unless result
  puts "DEBUG: Primary Email address found was #{result.email}" if result
  return result
end

但是我得到错误信息

NoMethodError - undefined method `primary_email' for #<ActiveRecord::Relation:0x10f0d3a58>:
 /Users/davesag/src/git/showpony3/rack/ruby/1.8/gems/activerecord-3.0.7/lib/active_record/relation.rb:374:in `method_missing'
 ./views/user_notifications/confirm_registration.haml:30:in `__tilt_2272398620'
 ./views/user_notifications/confirm_registration.haml:-7:in `instance_eval'
 ./views/user_notifications/confirm_registration.haml:-7:in `__tilt_2272398620'
 /Users/davesag/src/git/showpony3/rack/ruby/1.8/gems/tilt-1.3.2/lib/tilt/template.rb:140:in `call'
 /Users/davesag/src/git/showpony3/rack/ruby/1.8/gems/tilt-1.3.2/lib/tilt/template.rb:140:in `cached_evaluate'
 /Users/davesag/src/git/showpony3/rack/ruby/1.8/gems/tilt-1.3.2/lib/tilt/template.rb:127:in `evaluate'
 /Users/davesag/src/git/showpony3/rack/ruby/1.8/gems/tilt-1.3.2/lib/tilt/haml.rb:24:in `evaluate'
 /Users/davesag/src/git/showpony3/rack/ruby/1.8/gems/tilt-1.3.2/lib/tilt/template.rb:76:in `render'
 /Users/davesag/src/git/showpony3/rack/ruby/1.8/gems/sinatra-1.2.6/lib/sinatra/base.rb:563:in `render'
 /Users/davesag/src/git/showpony3/rack/ruby/1.8/gems/sinatra-1.2.6/lib/sinatra/base.rb:463:in `haml'
 ./showpony.rb:256:in `build_messge_for'
在我的简单单元测试中,我测试了primary_email方法
george = setup_dummy_user("George")
assert george.primary_email.email == GEORGE_TEST_EMAIL

这很好。

当我触发这个模板的发送时,它工作一次,然后在同一个请求中的第二次发送失败。(当我通过浏览器测试时,管理员用户和测试用户都会收到相同的通知电子邮件)

同样奇怪的是,在我的日志中,我看到了对primary_email方法的调用。(实际邮件已编辑)

org = {"number"=>"34567890", "name"=>"Test Limited", "country"=>"au", "website"=>"http://www.testing.com"}
people = [{"name"=>"Test 1", "username"=>nil, "roles"=>[{"name"=>"admin"}, {"name"=>"billing"}], "email"=>"##############"}, {"name"=>"Test 2", "username"=>nil, "roles"=>[], "email"=>"@@@@@@@@@@@@@@@@@"}]
DEBUG: Primary Email address found was ##############
Sending confirmation email to ##############
DEBUG: Primary Email address found was ##############
Sending confirmation email to @@@@@@@@@@@@@@@@@
DEBUG: Primary Email address found was @@@@@@@@@@@@@@@@@
NoMethodError - undefined method `primary_email' for#<ActiveRecord::Relation:0x10ea44e58>:

什么线索吗?

在Ruby 1.8.7上使用最新的Sinatra以及最新的ActiveRecord和HAML。

触发发送电子邮件请求的实际sinatra路由如下所示:注意底部的循环,该循环遍历提供的每个用户(通过JSON)并向他们发送电子邮件。该过程触发HAML模板的构建,其中User作为一个本地模板变量。

对第一个用户有效,但对第二个用户无效。

    post '/register' do
        content_type :json
      req = JSON.parse request.body.read
      if req['organisation'] == nil
        puts req.inspect
        return {:success => false, :error => "Request did not contain a proper Registration_Request object." }.to_json
      end
      org = req['organisation']
      people = req['people']
      message = "You (#{people[0]['name']} #{people[0]['email']}) have applied for membership on behalf of #{org['name']} (Company Number #{org['number']})."
      @@log.debug "org = #{org.inspect}"
      # do we have this org already?
      oo = Organisation.find_by_name(org['name'])
      if oo
        @@log.debug "Found exisiting Org #{oo.inspect}"
        return {:success => false, :error => "An organisation with that name is already a Member" }.to_json
      end
      these_people = []
      begin
        ActiveRecord::Base.transaction do
          o = Organisation.create(:name => org['name'],
                                  :number => org['number'],
                                  :website => org['website'],
                                  :country => org['country'])
          @@log.debug "people = #{people.inspect}"
          people.each {|person|
            p = User.create(:name => person['name'], :username => person['email'], :password => random_password)
            p.set_email({:email => person['email'], :primary => true})
            p.organisation = o
            person['roles'].each {|role|
              p.add_role(role['name'])
            }
            p.set_preference("HTML_EMAIL", "true")
            p.save!
            these_people << p
          }
        end
      end
      # send a secure notification to settings.notification_email
      send_system_email 'Membership Application received', :'system_notifications/registration', {:incoming_org => org, :incoming_people => people }
      # send an email_validation_request email to each user email.
      these_people.each {|p|
        @@log.debug "Sending confirmation email to #{p.primary_email.email}"
        send_user_email p, 'Please confirm your account details', :'user_notifications/confirm_registration', {:user => p }
      }
        return {:success => true, :message => message }.to_json
    end

仔细检查您的错误显示您试图调用"primary_email"方法不是在ActiveRecord对象上,而是在关系对象上

这种情况可能发生,例如,如果您以以下方式获取"user"变量

user = User.where("some conditions")

因为"where"返回的不是activerecord数组,而是关系对象

要获取实际的AR对象,可以尝试

user = User.where("some conditions").first

user = User.find("some conditions")

我的第一个想法是重构这个:

result = self.emails.first(:conditions => {:primary => true})

:

result = self.emails.where(:primary => true).first

但是,我不确定这就是你的问题的原因。

另外,尝试输出user。方法中的属性:

def primary_email()
  puts self.attributes.sort
  result = self.emails.first(:conditions => {:primary => true})

如果这还不清楚的话,我想你还得给我们你的用户、组织和电子邮件模型的代码。

您可能还会检查您的数据库,以验证是否没有从旧迁移中遗留下来的多余列。

这听起来很疯狂,但是尝试在.haml文件中重写您的haml代码,以便您可以利用多行缩进的优势:

%p
  - email = user.primary_email.email
    Please 
    %a{:href=>"#{base_url}/verify/#{email}/#{user.registration_token}"}
      click this link to confirm your email address...
    You will then be...

别忘了@instance你的变量

相关内容

最新更新