gpt4 book ai didi

ruby-on-rails - Rails + Devise 嵌套注册表未定义方法 'build_address'

转载 作者:太空宇宙 更新时间:2023-11-03 16:23:50 26 4
gpt4 key购买 nike

你好这个问题与this one基本相同,没有回应。我正在尝试合并 Devise 注册表单以包含不仅生成“用户”而且生成“客户”对象、该客户的“帐户”对象以及该客户的“地址”的字段。

当访问者点击“注册”时,注册表单应包括标准的 Devise 内容,以及用于创建其他对象的字段。相反,我收到此错误:

NoMethodError in Registrations#new

undefined method `build_address' for # Extracted source (around line #6):

    <div class="panel panel-default" style="width: 14em;">  
<% resource.build_customer if resource.customer.nil? %>
<% resource.build_account if resource.accounts.nil? %>
<% resource.build_address if resource.address.nil? %>
<%= form_for(resource, as: resource_name, url: >registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<h3>User Info</h3>

这里没有解释所有的关系,而是模型:

user.rb

    class User < ActiveRecord::Base
before_create :generate_id

# Virtual attribute for authenticating by either username or email
# This is in addition to a real persisted field like 'username'
attr_accessor :login

has_one :administrator

has_one :customer
has_many :accounts, through: :customer
accepts_nested_attributes_for :customer, :allow_destroy => true
accepts_nested_attributes_for :accounts, :allow_destroy => true

has_one :address, through: :customer
accepts_nested_attributes_for :customer, :allow_destroy => true
accepts_nested_attributes_for :address, :allow_destroy => true

validates_uniqueness_of :email, :case_sensitive => false
validates_uniqueness_of :id
validates :username,
:presence => true,
:uniqueness=> {
:case_sensitive => false
}

# User ID is a generated uuid
include ActiveUUID::UUID
natural_key :user_id, :remember_created_at
belongs_to :user
# specify custom UUID namespace for the natural key
uuid_namespace "1dd74dd0-d116-11e0-99c7-5ac5d975667e"

# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :timeoutable, :recoverable, :trackable, :validatable

# Generate a random uuid for new user id creation
def generate_id
self.id = SecureRandom.uuid
end

# Allow signin by either email or username ("lower" function might have to be removed?)
def self.find_for_database_authentication(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:login)
where(conditions.to_h).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
else
where(conditions.to_h).first
end
end
end

customer.rb

   class Customer < ActiveRecord::Base
belongs_to :user
has_one :address
has_many :accounts

validates :phone1, :firstname, :lastname, presence: true
end

account.rb

    class Account < ActiveRecord::Base
belongs_to :customer
belongs_to :user
has_one :acct_type
has_many :acct_transactions

validates :acct_type, presence: true
end

地址.rb

     class Address < ActiveRecord::Base
belongs_to :customer
belongs_to :user

validates :zip_code, presence: true
validates :address1, presence: true

has_one :zip_code
has_one :state, through: :zip_code
end

有问题的两个 Controller :registrations_controller.rb

    class RegistrationsController < Devise::RegistrationsController

before_filter :configure_permitted_parameters

# GET /users/sign_up
def new
@user = current_user
@customer = nil #@user.customer
@account = nil #@customer.account
@address = nil #@customer.address

# Override Devise default behavior and create a customer, account, and address as well
build_resource({})
resource.build_customer
respond_with self.resource

build_resource({})
resource.build_account
respond_with self.resource

build_resource({})
resource.build_address
respond_with self.resource

end

protected

def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u|
.permit(:username, :email, :password, :password_confirmation,
:customer_attributes => [:phone1, :phone2, :title, :firstname, :lastname],
:account_attributes => :acct_type,
:address_attributes => [:address1, :address2, :zip_code])
}
end
end

addresses_controller.rb(重要部分)

      def new
@customer = current_user.customer
@address = @customer.address.build(:customer_id => @customer.id,
:address1 => nil,
:address2 => nil,
:zip_code => nil)
end

def create
@customer = current_user.customer
@address = @customer.address.build(:customer_id => @customer.id,
:address1 => nil,
:address2 => nil,
:zip_code => nil)

respond_to do |format|
if @address.save
format.html { redirect_to @address, notice: 'Address was successfully created.' }
format.json { render :show, status: :created, location: @address }
else
format.html { render :new }
format.json { render json: @address.errors, status: :unprocessable_entity }
end
end
end

这是引发异常的 View (它真的很长,所以实际上是重要的部分):

    <h1>Create an account</h1>
<div class="form-group">
<div class="panel panel-default" style="width: 14em;">
<% resource.build_customer if resource.customer.nil? %>
<% resource.build_account if resource.accounts.nil? %>
<% resource.build_address if resource.address.nil? %>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<h3>User Info</h3>
<div class="form-group">
<!-- fields for User object -->
<div class="field">
<%= f.label :username %><br />
<%= f.text_field :username, autofocus: true %>
</div>
...
<!-- fields for Customer object -->
<%= f.fields_for :customer do |customer_fields| %>
<div class="field">
<%= customer_fields.label :firstname %>
<%= customer_fields.text_field :firstname %>
</div>
...
<!-- fields for Account object -->
<%= f.fields_for :account do |account_fields| %>
<div class="field">
<%= account_fields.label :acct_type %>
<%= account_fields.text_field :acct_type %>
</div>
<% end %>

<!-- fields for Address object -->
<%= f.fields_for :address do |address_fields| %>
<div class="field">
<%= address_fields.label :address1 %>
<%= address_fields.text_field :address1 %>
</div>
...

异常指向顶部的语句 block ...

    <% resource.build_customer if resource.customer.nil? %>
<% resource.build_account if resource.accounts.nil? %>
<% resource.build_address if resource.address.nil? %>

...这之前给我带来了麻烦。在出现当前错误之前,我从第二行(“build_account”)得到了类似的错误。但事实证明这是一个多元化问题,我相信我已经解决了。由于 HTML 是顺序读取的,因此前两个 build_ 方法似乎没有问题。为什么 build_address 方法会出现问题?

我需要先修复这个错误,然后才能知道整个事情是否真的有效。有什么想法吗?

谢谢这是 Rails 4.1.8/Devise 3.4.1

最佳答案

问题出在我使用创建多个资源对象的语法上。它会通过一个,但忽略其余的。我最终为使其工作(或至少使错误消失)所做的是覆盖 build_resource 方法以接受每个要实例化的对象的参数数组:

    def new
@user = current_user

build_resource({})
self.resource[:customer => Customer.new, :account => Account.new, :address => Address.new]
respond_with self.resource
end

def build_resource(hash=nil)
hash ||= params[resource_name] || {}
self.resource = resource_class.new(hash)
end

def create
# Override Devise default behavior and create a customer, account, and address as well
resource = build_resource(params[:user])

if(resource.save)
sign_in(resource_name, resource)
respond_with resource, :location => after_sign_up_path_for(resource)
else
render :action => "new"
end
end

另外,我删除了表单 View 顶部的三行,因为它们试图在 View 中进行某种预验证,结果导致了问题。提交表单时会进行大量验证。这似乎是在做一件好事。现在我正在使用表单 View ,但在渲染每个部分时遇到了问题。 Fields_for 是为 User 和 Account 模型渲染字段,而不是 Customer 或 Address。

关于ruby-on-rails - Rails + Devise 嵌套注册表未定义方法 'build_address',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28928197/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com