【发布时间】:2020-01-06 05:53:09
【问题描述】:
我是 Rails 新手,正在完成 Michael Hartl 教程,并在书中的基本应用程序上创建了一些变体。我想做的一件事是创建一组深度为三个的模型关联(用户-> 收藏-> 图片->)。我还试图将我的图片表单放在视图中以显示收藏。我尝试按照书中使用的用户到集合关系的模式,但遇到了几个问题。首先,我无法使用 Form_with 标签 (form_with(model: @picture, local: true)) 并最终写出了路径 (form_with(url:"/pictures/create" , 方法:“发布”))。此外,我使用隐藏字段标记将 collection_id 传递给“create”方法。
我现在的问题似乎是它没有将@picture 数据保存在图片控制器中。这是我认为可疑的行:
@picture= @collection.pictures.build
这是一个总结/我对我正在尝试做的事情的理解。
在控制器显示页面上渲染图片表单
将表单日期发布到图片模型,同时还传递 控制器对象 ID 到控制器,以便保留图片与控制器的关系
使用发送的控制器 ID 调用控制器对象 参数
使用 .build 将图片参数保存到图片模型并闪烁成功消息
从日志中,我认为问题出在我对 .build 的使用上(在下面的代码中突出显示)。
我将为应用程序的所有元素以及日志提供以下代码。我真的可以使用一些帮助来弄清楚我做错了什么。如果还有什么我应该分享的,请告诉我。
模型
图片模型
class Picture < ApplicationRecord
belongs_to :collection
validates :collection_id, presence: true
validates :picture_title, presence: true, length: { maximum: 30}
end
集合模型
class Collection < ApplicationRecord
belongs_to :user
has_many :pictures, dependent: :destroy
default_scope -> { order(created_at: :desc) }
validates :user_id, presence: true
validates :collection_title, presence: true, length: { maximum: 30 }
end
用户模型
class User < ApplicationRecord
has_many :collections, dependent: :destroy
has_many :pictures, through: :collections
attr_accessor :remember_token
before_save { self.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: true
has_secure_password
validates :password, presence: true, length: { minimum: 6 }, allow_nil: true
# Returns the hash digest of the given string.
def User.digest(string)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
BCrypt::Engine.cost
BCrypt::Password.create(string, cost: cost)
end
# Returns a random token.
def User.new_token
SecureRandom.urlsafe_base64
end
# Remembers a user in the database for use in persistent sessions.
def remember
self.remember_token = User.new_token
update_attribute(:remember_digest, User.digest(remember_token))
end
# Returns true if the given token matches the digest.
def authenticated?(remember_token)
return false if remember_digest.nil?
BCrypt::Password.new(remember_digest).is_password?(remember_token)
end
def forget
update_attribute(:remember_digest, nil)
end
def feed
Collection.where("user_id = ?", id)
end
end
路线
Rails.application.routes.draw do
get 'sessions/new'
root 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/signup', to: 'users#new'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
post '/pictures/create', to: 'pictures#create'
resources :users
resources :collections
resources :pictures
resources :users do
resources :collection
end
resources :collections do
resources :pictures
end
end
图片控制器
def create
@collection = Collection.find(params[:collection_id])
@picture= @collection.pictures.build
if @picture.save!
flash[:notice] = "Picture was successfully added."
redirect_to request.referrer
else
flash[:alert] = "Picture could not be saved."
redirect_to request.referrer
end
end
private
def correct_user
@collection = current_user.collections.find_by(id: params[:id])
redirect_to root_url if @collection.nil?
end
def picture_params
params.require(:picture).permit(:picture_title)
end
end
集合控制器
class CollectionsController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy, :show, :index]
before_action :correct_user, only: [:destroy, :show]
def show
@collection = Collection.find(params[:id])
@picture= Picture.new
end
def create
@collection = current_user.collections.build(collection_params)
if @collection.save
flash[:success] = "Image collection created!"
redirect_to root_url
else
@feed_items = current_user.feed.paginate(page: params[:page])
render 'static_pages/home'
end
end
def destroy
@collection.destroy
flash[:success] = "Collection deleted"
redirect_to request.referrer || root_url
end
private
def collection_params
params.require(:collection).permit(:collection_title)
end
def correct_user
@collection = current_user.collections.find_by(id: params[:id])
redirect_to root_url if @collection.nil?
end
end
**图片形式**
<%= form_with(url:"/pictures/create", method: "post") do |f| %>
<div class="field">
<%= f.text_field :picture_title, placeholder: "Picture Title" %>
</div>
<%= f.submit "Create Collection", class: "btn btn-primary" %>
<%= hidden_field_tag :collection_id, @collection.id %>
<% end %>
日志
Started POST "/pictures/create" for 99.150.231.55 at 2020-01-04 19:29:08 +0000
Cannot render console from 99.150.231.55! Allowed networks: 127.0.0.0/127.255.255.255, ::1
Processing by PicturesController#create as JS
Parameters: {"authenticity_token"=>"GNDEKiGPVP7EHRtgphGDMIJxbKgnXn2MFSmgTJMIoEo2Owan5THjMIx9N8pKLkS7hmaqJMdwhjqvuOBR/3JaHg==", "picture_title"=>"TEST", "collection_id"=>"10", "commit"=>"Create Collection"}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
↳ app/helpers/sessions_helper.rb:18:in `current_user'
Collection Load (0.1ms) SELECT "collections".* FROM "collections" WHERE "collections"."id" = ? ORDER BY "collections"."created_at" DESC LIMIT ? [["id", 10], ["LIMIT", 1]]
↳ app/controllers/pictures_controller.rb:12:in `create'
Completed 500 Internal Server Error in 6ms (ActiveRecord: 0.2ms | Allocations: 2423)
NoMethodError (undefined method `picture_title=' for nil:NilClass):
app/controllers/pictures_controller.rb:14:in `create'
编辑 我实现了 Max 的代码更正,但现在出现以下错误:
Started POST "/collections/10/pictures" for 99.150.231.55 at 2020-01-05 17:57:57 +0000
Cannot render console from 99.150.231.55! Allowed networks: 127.0.0.0/127.255.255.255, ::1
(0.1ms) SELECT sqlite_version(*)
NoMethodError (undefined method `make_response!' for PicturesController:Class):
【问题讨论】:
标签: ruby-on-rails model nested