3

I followed Michael Hartl's 'Rails Tutorial' book and need to render the 'micropost feed' at a custom location (/members) instead of at the site's root.

I've updated the SessionsController so that when a user logs in they are redirected to the new /members URL, but there are two statements needed on the member view that cause errors and prevent the page from loading with the micropost feed.

# app/views/members/index.html.erb
<%= render 'shared/micropost_form' %>
<%= render 'shared/feed' %>

The first error is:

ArgumentError in MembersController#index
First argument in form cannot contain nil or be empty

returning raise ArgumentError, "First argument in form cannot contain nil or be empty" unless object and the second error (seen when removing the first render statement) returns undefined method 'any?' for nil:NilClass

Part of this issue is because to render the 'micropost feed' at /members the app/views/members/index.html.erb seems to need access to app/controllers/microposts_controller.rb and I'm unsure how to handle this.

Update:

micropost_controller.rb

# controllers/micropost_controller.rb

class MicropostsController < ApplicationController
  before_action :logged_in_user, only: [:create, :destroy]
  before_action :correct_user,   only: :destroy

  def create
    @micropost = current_user.microposts.build(micropost_params)
    if @micropost.save
      flash[:success] = "Micropost created!"
      redirect_to '/members'
    else
      @feed_items = []
      render '/members'
    end
  end

  def destroy
    @micropost.destroy
    flash[:success] = "Micropost deleted"
    redirect_to request.referrer || '/members'
  end

  private

    def micropost_params
      params.require(:micropost).permit(:content, :picture)
    end

    def correct_user
      @micropost = current_user.microposts.find_by(id: params[:id])
      redirect_to '/members' if @micropost.nil?
    end
end

_micropost_form.html.erb

# shared/_micropost_form.html.erb

<%= form_for(@micropost, html: { multipart: true }) do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <div class="field">
    <%= f.text_area :content, placeholder: "Compose new micropost (420 chars max)..." %>
  </div>
  <%= f.submit "Post", class: "btn btn-primary" %>
  <span class="picture">
    <%= f.file_field :picture, accept: 'image/jpeg,image/gif,image/png' %>
  </span>
<% end %>

<script type="text/javascript">
  $('#micropost_picture').bind('change', function() {
    size_in_megabytes = this.files[0].size/1024/1024;
    if (size_in_megabytes > 5) {
      alert('Maximum file size is 5MB. Please choose a smaller file.');
    }
  });
</script>

_feed.html.erb

# shared/_feed.html.erb

<% if @feed_items.any? %>
  <ol class="microposts">
    <%= render @feed_items %>
  </ol>
  <%= will_paginate @feed_items %>
<% end %>

MembersController (as updated with @Mandeep's suggestion below)

class MembersController < ApplicationController
  def index
    @micropost = current_user.microposts.build
    @feed_items = current_user.microposts
  end
end
CryptoPiggy
  • 700
  • 2
  • 8
  • 21
  • 1
    Can you please post the code for controller, and partials? – Arslan Ali Jun 19 '15 at 05:06
  • Don't you have `index` method in your controller whose view you are rendering? – Arslan Ali Jun 19 '15 at 05:24
  • Second thing: You wrote the code for `MicropostsController`, and you are expecting something in `app/members/view/index.html.erb`. For the view of `members`, you should use `MembersController`. – Arslan Ali Jun 19 '15 at 05:26
  • And please post the code for you `index` method in controller. In `index` method, you should have `@micropost`, and `@feed_items` instance variables. – Arslan Ali Jun 19 '15 at 05:45
  • I added the `index` method from the MembersController as asked. It was empty before, but I applied @Mandeep's suggestion earlier. Thanks so much for both of your help! – CryptoPiggy Jun 19 '15 at 05:49
  • you are welcome for it. Happy learning! – Arslan Ali Jun 19 '15 at 05:51

2 Answers2

1

You are not passing arguments in your partials. You need to do the following:

<%= render 'shared/micropost_form', :locals => { :micropost => @micropost }  %>
<%= render 'shared/feed', :locals => { :feed_items => @feed_items }  %>

Remember, you need to have these two variables inside your index method: @micropost and @feed_items.

Arslan Ali
  • 17,418
  • 8
  • 58
  • 76
  • Thanks Arslan, that's very good to know! Somehow I'm still getting the `raise ArgumentError, "First argument in form cannot contain nil or be empty" unless object` error though from `ArgumentError in MembersController#index`. – CryptoPiggy Jun 19 '15 at 05:31
  • Why are you writing the code inside `MicropstsController`, instead you should write a separate `MembersController` class, and write member-related code there. – Arslan Ali Jun 19 '15 at 05:39
  • Good point. Thanks for the info Arslan. The tutorial I was following was designed that way and I didn't want to change it in case I broke something else. :) – CryptoPiggy Jun 19 '15 at 05:43
1

Add this code to your Controller:

class MembersController < ApplicationController
  def index
    @micropost = current_user.microposts.build
    @feed_items = current_user.microposts
  end
end
Arslan Ali
  • 17,418
  • 8
  • 58
  • 76
Mandeep
  • 9,093
  • 2
  • 26
  • 36