samedi 25 juillet 2015

Rails: Multi-Step New User Signup Form (First argument in form cannot contain nil or be empty)

I'm a beginner and have a serious problem with making two steps signing up.

I keep getting that error:

First argument in form cannot contain nil or be empty
<%= form_for(@Profile) do |f| %>

Users can sign up with their user information which are on the user table(DB). And all is fine with them. But I really want them to have profiles. So they can put their bio for example.

I tried to create MVC structure for the profiles based on users' MVC but it doesn't work.

I have been trying to find the answer for days. Tried hundreds of variations but nothing worked out. Please help!

views/users/new.html.erb (This is working)( I just wanted to create profile for the users and give them the ability to fill out their information as the second steps of the signing up)

<div class="container">
  <% provide(:title, 'Sign up') %>
  <h1 class="center">Sign up</h1>

  <div class="row">
    <div class="col s12 m10 l8 offset-m1 offset-l2">
      <%= form_for(@user) do |f| %>
        <%= render 'shared/error_messages', object: f.object %>

        <%= f.label :first_name %>
        <%= f.text_field :first_name %>

        <%= f.label :genre %>
        <%= f.text_field :genre %>

        <%= f.label :middle_name %>
        <%= f.text_field :middle_name %>

        <%= f.label :last_name %>
        <%= f.text_field :last_name %>

        <%= f.label :preferred_name %>
        <%= f.text_field :preferred_name %>

        <%= f.label :email %>
        <%= f.text_field :email %>

        <%= f.label :password %>
        <%= f.password_field :password %>

        <%= f.label :password_confirmation, "Confirmation" %>
        <%= f.password_field :password_confirmation %>
        <div class="row center">
        <%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
        </div>
      <% end %>
    </div>
  </div>
</div>

models/user.rb

class User < ActiveRecord::Base
  has_one  :profile
  has_many :microposts, dependent: :destroy
  has_many :relationships, foreign_key: "follower_id", dependent: :destroy
  has_many :followed_users, through: :relationships, source: :followed
  has_many :reverse_relationships, foreign_key: "followed_id",
                                   class_name:  "Relationship",
                                   dependent:   :destroy
  has_many :followers, through: :reverse_relationships, source: :follower
  before_save { self.email = email.downcase }
  before_create :create_remember_token
  validates :first_name, presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
  has_secure_password
  validates :password, length: { minimum: 6 }

  def User.new_remember_token
    SecureRandom.urlsafe_base64
  end

  def User.digest(token)
    Digest::SHA1.hexdigest(token.to_s)
  end

  def feed
    Micropost.from_users_followed_by(self)
  end

  def following?(other_user)
    relationships.find_by(followed_id: other_user.id)
  end

  def follow!(other_user)
    relationships.create!(followed_id: other_user.id)
  end

  def unfollow!(other_user)
    relationships.find_by(followed_id: other_user.id).destroy
  end

  private

    def create_remember_token
      self.remember_token = User.digest(User.new_remember_token)
    end
end

controllers/users_controller.rb

    class UsersController < ApplicationController


    before_action :signed_in_user,
                    only: [:index, :edit, :update, :destroy, :following, :followers]
      before_action :correct_user,   only: [:edit, :update]
      before_action :admin_user,     only: :destroy

      def index
        @users = User.paginate(page: params[:page])
      end

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

      def new
        @user = User.new
      end



  def create
    @user = User.new(user_params)
    if @user.save
      sign_in @user
      flash[:success] = "Welcome to the my app"
      redirect_to @user
    else
      render 'new'
    end
  end

  def edit
  end

  def update
    if @user.update_attributes(user_params)
      flash[:success] = "Profile updated"
      redirect_to @user
    else
      render 'edit'
    end
  end

  def destroy
    User.find(params[:id]).destroy
    flash[:success] = "just got destroyed."
    redirect_to users_url
  end

  def following
    @title = "Connections"
    @user = User.find(params[:id])
    @users = @user.followed_users.paginate(page: params[:page])
    render 'show_follow'
  end

  def followers
    @title = "known by"
    @user = User.find(params[:id])
    @users = @user.followers.paginate(page: params[:page])
    render 'show_follow'
  end

  private

    def user_params
      params.require(:user).permit(:first_name, :middle_name, :last_name, :preferred_name, :email, :password,
                                   :password_confirmation)
    end

    # Before filters

    def correct_user
      @user = User.find(params[:id])
      redirect_to(root_url) unless current_user?(@user)
    end

    def admin_user
      redirect_to(root_url) unless current_user.admin?
    end
  end

second signup page
views/users/signup2.html.erb

<div class="container">
  <% provide(:title, 'Sign up2') %>
  <h1 class="center">Sign up2</h1>

  <div class="row">
    <div class="col s12 m10 l8 offset-m1 offset-l2">
      <%= form_for(@Profile) do |f| %>
        <%= render 'shared/error_messages', object: f.object %>

        <%= f.label :primary_instrument %>
        <%= f.text_field :primary_instrument %>

        <%= f.label :bio %>
        <%= f.text_field :bio %>

        <div class="row center">
        <%= f.submit "Create my account2", class: "btn btn-large btn-primary" %>
        </div>
      <% end %>
    </div>
  </div>
</div>

models/profile.rb

class Profile < ActiveRecord::Base
  belongs_to :user
end

controllers/profiles_controller.rb

class ProfilesController < ApplicationController

  before_filter :get_user

  def get_user
    @profile = User.find(params[:user_id])
  end

  # generate new-profile form
  def new
    @user.profile = Profile.new
    @profile = @user.profile
  end

  # process new-profile-form post
  def create

    @user.profile = Profile.new(params[:profile])
    @profile = @user.profile

    respond_to do |format|
      if @profile.save
        flash[:notice] = 'Profile was successfully created.'
        format.html { redirect_to(@profile) }
        format.xml  { render :xml => @profile, :status => :created, :location => @profile }
      ...
      end
    end

  end

  # generate edit-profile form
  def edit
    @profile = Profile.find(params[:id])
  end

  # generate edit-profile-form post
  def update

    @profile = @user.profile

    respond_to do |format|
      if @profile.update_attributes(params[:profile])
        flash[:notice] = 'Profile was successfully updated.'
        # format.html { redirect_to(@profile) }
        format.html { redirect_to(user_profile(@user)) }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @profile.errors, :status => :unprocessable_entity }
      end
    end

end

Routes.rb

 root to: 'static_pages#home'
  match '/signup',  to: 'users#new',            via: 'get'
  match '/signup2', to: 'profiles#new',         via: 'get'
  match '/signin',  to: 'sessions#new',         via: 'get'
  match '/signout', to: 'sessions#destroy',     via: 'delete'
  match '/help',    to: 'static_pages#help',    via: 'get'
  match '/about',   to: 'static_pages#about',   via: 'get'
  match '/contact', to: 'static_pages#contact', via: 'get'
end

Aucun commentaire:

Enregistrer un commentaire