Установка has_many: через форму на рельсах 3 - PullRequest
2 голосов
/ 31 января 2012

Я пытаюсь создать роли пользователя для моего пользователя, используя форму,

<%= form_for @user do |f| %>
  <%= f.error_messages %>
  <p>
    <%= f.label :username %><br />
    <%= f.text_field :username %>
  </p>
  <p>
    <%= f.label :email, "Email Address" %><br />
    <%= f.text_field :email %>
  </p>
  <p>
    <%= f.label :password %><br />
    <%= f.password_field :password %>
  </p>
  <p>
    <%= f.label :password_confirmation, "Confirm Password" %><br />
    <%= f.password_field :password_confirmation %>
  </p>

  <% # f.select :roles, Role.all.map {|r| [r.title]} %>

  <% Role.all.each do |role| %>
    <div>
      <%= check_box_tag :role_ids, role.id, @user.roles.include?(role), :name => 'user[role_ids][]' -%>
      <%= label_tag :role_ids, role.title -%>
    </div>
  <% end -%>

  <p><%= f.submit (@user.new_record? ? "Sign up" : "Update"), :id => :sign_up %></p>
<% end %>

Это связь, которая у меня есть в моей модели

class user < ActiveRecord::Base
  has_many :assignments
  has_many :roles, :through => :assignments
end

class assignment < ActiveRecord::Base
  belongs_to :user
  belongs_to :role
end

class role < ActiveRecord::Base
  has_many :assignments
  has_many :users, :through => :assignments
end

Как создать назначение между пользователем и ролью, используя форму, которую я представил в начале?

Мое действие создания в моем пользовательском контроллере выглядит так:

def create
   @user = User.new(params[:user])
    if @user.save
      session[:user_id] = @user.id
      render :action => 'dashboard'
    else
      render :action => 'new'
    end
  end

При отправке формы я получаю сообщение об ошибке:

ActiveRecord :: AssociationTypeMismatch в UsersController # create

Ожидается роль (# 70331681817580), получена строка (# 70331650003400)

Request

Parameters:

{"utf8"=>"✓",
 "authenticity_token"=>"WHpOW+DmymZ2pWmY9NHSuodf2vjyKdgMNZcc8NvCNa0=",
 "user"=>{"username"=>"ioio",
 "email"=>"ioio@ioio.com",
 "password"=>"[FILTERED]",
 "password_confirmation"=>"[FILTERED]",
 "roles"=>["2"]},   #### <<< ==== This is the checkbox that I selected for this request.
 "commit"=>"Sign up"}

Любая помощь приветствуется.

Ответы [ 2 ]

4 голосов
/ 31 января 2012

Используя вашу текущую форму и основываясь на:

<%= check_box_tag :role_ids, role.id, @user.roles.include?(role), :name => 'user[role_ids][]' -%>

При отправке ваши параметры должны выглядеть следующим образом (обратите внимание на 'role_ids', а не 'role'):

Request

Parameters:

{"utf8"=>"✓",
 "authenticity_token"=>"WHpOW+DmymZ2pWmY9NHSuodf2vjyKdgMNZcc8NvCNa0=",
 "user"=>{"username"=>"ioio",
 "email"=>"ioio@ioio.com",
 "password"=>"[FILTERED]",
 "password_confirmation"=>"[FILTERED]",
 "role_ids"=>["2"]},   #### <<< ==== This is the checkbox that I selected for this request.
 "commit"=>"Sign up"}

Если это так, вам придется скопировать свои роли и установить их для пользователя в контроллере:

    def create
      @user = User.new(params[:user])
      roles = Role.find(params[:user][:role_ids]) rescue []
      @user.roles = roles
      if @user.save
        session[:user_id] = @user.id
        render :action => 'dashboard'
      else
        render :action => 'new'
      end
    end

... и аналогично:

   def update
     @user = User.where(:username=>params[:id]).first
     roles = Role.find(params[:user][:role_ids]) rescue []
     @user.roles = roles
     if @user.update_attributes(params[:user])
       redirect_to users_url, :notice  => "Successfully updated user."
     else
      render :action => 'edit'
     end
   end
0 голосов
/ 31 января 2012

Сообщение об ошибке дает подсказку: чтобы сохранить пользовательский объект, сначала нужно как-то создать связанные объекты Role.На данный момент у вас есть только массив строк с идентификаторами ролей.

Вам необходимо использовать метод acceptpts_nested_attributes_for в пользовательской модели.

...