pmuens
pmuens

Reputation: 798

Rails Wicked Gem - Using two (nested) models in one wizard

I'm trying to use the Wicked-Gem for my wizard after a user has signed up successfull.

The first step is that the user should enter his "general infos" (bio and interests). After submitting these information, the user should enter one characteristic (A user has many charactersitics).

The Problem I have is the following: How do I use Wicked correctly to create a Form for the user-model for the fist step and the characteristic-model in the second step (which belongs to a user)?

The Error I'm getting is:

Can't mass-assign protected attributes: characteristics

I don't want to use nested-attributes, because the wizard would be the only place where I would use them.

Here is my sourcecode:

The Wicked-Controller:

#!/bin/env ruby
# encoding: utf-8
class AfterFirstSignInController < ApplicationController
  include Wicked::Wizard

  skip_before_filter :check_if_profile_complete, only: [:show, :update]

  steps :general_infos, :characteristics

  def show
    @user = current_user
    @characteristic = @user.characteristics.new
    @title = t('controllers.after_first_sign_in_controller.show.title')
    render_wizard
  end

  def update
    @user = current_user
    @characteristic = @user.characteristics.new
    case step
      when :general_infos
        @user.attributes = params[:user]
        render_wizard @user
      else
        @characteristic.attributes = params[:characteristic]
        render_wizard @characteristic
    end
  end
end

The "general-infos-form"

.container
  .row
    .span5.offset3
      .progress.progress-info.progress-striped
        .bar(style='width: 50%')
          1/2
      .page-header
        %h1
          = t('views.after_first_sign_in.general_infos.h1')
      = form_for(@user, url: wizard_path, method: :put) do |f|
        = render 'shared/error_messages', object: @user
        .control-group
          %label.control-label(for='bio')
            = t('views.after_first_sign_in.general_infos.labels.bio')
          .controls
            = f.text_area :bio, id: 'bio', rows: '6'
        .control-group
          %label.control-label(for='interest_list')
            = t('views.after_first_sign_in.general_infos.labels.interest_list')
          .controls
            = f.text_field :interest_list, id: 'interest_list'
        .form-actions
          = f.submit t('views.after_first_sign_in.general_infos.buttons.submit'), disable_with: t('views.after_first_sign_in.general_infos.buttons.submit'), class: 'btn btn-primary pull-right'

The "characteristics-form"

.container
  .row
    .span5.offset3
      .progress.progress-info.progress-striped
        .bar(style='width: 100%')
          2/2
      .page-header
        %h1
          = t('views.after_first_sign_in.characteristics.h1')
      = form_for([@user, @characteristic], url: wizard_path, method: :put) do |f|
        = render 'shared/error_messages', object: @characteristic
        = f.fields_for :characteristics do |builder|
          .control-group
            %label.control-label(for='title')
              = t('views.after_first_sign_in.characteristics.labels.title')
            .controls
              = builder.text_field :title, id: 'title'
          .control-group
            %label.control-label(for='description')
              = t('views.after_first_sign_in.characteristics.labels.description')
            .controls
              = builder.text_area :description, id: 'description', rows: '6'
        .form-actions
          = f.submit t('views.after_first_sign_in.characteristics.buttons.submit'), disable_with: t('views.after_first_sign_in.characteristics.buttons.submit'), class: 'btn btn-primary pull-right'
          = link_to t('views.after_first_sign_in.characteristics.buttons.general_infos_step'), after_first_sign_in_path(:general_infos), class: 'btn'

The routes-file

Test::Application.routes.draw do
  scope '(:locale)' do
    resources :users do
      resources :characteristics
      resources :followings, only: [:create, :destroy, :index]
      resources :wall_entries, only: [:create, :destroy]
      resources :messages, only: [:create, :destroy, :index]
    end

    resources :characteristics do
      resources :votes, only: [:create, :destroy]
    end

    resources :after_first_sign_in

    match '/auth/:provider/callback', to: 'sessions#create'
    match '/auth/failure', to: redirect('/')
    match '/sign_out', to: 'sessions#destroy', as: 'sign_out'

    match '/change_locale', to: 'users#change_locale', as: 'change_locale'
    match '/home', to: 'users#home', as: 'home'
    match '/discover', to: 'users#discover', as: 'discover'

    match '/terms_of_service', to: 'pages#terms_of_service'
    match '/masthead', to: 'pages#masthead'
    match '/privacy', to: 'pages#privacy'

    root to: 'pages#index'
  end
end

Thank you very much!

Upvotes: 3

Views: 2204

Answers (1)

dombesz
dombesz

Reputation: 7909

I guess you are using nested_attributes for @user.characteristics. If so then you should add the following to your user model:

attr_accessible :characteristics_attributes
accepts_nested_attributes_for :characteristics

But also something is not clear on your characteristics-form this part, you probably want something like this:

= form_for(@user, url: wizard_path, method: :put) do |f|
    = render 'shared/error_messages', object: @user
    = f.fields_for :characteristics do |builder|

Note that, fields_for probably will loop through each characteristic separate and render the fields for each of them, so you don't need to care about @characteristic

Upvotes: 3

Related Questions