I have a Rails 5.0.2 app and I've managed to implement a user following system using the acts_as_follower gem. Everything works nicely, however, I'm running into some trouble adding ajax.
I'm getting the following error when clicking 'follow'
NoMethodError at /7/follow
==========================
> undefined method `followed_by?' for nil:NilClass
I have the following
users_controller.rb
def follow
user = User.find(params[:id])
current_user.follow(user)
respond_to do |format|
format.html { redirect_to user}
format.js
end
end
show.html.erb
...
<div id="follow">
<%= render partial: "users/following", locals: {user: #user} %>
</div>
...
_following.html.erb
<% if !#user.followed_by?(current_user) %>
<%= link_to follow_user_path(#user.id), remote: true do %>
<h4><span class="label label-primary">Follow</span></h4>
<% end %>
<% else %>
<%= link_to unfollow_user_path(#user.id) do %>
<h4><span class="label label-primary">Unfollow</span></h4>
<% end %>
<% end %>
I understand that I have no #user in my partial after creating the record and I can't work out how to pass it back in to the partial. Any help would be appreciated.
Silly me.
In the follow method I had this:
def follow
user = User.find(params[:id])
current_user.follow(user)
respond_to do |format|
format.html { redirect_to user}
format.js
end
end
but should have been
def follow
#user = User.find(params[:id])
current_user.follow(#user)
respond_to do |format|
format.html { redirect_to #user}
format.js
end
end
#user rather than user
your problem here is that in your controller you have user, without the "#" user is a variable that exist just in your controller method, and #user is an instance variable that can be accessed on the view.
So if you plan to use this on the view, you need to add "#" to the variable.
Related
I have created a cart in the products view and want to display an error message
views/products/index.html.erb
<% if #order.errors.any? %>
<div class="error error-success note-shadow">
<% #order.errors.full_messages.each do |msg| %>
<p><%= msg %></p>
<% end %>
</div>
<% end %>
controllers/orders_controller.rb
def create
#order = Order.new(params_slip)
respond_to do |format|
if #order.save
format.html {
redirect_to :back,
notice: 'Order was successfully placed.'
}
else
format.html { redirect_to :back }
end
end
end
I am using the above method trying to display the error messages, but it didn't work out. I supposed that is because my create action is in orders_controller, and I couldn't add the error message to the products view?
The root cause is the #order instance variable is not being carried through the redirection process, so that's the reason you don't see any error messages.
You can put the error messages into flash container
if #order.save
[do something]
else
flash[:order_errors] = #order.errors.full_messages
redirect_to :back
end
<% if flash[:order_error] %>
[display it here]
<% end %>
I'm not sure why you put your form in index.html.erb. You'd better put your form in your new.html.erb.
Try to change:
format.html { redirect_to :back }
Into:
render "index"
I hope this helps you
I am trying to implement the follower feature from Hartl's RoR tutorial, chapter 12.
I have the feature working in that I can login, go to another user profile, click follow and (after refreshing the page) I see I am now following them. Same with unfollowing.
However, my integration tests fail, the Ajax doesn't work, and I get this error in my Rails server log when I click follow or unfollow:
Rendered users/_follow.html.erb (1.7ms)
Rendered relationships/destroy.js.erb (2.5ms)
Completed 500 Internal Server Error in 17ms
NoMethodError - undefined method `id' for nil:NilClass:
My code matches Hartl's exactly (I think). However, I am using FriendlyID on my User model and Devise, one of which (likely FriendlyID) is causing problems.
I believe this is all the relevant code.
Any ideas would be much appreciated... now on hour 5 or so of this!
controllers/users_controller.rb
def following
#title = "Following"
#user = User.friendly.find(params[:id])
#users = #user.following
render 'show_follow'
end
def followers
#title = "Followers"
#user = User.friendly.find(params[:id])
#users = #user.followers
render 'show_follow'
end
controllers/relationships_controller.rb
def create
user = User.friendly.find(params[:followed_id])
current_user.follow(user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
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
models/user.rb
# follows a user
def follow(other_user)
active_relationships.create(followed_id: other_user.id)
end
# unfollows a user
def unfollow(other_user)
active_relationships.find_by(followed_id: other_user.id).destroy
end
# returns true if user is following the other user
def following?(other_user)
following.include?(other_user)
end
_unfollow.html.erb
<%= form_for(current_user.active_relationships.find_by(followed_id: #user.id),
html: { method: :delete }, remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn" %>
<% end %>
_follow.html.erb
<%= form_for(current_user.active_relationships.build(followed_id: #user.id), remote: true) do |f| %>
<div><%= hidden_field_tag :followed_id, #user.id %></div>
<%= f.submit "Follow", class: "btn" %>
<% end %>
In your relationships_controller.rb you haven't defined the #user variable, which is why you're receiving the undefined method error. Try this:
def create
#user = User.friendly.find(params[:followed_id])
current_user.follow(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
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
I am new to rails.I have some confusion about about rails object life cycle.In rails we have the bellow code.
class UsersController < ApplicationController
# GET /users
# GET /users.json
def index
#users = User.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #users }
end
end
# GET /users/1
# GET /users/1.json
def show
#user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #user }
end
end
# GET /users/new
# GET /users/new.json
def new
#user = User.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #user }
end
end
# GET /users/1/edit
def edit
#user = User.find(params[:id])
end
# POST /users
# POST /users.json
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render json: #user, status: :created, location: #user }
else
format.html { render action: "new" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PUT /users/1
# PUT /users/1.json
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
end
end
then in the form we have
<%= form_for(#user) do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
my confusion is in the new action in controller i have #user = User.new
and again in the create #user = User.new(params[:user]).
then in form i have <%= form_for(#user) do |f| %> .
My question is here at the form the #user object actually means waht?
I mean does this #user is going to hit the new action or create action.
If it is going to hit the create action then how this is happening because the form is actually comes from the new action so i can't figure it out how its hitting to the create action .
i know its very simple question.But i dont know how its happening as i am new to rails.
Please help me to make me understand the object flow.
thanks in advance.
The "new" action makes a new object and shows a form for editing it. That form submits to the "create" action because the object has not been saved yet.
If you did
form_for #user
and #user was a previously-saved object, the form would submit to the update action instead.
form_for is a bit magical, like a lot of rails: it does two things:
sets the "action" attribute of the form to point at either "/users" (for create) and "/users/:id" (for update)
in the case of update (ie for objects that already have an id) it also adds a hidden field which triggers the update action: this hidden field will look like this: <input type="hidden" value="put" name="_method">.
Have a look at form_for in your rails api.
It's hitting create action because of the proper form URL. When you run rake routes command, you'll see that POST /users leads to users#create action - and that's the URL in the new form. URL is set (and form fields are generated) properly by Rails because you pass User instance to the form.
I've been trying to edit the default scaffolding, and have been thus far quite successful. However, this little puzzle has managed to boggle me, as even reverting the file to it's original state isn't working. It's throwing up a "undefined method `model_name' for NilClass:Class" as the title suggests.
New Action In User Controller:
def new
if #current_user
redirect_to(action: 'home')
else
#user = User.new
end
respond_to do |format|
format.html # new.html.erb
format.json { render json: #user }
end
end
_form.html.erb beginning
<%= form_for(#user) do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
Any help would be appreciated!
In the case when #current_user is set, your new action doesn't stop executing after the redirect_to. Execution proceeds to the respond_to block, which attempts to render the page without setting #user, resulting in the error you're getting.
Possible solutions:
Use a before filter—Execution of the current action is halted if a before filter triggers a redirect. This is standard Rails practice.
before_filter :check_for_current_user, only: [:new]
def new
#user = User.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #user }
end
end
protected
def check_for_current_user
redirect_to(action: 'home') if #current_user
end
Just return early.
def new
if #current_user
redirect_to(action: 'home') and return
end
#user = User.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #user }
end
end
Cite: http://excid3.com/blog/execution-after-redirect-vulnerability
Here is my Edited details:
I have my controller like,
class Enr::Rds::SurvRdsapXrefsController < Enr::Controller
def index
#enr_rds_surv_rdsap_xrefs = Enr::Rds::SurvRdsapXref.paginate(page: params[:page])
end
def show
end
def new
#enr_rds_surv_rdsap_xref = Enr::Rds::SurvRdsapXref.new
end
def edit
#enr_rds_surv_rdsap_xref = Enr::Rds::SurvRdsapXref.find(params[:id])
end
def create
#enr_rds_surv_rdsap_xref = Enr::Rds::SurvRdsapXref.new(params[:enr_rds_surv_rdsap_xref])
respond_to do |format|
if #enr_rds_surv_rdsap_xref.save
format.html { redirect_to :enr_rds_surv_rdsap_xrefs, notice: "Survey link was successfully created." }
format.js
format.json { render json: #enr_rds_surv_rdsap_xref, status: :created, location: #enr_rds_surv_rdsap_xref }
else
format.html { render action: "new" }
format.js
format.json { render json: #enr_rds_surv_rdsap_xref.errors, status: :unprocessable_entity }
end
end
end
def update
end
def destroy
end
end
Here is my view form like
<%= form_for(#enr_rds_surv_rdsap_xref, :remote => true) do |f| %>
<% if #enr_rds_surv_rdsap_xref.errors.any? %>
<div id="error_explanation">
<div class="validate">
The form contains <%= pluralize#enr_rds_surv_rdsap_xref.errors.count, "error") %>.
</div>
<ul>
<% #enr_rds_surv_rdsap_xref.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="control-group">
<%= f.label :section %><br />
<%= f.text_field :section %>
</div>
<%= f.submit %>
<% end %>
When i click the index page to create a new link, the index page showing error like
NoMethodError in Enr/rds/surv_rdsap_xrefs#index
undefined method `errors' for nil:NilClass
Thanks for the suppport and please suggest me to rectify the error. I am new to ROR. Thanks
Your error reveals that the rendering of the index template is causing the error, which means you're rendering the form for the new survey (the code snippet above) in the index template. This is fine, but if you're going to do that, you'll have to instantiate a new survey in index, as well as in new.
At the simplest, you could just copy the code in new to index:
def index
#enr_rds_surv_rdsap_xrefs = Enr::Rds::SurvRdsapXref.paginate(page: params[:page])
#enr_rds_surv_rdsap_xref = Enr::Rds::SurvRdsapXref.new
end
def new
#enr_rds_surv_rdsap_xref = Enr::Rds::SurvRdsapXref.new
end
To keep your code a bit DRYer you might change where the new instance is created. A pattern you'll often see is something similar to:
before_filter :build_record, :only => [:new, :index]
protected
def build_record
#survey = YourSurvey.new
end
This way you don't even need to write the new/index methods if you don't have any other logic.
Do you also set #survey in the new action in your controller? The error means that when the view is rendered #survey is nil, so there must be a problem with setting that instance variable.
Do you get the error when you go to the 'new' view or when you try to submit the form (create)?
The form contains <%= pluralize#enr_rds_surv_rdsap_xref.errors.count, "error") %>
This line of the code is the problem. You are lacking a "(" between the pluralize and the #enr...
Explained: RoR thinks that the object is: pluralize#enr... instead of the # All alone, and he has no errors for this kind of object.