NoMethodError - 未定义的方法`email&#39; for#<actiondispatch ::

时间:2015-08-25 22:22:19

标签: ruby-on-rails ruby devise

=“”

设计3.5.2,Rails 4.2.3

登录时,我尝试将隐藏的role_id与电子邮件/密码组合一起传递。我允许相同的电子邮件再次在另一个子域上注册,这会导致传递不同的role_id。电子邮件+ role_id是用户的唯一索引。

我可以创建一个用户,但无法登录。当我提交登录表单时,我遇到以下错误:

self.view = QTableView(self)

编辑:

如果有人可以解释将电子邮件唯一性验证更改为电子邮件+ role_id的过程(不是/或,而是和),那就是我需要完成的所有事情。正确地执行该过程可以避免此错误。

调试信息:

POST参数如下:

undefined method 'email' for #<ActionDispatch::Request:0x007fa21628bda0>

这是我的会员模特:

{"utf8"=>"✓",
 "authenticity_token"=>"[FILTERED]",
 "member"=>{"role_id"=>"1",
 "email"=>"some.user@email.com",
 "password"=>"[FILTERED]",
 "remember_me"=>"0"},
 "commit"=>"Log in"}

config / initializers / devise.rb 中,设置如下:

class Member < ActiveRecord::Base # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable, :lockable, :timeoutable, :omniauthable belongs_to :role def self.find_for_authentication(warden_conditions) where(:email => warden_conditions[:email], :role_id => warden_conditions[:role_id]).first end end

config.authentication_keys = [:email, :role_id]

我的观点/ devise / sessions / new.html.erb包括:

config.request_keys = [:email, :role_id]

我通过更改此行来调整 vendor / bundle / ruby​​ / 1.9.1 / gems / devise-3.5.2 / lib / devise / models / validatable.rb

<%= f.hidden_field :role_id, :value => Role.find_by_name(current_subdomain).id %>

为:

validates_uniqueness_of :email, allow_blank: true, if: :email_changed?

可在此处找到该成员的相关数据库迁移:

... devise_create_members.rb

validates_uniqueness_of :email, :scope => :role_id, allow_blank: true, if: :email_changed? #using subdomains for validation

... add_columns_to_member.rb

class DeviseCreateMembers < ActiveRecord::Migration
  def change
    create_table(:members) do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      t.integer  :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip

      ## Confirmable
      t.string   :confirmation_token
      t.datetime :confirmed_at
      t.datetime :confirmation_sent_at
      t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      t.string   :unlock_token # Only if unlock strategy is :email or :both
      t.datetime :locked_at


      t.timestamps null: false
    end

    add_index :members, :email,                unique: true
    add_index :members, :reset_password_token, unique: true
    add_index :members, :confirmation_token,   unique: true
    add_index :members, :unlock_token,         unique: true
  end

... reindex_members_email_and_role.rb

class AddColumnsToMember < ActiveRecord::Migration
  def change
    add_reference :members, :contact, index: true
    add_reference :members, :role, index: true
    add_reference :members, :ownership, index: true
    add_column :members, :account_status, :string
  end
end

跟踪的最后一项是:

vendor / bundle / ruby​​ / 1.9.1 / gems / devise-3.5.2 / lib / devise / strategies / authenticatable.rb:152:在`block in request_values&#39;

class ReindexMembersEmailAndRole < ActiveRecord::Migration
  def change
    add_index :members, [:email, :role_id], :unique => true
  end
end

我错过了什么?

1 个答案:

答案 0 :(得分:3)

要解决此问题,我更改了config.request_keys = { role_id: false }以反映以下内容:

:validatable

这解决了问题,但仍然阻止同一封电子邮件使用其他角色ID注册。为解决此问题,我从用户模型中删除了 validates_uniqueness_of :email, :case_sensitive => false, :scope => :role_id, :allow_blank => true, :if => :email_changed? validates_format_of :email, :with => Devise.email_regexp, :allow_blank => true, :if => :email_changed? validates_presence_of :password, :on=>:create validates_confirmation_of :password, :on=>:create validates_length_of :password, :within => Devise.password_length, :allow_blank => true 并添加了:

      def request_values
        keys = request_keys.respond_to?(:keys) ? request_keys.keys : request_keys
        values = keys.map { |k| self.request[self.scope][k] }
#        values = keys.map { |k| self.request.send(k) }
        Hash[keys.zip(values)]
      end

这允许使用不同的role_id注册相同的电子邮件地址。

我还在authenticatable.rb中更改了以下内容:

# config.request_keys = { role_id: false }

<强>更新

我厌倦了总是不得不重新破解设计库,特别是在我更新了宝石或转移应用程序之后。我发现这个页面提供了更好的解决方法(仍然遵循上面列出的用户模型的验证步骤):

(来自IFNULL

注释掉我们上面编辑的以下行:

config.authentication_keys

按如下方式编辑config.authentication_keys = { email: true, role_id: false }行:

request_keys

问题是:subdomain仅尊重预定义的密钥,例如{{1}}。

现在应该可以创建自定义密钥组合以进行身份​​验证。