1

У меня есть 1:N взаимосвязь между user и post модель. Я хочу получить user_id в модели post. Я попробовал это, обратившись к current_user, но это метать не может найти переменную 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 

я могу получить доступ к before_action :authenticate_user! в Post контроллер, но не current_user в post model или controller. Что я делаю неправильно здесь, в Post.fill_data. self.user_id?

Остальная часть кода работает нормально, и я вижу новую запись :name and :is_delete в базе данных sqlite3 (когда я комментирую строку self.user_id в классе Post).

Edit-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 

ответ

0

Вы пытаетесь добавить current_user.id в post model, используя обратный вызов before_create. но лучше всего использовать это

В 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 
+0

'current_user.posts.build (posts_params)' – max

+0

Да, это тоже правильно. но см. разницу между сборкой и новым/созданием. – SSR

+0

Если вы нашли мой ответ полезным, вы можете его принять. – SSR

1

В Rails ваши модели не должны знать о приложениях текущего пользователя или любого другого государства. Им нужно только знать о себе и объектах, с которыми они непосредственно связаны.

Контроллер, с другой стороны, знает о текущем пользователе.

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

Затем мы используем рельсы перечислимого макрос для отображения состояния в список символов:

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

Это позволяет сделать Post.trashed, чтобы получить все сообщения в корзине или post.trashed?, чтобы проверить, не удалена ли определенная запись.

Извещение, что я использую trashed вместо удаления, потому что у ActiveRecord есть методы deleted?, с которыми мы не хотим связываться.

+0

У меня уже есть класс миграции на пост. Пожалуйста, ознакомьтесь с разделом «Редактировать». Мне нужно создать еще один «ActiveRecord :: Migration»? –

+0

Я пытался, но все же контроллер не смог распознать 'current_user' –

+0

Этот перенос удаляет столбец' is_deleted' и добавляет столбец 'is_deleted'. Вы можете отредактировать исходную миграцию, но для этого вам потребуется сначала откат. Вы имеете в виду, что ваш контроллер бросает NoMethodError? Или вы не избавились от 'before_create: fill_data' в своей модели Post? – max

Смежные вопросы