加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby-on-rails – 使用Rails find_or_create_by和表单对象

发布时间:2020-12-16 21:06:21 所属栏目:百科 来源:网络整理
导读:我正在创建一个Rails库应用程序,其中一个类型has_many书籍和一本书属于一种类型.我需要使用表单对象,因为我的数据模型最终会有多个多对多关系,因为我想学习如何使用表单对象.我已经将我的表单对象基于Rails Cast#416表单对象.我的表单,表单对象,模型和控制器
我正在创建一个Rails库应用程序,其中一个类型has_many书籍和一本书属于一种类型.我需要使用表单对象,因为我的数据模型最终会有多个多对多关系,因为我想学习如何使用表单对象.我已经将我的表单对象基于Rails Cast#416表单对象.我的表单,表单对象,模型和控制器似乎都可以工作.新书被创建并且它们与流派相关联,但它们都是流派“流派”.我正在使用find_or_create_by.我认为问题在于book_form.rb,其中@genre || = Genre.find_by(name :: name)实际上没有从表单中传入Genre信息.我的相关代码如下:

模型book.rb

class Book < ActiveRecord::Base
  belongs_to :genre
  before_save :convert_isbn
.
.
.
end

型号genre.rb

class Genre < ActiveRecord::Base
  has_many :books,dependent: :destroy
  validates_associated :books
end

book_form.rb

class BookForm
  include ActiveModel::Model

  def self.model_name
    ActiveModel::Name.new(self,nil,"Book")
  end
.
.
.
  validates :name,presence: true

  delegate :name,to: :genre
  delegate :title,:year,:pages,:isbn,:summary,:volume_a,:volume_b,to: :book

  def genre
    @genre ||= Genre.find_by(name: :name)
  end

  def book
    @book ||= genre.books.build
  end

  def submit(params)
    genre.attributes = params.slice(:name).permit(:name)
    book.attributes = params.slice(:title,:volume_b).permit(:title,:volume_b)
    if valid?
      genre.save!
      book.save!
      true
    else
      false
    end
  end
end

books_controller.rb

class BooksController < ApplicationController
  before_action :admin_user,only: [:new,:edit,:destroy]

  def new
    @book_form = BookForm.new
    @genres = Genre.all
  end

  def create
    @book_form = BookForm.new
    @genres = Genre.all
    if @book_form.submit(params[:book])
      flash[:success] = "You've added a new book to the library!"
      redirect_to @book_form
    else
      render 'new'
    end
  end

查看new.html.erb

<%= form_for @book_form do |f| %>
  <%=render 'shared/error_messages',object: f.object %>

  <%= f.label :title %>
  <%= f.text_field :title,class: 'form-control' %>
  .
  .
  .
  <%= f.label :genre %><br>

  <%= collection_select(:genre,:name,Genre.all,:name) %>
  <br>
  <br>
  <%= f.submit "Add book to library",class: "btn btn-primary" %>
<% end %>

使用Pry gem,我在创建一本书时从服务器获取:

Started POST "/books" for ::1 at 2016-02-22 14:19:20 -0700
Processing by BooksController#create as HTML
  Parameters: {"utf8"=>"?","authenticity_token"=>"bPusgyl9n+p07eQsEAe9CpSsithtkg33HMifj8KTsidv3GDLuhjibOC7d2mm5boC4w7ZUne64R4n4OMQotDE4g==","book"=>{"title"=>"test","year"=>"2016","pages"=>"222","isbn"=>"9780-xx-xx-xx","summary"=>"fake summary","volume_a"=>"1","volume_b"=>"2"},"genre"=>{"name"=>"Mystery"},"commit"=>"Add book to library"}

From: /home/nathaniel/rails_apps/allredlib/app/forms/book_form.rb @ line 38 BookForm#submit:

    37: def submit(params)
 => 38:   binding.pry
    39:   genre.attributes = params.slice(:name).permit(:name)
    40:   book.attributes = params.slice(:title,:volume_b)
    41:   if valid?
    42:     genre.save!
    43:     book.save!
    44:     true
    45:   else
    46:     false
    47:   end
    48: end

因此,书籍类型在参数中得到了传递,但我在书本表格中以错误的方式访问它.如果我注释掉binding.pry,那么这个表格会创建一个带有流派“名称”的新书,而不是像我希望它那样的流派“神秘”.

当我使用binding.pry键入@genre到rails时,我得到了

[1] pry(#<BookForm>)> @genre
=> #<Genre:0x007f19554e1220
 id: 20,name: "name",book_id: nil,created_at: Thu,25 Feb 2016 20:28:45 UTC +00:00,updated_at: Thu,25 Feb 2016 20:28:45 UTC +00:00>

最新的binding.pry结果
27:def类型
=> 28:binding.pry
29:@genre || = Genre.find_or_initialize_by(name :: name)
30:#@ genre || = Genre.find_or_initialize_by(name:params [:genre] [:name])
31:结束

解决方法

如果您要按名称查找类型,则需要在方法的选项哈希中传入name属性.
def genre
  @genre ||= Genre.find_or_create_by(name: :name)
end

UPDATE

更改

genre.attributes = params.slice(:name).permit(:name)

genre.attributes = { :name => params[:genre][:name] }

同时在genre.save之前和之后抛出binding.pry!如果你输入@genre,看看你得到了什么,因为你的流派方法应该已经创建了你刚刚用genre.attributes发送params的实例变量接受哈希.

我会考虑书籍参数相同,但如果切片工作得很好.

此外,由于您在窗体视图中调用Genre.all,您可能不需要在控制器操作中执行此操作,但如果这样做,请考虑在窗体视图collection_select中使用对象@genres,因为您’在模型上重复两次所有请求.

@genres = Genre.all

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读