Вложенная форма разработки, не связывающая модели

Вложенная форма разработки, не связывающая модели

Я пытаюсь создать новое местоположение и создать пользователя в той же форме и связать их. Пользователь и местоположение созданы, но location_id не сохраняется для пользователя. В пользовательской таблице есть столбец location_id.

Моя форма

<% resource.build_location %>
<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => {:class => 'form-vertical' }) do |f| %>
 <%= f.error_notification %>
 <!-- capture location details hidden values -->
  <%= f.fields_for :location do |location_form| %>
  <%= location_form.text_field :name, :name => "name", :type => "hidden" %>
  <%= location_form.text_field :street_address, :name => "formatted_address", :type => "hidden" %>
  <%= location_form.text_field :lat, :name => "lat", :type => "hidden" %>
  <%= location_form.text_field :long, :name => "lng", :type => "hidden" %>
<% end %>
 <!-- devise user authenticate --> 
  <%= f.input :name, :autofocus => true %> 
  <%= f.input :email, :required => true %>
  <%= f.input :password, :required => true %>
  <%= f.input :password_confirmation, :required => true %>
  <%= f.button :submit, 'Sign up', :class => 'btn-primary' %>
<% end %>
<%= render "devise/shared/links" %>
 

Модель местоположения

class Location < ActiveRecord::Base
  has_many :users, :dependent => :destroy
  accepts_nested_attributes_for :users, :allow_destroy => true
  attr_accessible :lat, :long, :name, :street_address
  attr_accessible :user_attributes
end
 

Контроллер местоположения

def new
    @location = Location.new
    @location.user.build
    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @location }
    end
  end

  # GET /locations/1/edit
  def edit
    @location = Location.find(params[:id])
  end

  # POST /locations
  # POST /locations.json
  def create
    @location = @user.location.build(params[:location])
    respond_to do |format|
      if @location.save
        format.html { redirect_to @location, notice: 'Location was successfully created.' }
        format.json { render json: @location, status: :created, location: @location }
      else
        format.html { render action: "new" }
        format.json { render json: @location.errors, status: :unprocessable_entity }
      end
    end
  end
 

Модель пользователя

class User < ActiveRecord::Base
  belongs_to :location
  accepts_nested_attributes_for :location
  rolify
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :role_ids, :as => :admin
  attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :location, :location_id, :location_attributes
end
 

Пользовательский контроллер

class UsersController < ApplicationController
  before_filter :authenticate_user!

  def index
    authorize! :index, @user, :message => 'Not authorized as an administrator.'
    @users = User.all
  end

  def show
    @user = User.find(params[:id])
  end

  def update
    authorize! :update, @user, :message => 'Not authorized as an administrator.'
    @user = User.find(params[:id])
    if @user.update_attributes(params[:user], :as => :admin)
      redirect_to users_path, :notice => "User updated."
    else
      redirect_to users_path, :alert => "Unable to update user."
    end
  end

  def destroy
    authorize! :destroy, @user, :message => 'Not authorized as an administrator.'
    user = User.find(params[:id])
    unless user == current_user
      user.destroy
      redirect_to users_path, :notice => "User deleted."
    else
      redirect_to users_path, :notice => "Can't delete yourself."
    end
  end
end
 

Никаких ошибок при создании пользователя, просто получение location_id = "nil" при создании пользователя. Я могу получить доступ к местоположению, и идентификатор location_id создается, но не связан с пользователем. Есть идеи, как сохранить location_id для пользователя?

Я заполняю информацию о местоположении с помощью json, возвращаемого из автозаполнения api местоположения Google, и назначаю элемент с name = "". Кажется, что все работает нормально, когда я вручную ввожу информацию о местоположении, но не работает, когда поля заполняются из автозаполнения.

Показать лучший ответ

Прежде всего следует отметить, что вам не нужен accepts_nested_attributes_for на обеих моделях, а только на той, которая имеет ассоциацию has_many . Кроме того, похоже, что множественное число неверно в модели местоположения для атрибутов пользователей

class Location < ActiveRecord::Base
  has_many :users, :dependent => :destroy
  accepts_nested_attributes_for :users, :allow_destroy => true
  attr_accessible :lat, :long, :name, :street_address
  attr_accessible :users_attributes # <- This should be plural
end
 

Удалите accepts_nested_attributes_for в пользовательской модели

class User < ActiveRecord::Base
  belongs_to :location
  accepts_nested_attributes_for :location # <- This should be removed
  rolify
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :role_ids, :as => :admin
  attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :location, :location_id # Also remove location_atributes
end
 

Также эта строка

@location = @user.location.build(params[:location])
 

Должно быть

@location = Location.new(params[:location)
 

так как ваши модели настроены, теперь у местоположения есть пользователь, поэтому вам не нужно создавать местоположение от пользователя. При этом я бы порекомендовал вам создать ассоциацию в противоположном направлении, где у пользователя has_many location, но это, конечно, может противоречить вашей функции, поэтому относитесь к этому с недоверием :).

http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ ClassMethods.html

Спасибо, Джейсон, проблема в том, что если я удалю accept_nested_attributes_for в модели пользователя, я получу эту ошибку: ActiveRecord :: AssociationTypeMismatch в DeviseInvitable :: RegistrationsController # create Location (# 70224765161800) ожидается, получил ActiveSupport :: HashWithIndifferentAccess (# 7024024763369)

Может быть проблема с UsersController . Поскольку вы используете devise, он вам вообще не нужен, и если вы хотите переопределить функциональность, которую предоставляет devise, вам придется переопределить сам их контроллер. См. Для справки: github.com/plataformatec/devise#configuring-controllers . Вы также можете удалить :location и location_attributes из пользовательской модели, если вы этого не сделали.

Спасибо, Джейсон, я посмотрю на это. Я уверен, что есть более эффективные способы сделать это, хотя я все еще немного не понимаю, почему это работает, когда я вручную ввожу данные в text_field, но не работает, когда это же text_field получает текст json.