undefined method `memo' for nil:NilClass error using best_in_place - ruby

I've created a simple memo feature for my app, and have successfully implemented in-place editing using the best_in_place gem.
The problem I am having is creating new memos using in-place editing, the following code returns undefined methodmemo' for nil:NilClass`
#partial for logged in users on homepage
<% provide(:title, current_user.name) %>
<h1>Hey
<%= current_user.name %>
</h1>
<div class="row-fluid">
<div class="span12">
<div class="row-fluid">
<div class="span6">
<h2>Memos</h2>
<ul id="memos" data-update-url="<%= sort_memos_url %>">
<%# render #memos %>
<% #memos.each do |memo| %>
<%= content_tag_for :li, memo do %>
<%= best_in_place memo, :memo %>
<% end %>
<% end %>
</ul>
<p><%# link_to "Add a memo", new_memo_path %></p>
<p><%= best_in_place #memo, :memo, :path => new_memo_path, :nil => "Add a memo" %></p>
</div>
<div class="span6"><h2>Coming up...</h2></div>
</div>
</div>
</div>
#memos controller
def index
#memos = Memo.order("position")
end
def show
#memo = Memo.find(params[:id])
end
def new
#memo = Memo.new
end
def create
#memo = Memo.new(params[:memo])
if #memo.save
redirect_to #memo, notice: "Successfully created memo."
else
render :new
end
end
def edit
#memo = Memo.find(params[:id])
end
def update
#memo = Memo.find(params[:id])
#memo.update_attributes(params[:memo])
respond_with #memo
end
def sort
params[:memo].each_with_index do |id, index|
Memo.update_all({position: index+1}, {id: id})
end
render nothing: true
end
#home page controller
respond_to :html, :json
def home
if signed_in?
#memos = Memo.order("position")
end
end
def sort
params[:memo].each_with_index do |id, index|
Memo.update_all({position: index+1}, {id: id})
end
render nothing: true
end
def help
end
end
I am new to rails and programming in general so I am sure it is a simple fix, none-the-less it's one that I cannot seem to remedy.

Have a look at (see 3.3.4):
http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials
Using partials and variables, means you need to stick to a certain naming convention. If your not doing that, then you need to send the variable (from the calling view) with it.
<%= render :partial => "form", :locals => { :zone => #zone } %>

Related

Nested formed by cocoon cannot be saved

Problem
I'm coding user's profile page on Rails.
I added a gem "language-select" for users to choose a language which they're learning. And users might learn several languages, so I added gem "cocoon" as well.
The first language which users choose is successfully saved, but others which were chosen by cocoon cannot be saved. I would like them to be saved and being showed on their profile page.
How I reached this problem
I added cocoon by refering this page and code.README in github
However, "Save" button didn't react anything, so I made the form_for's method "post".
<%= form_for #user, method: :post do |f| %>
<div id='languages'>
<%= f.fields_for :languages do |language| %>
<%= render 'language_fields', :f => language %>
<% end %>
<div class='links'>
<%= link_to_add_association 'add language', f, :languages %>
</div>
</div>
<% end %>
Then "Save" button worked, but an error occured.
ActionController::InvalidAuthenticityToken in UsersController#update
ActionController::InvalidAuthenticityToken
Extracted source (around line #211):
def handle_unverified_request
raise ActionController::InvalidAuthenticityToken
end
end
end
Therefore, I added "protect_from_forgery with: :null_session" to application_controller.rb. Then the error disappeared, but the problem which I mentioned above occered. The first language which users choose is saved, but other ones which were chosen by cocoon cannot be saved.
(users#show.html.erb)
<h2><%= #user.language %></h2>
(users#edit.html.erb)
<%= form_tag("/users/#{#user.id}/update", {multipart: true}) do %>
<table>
<p>Languages</p>
<%= select_tag(:language,options_for_select(languages)) %>
<%= render 'users/form' %>
<input type="submit" value="Submit">
</table>
<% end %>
(users#_form.html.erb)
Partial of cocoon.
<%= form_for #user, method: :post do |f| %>
<div id='languages'>
<%= f.fields_for :languages do |language| %>
<%= render 'language_fields', :f => language %>
<% end %>
<div class='links'>
<%= link_to_add_association 'add language', f, :languages %>
</div>
</div>
<% end %>
(users#_language.html.erb)
Partial of cocoon.
<div class='nested-fields'>
<div class="field">
<%= select_tag(:language,options_for_select(languages)) %>
</div>
<%= link_to_remove_association "remove language", f %>
</div>
(users_controller.rb)
Even though I settled "redirect_to("/users/#{#user.id}")" here, it redirects to "/posts/index" after press "Save" button. And the sentence "You're already logged in" which I settled at "forbid_login_user" in "application_controller.rb" is shown too.
before_action :authenticate_user, {only: [:index, :show, :edit, :update]}
before_action :forbid_login_user, {only: [:new, :create, :login_form, :login]}
before_action :ensure_correct_user, {only: [:edit, :update]}
def edit
#user = User.find_by(id: params[:id])
end
def user_params
params.require(:user).permit(:name, :description, languages_attributes: [:id, :description, :done, :_destroy])
end
def update
#user = User.find_by(id: params[:id])
#user.language = params[:language]
if params[:image]
#user.image_name = "#{#user.id}.jpg"
image = params[:image]
File.binwrite("public/user_images/#{#user.image_name}", image.read)
end
if params[:cover_image]
#user.cover_image_name = "#{#user.id}_cover.jpg"
cover_image = params[:cover_image]
File.binwrite("public/user_cover_images/#{#user.cover_image_name}", cover_image.read)
end
if #user.save
flash[:notice] = "Edited user's information"
redirect_to("/users/#{#user.id}")
else
render("users/edit")
end
end
(application_controller.rb)
class ApplicationController < ActionController::Base
protect_from_forgery with: :null_session
before_action :set_current_user
def set_current_user
#current_user = User.find_by(id: session[:user_id])
end
def authenticate_user
if #current_user == nil
flash[:notice] = "You need to log in"
redirect_to("/login")
end
end
def forbid_login_user
if #current_user
flash[:notice] = "You're already logged in"
redirect_to("/posts/index")
end
end
end
I will add more code if it needs to be refered. Thank you very much.
Version
ruby 2.6.4p104 / RubyGems 3.0.3 / Rails 5.2.3
Postscript
When I choose only one language, it can be saved.
When I choose like several languages like below, the problem which I mentoined above happens. Nothing is saved.
But after putting "skip_before_action :verify_authenticity_token" in application_controller.rb, only "English"(the last one) is saved (checked by rails console).
"Japanese" (chose by original form)
"English" (added and chose by cocoon)
Anyway, only 1 language can be saved so far.

undefined method `any?' for nil:NilClass for <% if #users.any? %>

I am following the Micheal Hartl Ruby on Rails tutorial. In the 12 chapter, I am getting this error.
I am trying to display the following and the followers, but I am not able to.
Following are the codes:
show.html.erb
<% provide(:title, #title) %>
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<%= gravatar_for #user %>
<h1><%= #user.name %></h1>
<span><%= link_to "view my profile", #user %></span>
<span><b>Microposts:</b> <%= #user.microposts.count %></span>
</section>
<section class="stats">
<%= render 'shared/stats' %>
<% if #users.any? %>
<div class="user_avatars">
<% #users.each do |user| %>
<%= link_to gravatar_for(user, size: 30), user %>
<% end %>
</div>
<% end %>
</section>
</aside>
<div class="col-md-8">
<h3><%= #title %></h3>
<% if #users.any? %>
<ul class="users follow">
<%= render #users %>
</ul>
<%= will_paginate %>
<% end %>
</div>
</div>
relationship_controller.rb
class RelationshipsController < ApplicationController
before_action :logged_in_user
def create
def create
#user = User.find(params[:followed_id])
current_user.follow(user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
def destroy
#user = Relationship.find(params[:id]).followed
current_user.unfollow(user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
end
user_controller.rb
class UsersController < ApplicationController
before_action :logged_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], :per_page => 5)
end
def new
#user= User.new
end
def create
#user= User.new(user_params)
if #user.save
#user.send_activation_email
flash[:info] = "Please check your email to activate your account."
redirect_to root_url
else
render 'new'
end
end
def edit
#user= User.find(params[:id])
end
def update
#user= User.find(params[:id])
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] = "User deleted"
redirect_to users_url
end
def following
#title = "Following"
#user = User.find(params[:id])
#users = #user.following.paginate(page: params[:page])
render 'show_follow'
end
def followers
#title = "Followers"
#user = User.find(params[:id])
#users = #user.followers.paginate(page: params[:page])
render 'show_follow'
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
def correct_user
#user= User.find(params[:id])
redirect_to(root_url) unless #user== current_user
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
Your issue is that the show action is actually using the #user instead of #users instance variable.
Your section for stats will not work since it's expecting what it looks like a collection of User as it would from the index action.
Since you have the action for followers which sets the #user and #users instance variables you have to visit that action instead and the code on your show.html.erb template will most likely have to move to the show_follow.html.erb template.
UPDATE
You need to remove this section from your show.html.erb template
<section class="stats">
<%= render 'shared/stats' %>
<% if #users.any? %>
<div class="user_avatars">
<% #users.each do |user| %>
<%= link_to gravatar_for(user, size: 30), user %>
<% end %>
</div>
<% end %>
</section>
</aside>
<div class="col-md-8">
<h3><%= #title %></h3>
<% if #users.any? %>
<ul class="users follow">
<%= render #users %>
</ul>
<%= will_paginate %>
<% end %>
</div>
I saw your repository and seems like you have messed up the code, according to what you are following(Ruby on Rails - Micheal Hartl), this is what you need to change:
The code in your show.html.erb should be placed in show_follow.html.erb
After this follow the 12th chapter again and place the right code in show.html.erb.

Ruby on Rails error when using same form on multiple pages

I have a contact form setup and working on my 'Contact' page. However, when I copy that form to another page I get this error: 'First argument in form cannot contain nil or be empty'.
Here is my contactcontroller:
class ContactsController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact = Contact.new(params[:contact])
if #contact.valid?
ContactMailer.contact_email(#contact).deliver_now
redirect_to new_contact_path, notice: "Your email has been sent. Thank you."
else
render :new
end
end
end
Here is the other page controller:
class GolfcoursesController < ApplicationController
protect_from_forgery
def index
#golf_courses = GolfCourse.all
end
def show
#golf_courses = GolfCourse.all
#golfcourse = GolfCourse.find_by(slug: params[:slug])
#holes = #golfcourse.golf_holes
end
def events
end
def membership
end
def practice_facilities
end
def contact
end
def golf
#golf_courses = GolfCourse.all
end
def new
#contact = Contact.new
end
def create
#contact = Contact.new(params[:contact])
if #contact.valid?
ContactMailer.contact_email(#contact).deliver_now
redirect_to new_contact_path, notice: "Your email has been sent. Thank you."
else
render :new
end
end
end
And here is the form:
<div class="container">
<h4>Let us know if you have any questions.</h4>
<%= form_for #contact, :html => {:role => 'form'} do |f| %>
<div class="form-group">
<%= f.label :name, 'Enter your name:' %>
<%= f.text_field :name, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :email, 'Email:' %>
<%= f.email_field :email, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :message, 'Message:' %>
<%= f.text_area :message, class: 'form-control', :rows => 3 %>
</div>
<div class="form-group">
<%= f.submit 'Submit', class: 'btn btn-default' %>
</div>
<% end %>
</div>
Thanks in advance for any help!
'First argument in form cannot contain nil or be empty'
You should also initialize the #contact in your other controller.
If you would like to share forms, I'd suggest the use of partials and passing in locals. This makes your code also somewhat DRY.
For reference also see the rails guides:
http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials

Can I work around ActiveRecord?

Trying get a handle on oAuth by recreating twitter using the omniauth-twitter and twitter gems, and I'm stuck on viewing the tweets of all the users I'm following in my app together in one place. I can view my own tweets and other users' in their own profile fine.
This is the error trace
NoMethodError in PagesController#home
undefined method `where' for Twitter::Timeline:Class
app/models/twitter/timeline.rb:47:in `from_users_followed_by'
app/models/user.rb:24:in `hub'
app/controllers/pages_controller.rb:5:in `home'
pages_controller.rb
def home
if signed_in?
#hub_items = current_user.hub.paginate(page: params[:page])
end
end
user.rb
def hub
Twitter::Timeline.from_users_followed_by(self)
end
timeline.rb
module Twitter
class Timeline
def self.from_users_followed_by(user)
followed_user_ids = "SELECT followed_id FROM relationships
WHERE follower_id = :user_id"
Twitter::Timeline.where("user_id IN (#{followed_user_ids}) OR user_id = :user_id",
user_id: user.id)
end
end
end
** Controllers
hub_controller.rb
def show
#hub_items = []
render 'pages/home'
end
** Views
_hub.html.erb
<% if #hub_items.any? %>
<ol class="microposts">
<%= render partial: 'shared/hub_item', collection: #hub_items %>
</ol>
<%= will_paginate #hub_items %>
<% end %>
_hub_items.html.erb
<li id="<%= hub_item.id %>">
<% if #hub_item.any? %>
<% #hub_item.each do |post| %>
<% if post.provider == "twitter" %>
<%= render partial: "users/twitter_post", locals: {post: post} %>
<% end %>
</li>
So, Is there a way to write my self.from_users_followed_by method so that it doesn't have to inherit from ActiveRecord::Base? I can give anything else that's needed to figure this out.

Object in hidden_field_tag becomes nil when partial is called into an index (yet, works in individual Show view)

Rails 3.1.3
I am making a simple site where people can share short stories and can rate those stories on a 5 Star rating system. The Star rating system is the problem. I can get it to work fine in the stories/show.html view, but not on the indexed home page. Here is my code:
home.html.erb
<% content_for(:scripts) do %>
<%= javascript_include_tag 'rating_ballot'%>
<% end %>
<div id="talesFeedHome">
<p class="notice"><%= notice %></p>
<%= render #tales.sort_by { |tale| tale.created_at }.reverse %>
</div>
<p class="clear"> </p>
tales/_tale.html.erb
<% if signed_in? %>
<div id="homeTales">
<ul>
<div id="taleShow">
<div id="controlPanel">
<li id="taleUserName"><%= tale.user.name %></li>
<li id="averageRating"> Your Rating:<br /><%= render "tales/stars" %></li>
</div>
<div id="taleDisplay">
<li><%= link_to(tale) do %>
<span><%= tale.title %> </span>
<span><%= tale.content %></span>
<% end %>
</li> <br />
</div>
</div>
</ul>
</div>
<% else %>
...
tales/_stars.html.erb
<div id="starRating">
<%= form_for(rating_ballot, :remote => true, :html => { :class => 'rating_ballot' }) do |f| %>
<%= f.label("value_1", content_tag(:span, '1'), {:class=>"rating", :id=>"1"}) %>
<%= radio_button_tag("rating[value]", 1, current_user_rating == 1, :class => 'rating_button') %>
<%= f.label("value_2", content_tag(:span, '2'), {:class=>"rating", :id=>"2"}) %>
<%= radio_button_tag("rating[value]", 2, current_user_rating == 2, :class => 'rating_button') %>
<%= f.label("value_3", content_tag(:span, '3'), {:class=>"rating", :id=>"3"}) %>
<%= radio_button_tag("rating[value]", 3, current_user_rating == 3, :class => 'rating_button') %>
<%= f.label("value_4", content_tag(:span, '4'), {:class=>"rating", :id=>"4"}) %>
<%= radio_button_tag("rating[value]", 4, current_user_rating == 4, :class => 'rating_button') %>
<%= f.label("value_5", content_tag(:span, '5'), {:class=>"rating", :id=>"5"}) %>
<%= radio_button_tag("rating[value]", 5, current_user_rating == 5, :class => 'rating_button') %>
<%= hidden_field_tag(:tale_id, #tale.id) %>
<% end %>
</div>
It is at this point, in the hidden field tag, that I get this error:
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
Here are the 3 relevant controllers:
pages_controller.rb
class PagesController < ApplicationController
def home
#tales = Tale.all
end
end
tales_controller.rb
class TalesController < ApplicationController
respond_to :html, :js
def new
#tale = Tale.new
end
def show
#tale = Tale.find(params[:id])
end
def index
#tales = Tale.all
#tale = Tale.find(params[:id])
end
...
ratings_controller.rb
class RatingsController < ApplicationController
before_filter :authenticate_user!
respond_to :html, :js
def create
#tale = Tale.find_by_id(params[:tale_id])
#rating = Rating.new(params[:rating])
#rating.tale_id = #tale.id
#rating.user_id = current_user.id
if #rating.save
respond_to do |format|
format.html { redirect_to #tale, :notice => "Your rating has been saved" }
format.js
end
end
end
def update
#rating = current_user.ratings.find_by_tale_id(params[:tale_id])
#tale = #rating.tale
if #tale and #rating.update_attributes(params[:rating])
respond_to do |format|
format.html { redirect_to #tale, :notice => "Your rating has been updated" }
format.js
end
end
end
end
The problem is here somewhere. Somehow when rendering #tales on the home page, this invalidates the #tale.id on the _stars partial. I can not figure out how to solve this. Thank You.
ok, I think your value of #tales is nil so please do the following things and let me know what would be the result
first put raise #tales.Inspect in your home method in your PagesController
second <%= raise tale.inspect%> in _tale.html.erb.
want to check weather value of tale is null or not.

Resources