Devise + Polymorphic不与关联:id

时间:2014-07-10 23:41:54

标签: ruby-on-rails ruby ruby-on-rails-4 devise

我正在开发我的第一个应用程序,而Devise给了我一些问题。我在一个模型上设计了一个与其他3个模型Artist,Label,Fan有多态关联的用户。一切都是正确的,但是当我创建一个新的艺术家时,一切正常。当我与该艺术家重新签名时,例如,如果User_id为2且Artist_id为4,我将在Artists控制器中的Show Action上找到“找不到'id'= 2的艺术家”。我已经编辑了after_sign_in_path_for方法来检测帐户类型,以便在登录后重定向到用户类型的正确路径,从日志看起来艺术家的show动作试图匹配User_id而不匹配记录的Artist_id在用户中。

我的模特:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, 
         :recoverable, :rememberable, :trackable, :validatable
  belongs_to :account, polymorphic: true
  validates_uniqueness_of :user_name 
end


class Artist < ActiveRecord::Base
  has_one :user, as: :account, dependent: :destroy
  has_many :tracks, dependent: :destroy
  accepts_nested_attributes_for :user
  validates_uniqueness_of :artist_name 
  has_attached_file :avatar, 
                    :styles => { :medium => "300x300>", :thumb => "64x64>" }, 
                    :default_url => "https://s3-us-west-    2.amazonaws.com/trackfilter/default/default_250.png"
  validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
end

class Fan < ActiveRecord::Base
  has_one :user, as: :account, dependent: :destroy
  accepts_nested_attributes_for :user
  has_attached_file :avatar, 
                    :styles => { :medium => "300x300>", :thumb => "150x150>" }, 
                    :default_url => "https://s3-us-west-2.amazonaws.com/trackfilter/default/default_250.png"
  validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
end

class Label < ActiveRecord::Base
  has_one :user, as: :account, dependent: :destroy
  accepts_nested_attributes_for :user
  validates_uniqueness_of :label_name 
  has_attached_file :avatar, 
                    :styles => { :medium => "300x300>", :thumb => "150x150>" }, 
                    :default_url => "https://s3-us-west-2.amazonaws.com/trackfilter/default/default_250.png"
  validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
end

应用程序控制器:

class ApplicationController < ActionController::Base

 def after_sign_in_path_for(resource)
   if current_user.account_type == "Artist" 
     artist_path(resource)
   elsif current_user.account_type ==  "Label"
     label_path(resource)
   else current_user.account_type == "Fan"
     fan_path(resource)
   end
 end
end

艺术家控制器:

class ArtistsController < ApplicationController
 before_action :authenticate_user!, :except => [:index, :show]
 before_action :set_artist, only: [:show, :edit, :update, :destroy]

 def show
   @artist = Artist.find(params[:id])
   @tracks = @artist.tracks.all
 end

日志:

Started POST "/users/sign_in" for 127.0.0.1 at 2014-07-10 16:19:23 -0600
Processing by Devise::SessionsController#create as HTML
  Parameters: {"utf8"=>"✓",     "authenticity_token"=>"bdHPGqkUlW2OkJiP0qHaJOI1fnEMR3o+wZEwrWoQVxs=", "user"=>    {"email"=>"dino@dino.com", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Sign in"}
  User Load (0.2ms)  SELECT  "users".* FROM "users"  WHERE "users"."email" = 'dino@dino.com'  ORDER BY "users"."id" ASC LIMIT 1 (0.1ms)  begin transaction SQL (0.3ms)  UPDATE "users" SET "current_sign_in_at" = ?, "last_sign_in_at" = ?, "sign_in_count" = ?, "updated_at" = ? WHERE "users"."id" = 2  [["current_sign_in_at", "2014-07-10 22:19:23.660435"], ["last_sign_in_at", "2014-07-10 22:15:59.573569"], ["sign_in_count", 26], ["updated_at", "2014-07-10 22:19:23.661056"]](4.0ms)  commit transaction
Redirected to http://localhost:3000/artists/2
Completed 302 Found in 78ms (ActiveRecord: 4.6ms)

Started GET "/artists/2" for 127.0.0.1 at 2014-07-10 16:19:23 -0600
Processing by ArtistsController#show as HTML
  Parameters: {"id"=>"2"}
  Artist Load (0.1ms)  SELECT  "artists".* FROM "artists"  WHERE "artists"."id" = ? LIMIT 1  [["id", 2]]
Completed 404 Not Found in 1ms

ActiveRecord::RecordNotFound - Couldn't find Artist with 'id'=2:

对我来说很清楚,它是通过Devise用户ID而不是艺术家ID ...有关如何解决此问题的任何想法?

...谢谢

1 个答案:

答案 0 :(得分:0)

您的问题在重定向中,您需要提供帐户,因为它是您的artist / fan_controller查找对象所需的帐户ID。

class ApplicationController < ActionController::Base

 def after_sign_in_path_for(resource)
   if resource.account_type == "Artist" 
     artist_path(resource.account)
   elsif resource.account_type ==  "Label"
     label_path(resource.account)
   else resource.account_type == "Fan"
     fan_path(resource.account)
   end
 end
end

或更好(相同的逻辑,不同的写作):

class ApplicationController < ActionController::Base

 def after_sign_in_path_for(resource)
   account = resource.account
   case account
     when 'Artist' then artist_path(account)
     when 'Label' then label_path(account)
     when 'Fan' then fan_path(account)
     else
       #Handle error
   end
 end
end

甚至更时髦/灵活/危险:

class ApplicationController < ActionController::Base

 def after_sign_in_path_for(resource)
   self.public_send("#{resource.account_type.to_s.downcase.underscore}_path".to_sym, resource.account)
 end
end