1

Я играю с Rails 5's find_or_initialize в моем приложении для блога, в котором есть записи и категории, введенные в текстовые поля ввода.Использование find_or_initialize on Rails 5

сообщение модель

# == Schema Information 
# 
# Table name: posts 
# 
# id   :integer   not null, primary key 
# title  :string   default(""), not null 
# body   :text    default(""), not null 
# created_at :datetime   not null 
# updated_at :datetime   not null 
# category_id :integer 


class Post < ApplicationRecord 
    validates :title, :body, :category, presence: true 

    has_one :category 
    accepts_nested_attributes_for :category 
end 

Категория модель

# == Schema Information 
# 
# Table name: category 
# 
# id   :integer   not null, primary key 
# name  :string   default(""), not null 
# created_at :datetime   not null 
# updated_at :datetime   not null 

class Category < ApplicationRecord 
    validates :name, presence: true 
    validates :name, length: { in: 3..80 } 

    has_many :posts 
end 

В консоли можно получить следующие работы:

post = Post.new(title: "Hello Stack Overflow", body: "How are you today?") 
post.category = Category.find_or_initialize_by(name: "Greetings") 
post.save 

post.last 
=> #<Post:0x007fd34fa21a23 
id: 42, 
title: "Hello Stack Overflow", 
body: "How are you today?", 
created_at: Mon, 25 Jul 2016 12:56:39 UTC +00:00, 
updated_at: Mon, 25 Jul 2016 12:56:39 UTC +00:00, 
category_id: 3> 

Столб форма выглядит следующим образом :

<%= form_for @post do |f| %> 
    <fieldset> 
    <%= f.label "Title" %> 
    <%= f.text_field :body %> 
    </fieldset> 

    <fieldset> 
    <%= f.fields_for :category do |category_fields| 
     <%= f.label "Category" %> 
     <%= category_fields.text_field :name %> 
    <% end %> 
    </fieldset> 
<% end %> 

Моя беда пытается получить то, что вводится в категории fields_for ввода в модель сообщение, чтобы использовать find_or_initialize.

Я попытался следующие:

class Post < ApplicationRecord 
    before_save :generate_category? 

    has_one :category 
    accepts_nested_attributes_for :category 

    private 

    def generate_category? 
    self.category = Category.find_or_initialize_by(name: name) 
    end 
end 

Это терпит неудачу, и я получаю сообщение об ошибке: NameError

NameError in PostController#create 
undefined local variable or method `name' for #<Listing:0x007fc3d9b48a48> 

Мой вопрос:

  1. Как получить доступ к категории атрибуты - есть ли способ получить доступ к nested_attributes в модели?
  2. Я использую правильный обратный вызов с before_save
  3. Должен ли я как-то обращаться с этим в контроллере?

Любые советы о том, как я могу кодировать это, будут высоко оценены.

ответ

0

name не метод на модели сообщения, но и по категории один. Поскольку категория еще не определена, вы не можете действительно полагаться на вызов: self.category.name. Вам нужно будет определить значение имени в другой форме. Теперь, если вы планируете использовать accepts_nested_attributes_for вы должны быть в состоянии отказаться от этого метода полностью, и просто хэш из данных содержит название категории:

{ title: 'Post Title', category: { name: 'blog' } }

Если вы не собираетесь этот маршрут, вы должен, вероятно, настроить традиционный публичный метод для создания категории путем передачи аргументов этому методу вместо использования активного обратного вызова. Кроме того, поскольку find_or_initialize() вернет объект, использование предикатного метода не имеет большого смысла. generate_category? должно стать generate_category

+0

Спасибо agmcleod. Позвольте мне найти реализацию для этого с API-интерфейсом атрибутов, но кто-то заставляет его работать с проверками. Согласился на метод предиката, спасибо за это. –