Когда мой объект вызывается через HAML, он пытается запустить Active Record вместо того, чтобы просто вызывать метод - PullRequest
0 голосов
/ 29 августа 2011

У меня следующий фрагмент 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>:

какие-либо подсказки?

Использование самой последней версии Sinatra на Ruby 1.8.7 с последними версиями ActiveRecord и HAML.

Фактическая sinatraМаршрут, который вызывает запрос на отправку электронной почты, выглядит следующим образом: Обратите внимание на цикл внизу, который проходит через каждого предоставленного пользователя (через JSON) и отправляет им электронное письмо.Этот процесс запускает сборку шаблона HAML с пользователем в качестве локальной переменной шаблона.

Хорошо работает для первого пользователя, но не для второго.

    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

Ответы [ 3 ]

1 голос
/ 30 августа 2011

Моя первая мысль - это рефакторинг:

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

в:

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

Но не уверен, что это является причиной ваших проблем.

Такжепопробуйте вывести user.attributes в вашем методе:

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

Если это не проливает свет, я думаю, что вам придется предоставить нам код для ваших моделей User, Organization и Email,тоже.

Вы также можете проверить свою базу данных, чтобы убедиться, что от старой миграции не осталось пустых столбцов, возможно?

1 голос
/ 29 августа 2011

тщательная проверка вашей ошибки показывает, что вы пытаетесь вызвать метод «primary_email» не для объекта ActiveRecord, а для объекта Relation

это может произойти, например, если вы получаете свою «пользовательскую» переменную следующим образом

user = User.where("some conditions")

потому что «где» возвращает не массив ActiveRecords, а объект Relation

чтобы получить объект AR, который вы можете попробовать

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

или

user = User.find("some conditions")
0 голосов
/ 30 августа 2011

Это будет звучать безумно, но попробуйте переписать свой код 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переменные

...