【问题标题】:How to access current_user variable in controller or model?如何访问控制器或模型中的 current_user 变量?
【发布时间】:2015-09-15 06:06:45
【问题描述】:

我在userpost 模型之间有1:N 关系。我想在post 模型中访问user_id。我通过访问current_user 进行了尝试,但它抛出了找不到current_user 变量。

我的 userModel 类:

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable, :validatable
  has_many :post
  validates_format_of :email, with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
end

MyPostModel 类:

class Post < ActiveRecord::Base
 belongs_to :user
 before_create :fill_data
 validates_presence_of :name, :message => 'Name field cannot be empty..'

 def fill_data
  self.is_delete = false
  self.user_id = current_user # here I am getting the error
 end
 end

MyPostController 类

class PostController < ApplicationController
 before_action :authenticate_user!
 def index
  @post = Post.all
 end

 def new
  @post = Post.new
 end

def create
 @post = Post.new(post_params)
 if @post.save
  redirect_to action: 'index'
 else
  render 'new'
 end
end
.....
private
 def post_params
  params.require(:post).permit(:name,:user_id,:is_delete)
 end
end

我可以访问 Post 控制器中的 before_action :authenticate_user!,但不能访问 post modelcontroller 中的 current_user。我在Post.fill_data. self.user_id 做错了什么?

其余代码工作正常,我可以在 sqlite3 数据库中看到 :name and :is_delete 的新条目(当我在 Post 类中评论 self.user_id 行时)。

编辑-1

我已经有 post 的迁移类

class CreatePosts < ActiveRecord::Migration
  def change
    create_table :posts do |t|
     t.string :name
     t.boolean :is_delete
     t.references :user, index: true, foreign_key: true
     t.timestamps null: false
    end
  end
end

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 model-view-controller devise controller


    【解决方案1】:

    您正在尝试使用 before_create 回调在 post 模型中添加 current_user.id。但更好的做法是使用这个

    在posts_controller.rb中

    def new
      @post = current_user.posts.new
    end
    
    def create
      @post = current_user.posts.create(posts_params)
    end
    

    这将为当前用户创建一个帖子。

    您的 fill_data 方法是

    def fill_data
      self.is_delete = false
    end
    

    【讨论】:

    • current_user.posts.build(posts_params)
    • 是的,这也是正确的。但是看看 build 和 new/create 之间的区别。
    • current_user.posts(posts_params) 不会创建新帖子!它只是创建一个 SELECT 查询并在 where 子句中使用 posts_params。 api.rubyonrails.org/classes/ActiveRecord/Associations/…
    【解决方案2】:

    在 Rails 中,您的模型不应该知道应用程序的当前用户或任何其他状态。他们只需要了解自己以及与他们直接相关的对象。

    另一方面,控制器知道当前用户。

    因此,正确的做法是从 Post 中删除 fill_data 回调。并在控制器中执行:

    class PostController < ApplicationController
      before_action :authenticate_user!
      def index
        @post = Post.all
      end
    
      def new
        @post = current_user.posts.build
      end
    
      def create
        @post = current_user.posts.build(post_params)
        if @post.save
          redirect_to action: 'index'
        else
          render 'new'
        end
      end
    
      private
      def post_params
        params.require(:post).permit(:name,:user_id,:is_delete)
      end
    end
    

    您还应该为数据库中的is_delete 列设置默认值,但如果您想像专业人士一样使用它,请改用enum

    创建迁移rails g migration AddStateToUsers 并填写:

    class AddStateToUsers < ActiveRecord::Migration
      def change
        add_column :users, :state, :integer, default: 0
        remove_column :users, :is_delete
        add_index :users, :state
      end
    end
    

    然后我们使用 rails 枚举宏将状态映射到符号列表:

    class Post
      enum state: [:draft, :published, :trashed]
      # ...
    end
    

    这让您可以通过Post.trashed 将所有帖子放入垃圾箱,或者通过post.trashed? 检查特定帖子是否已被删除。

    请注意,我使用 trashed 而不是删除,因为 ActiveRecord 已内置 deleted? 方法,我们不想乱用。

    【讨论】:

    • 我已经有迁移课程。请查看有问题的编辑部分。我需要创建另一个ActiveRecord::Migration 吗?
    • 我试过但控制器仍然无法识别current_user
    • 此迁移删除了 is_deleted 列并添加了 is_deleted 列。您可以编辑原始迁移,但需要您先回滚。您的意思是您的控制器正在抛出 NoMethodError 吗?或者你没有在你的 Post 模型中去掉before_create :fill_data
    • 正在抛出 current_user 未定义
    • 您是否正确安装了设计?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-27
    • 2014-05-16
    • 2011-01-17
    • 2017-09-22
    • 2011-12-13
    相关资源
    最近更新 更多