Ruby on Rails Page not reloading on submit button click - ruby-on-rails

I have an Approve button that changes status attribute of the Shop table record. When I click on it, it does change attribute, but it doesn't reload the page, so I have to reload page manually to see the result, which is very inconvenient. Looks like everything has to work, but page still not reloading.
My view has:
<%= form_for([:admin, #shop], remote: true, data: { confirm: "You sure?" }) do |fr| %>
<%= fr.hidden_field :status, :value => 2 %>
<%= fr.submit "Reject", class: "btn btn-large btn-danger" %>
<% end %>
And the controller:
def update
#shop = Shop.find(params[:id])
if #shop.update_attributes(shop_params)
flash[:success] = "Shop updated"
redirect_to([:admin, #shop])
else
render 'edit'
end
end
I would be grateful for any help, thank you!

You are using remote: true in form_for, which is making your form submission via AJAX.
You may need to add method: :put so that form hits action update instead of create.
So just try removing remote: true and add method: :put as follow and try submitting form again.
<%= form_for([:admin, #shop], method: :put, data: { confirm: "You sure?" }) do |fr| %>
<%= fr.hidden_field :status, :value => 2 %>
<%= fr.submit "Reject", class: "btn btn-large btn-danger" %>
<% end %>

maybe you are missing the respond_to do |format| calls or did you omitted them on the question?
should be like that:
def update
#shop = Shop.find(params[:id])
respond_to do |format|
if #shop.update(shop_params)
format.html { redirect_to [:admin, #shop], notice: "Shop updated"
else
format.html { render action: 'edit' }
end
end
end
hope that helps.

Related

How to set "approved" user attribute to true with a button in Rails

I have a user model established by Devise and it has a Boolean attribute "approved" with default value set to false.
I created a separate controller called "newcomers" where I set index action to display all not approved users and update action to set "approved" to true
class NewcomersController < ApplicationController
def index
#users = User.where("approved = ?", false)
end
def update
#user = User.find(params[:id])
#user.update_attribute :approved, true
respond_to do |format|
format.html { redirect_to newcomers_path, notice: 'Member was successfully approved!' }
end
end
end
So, in my view I did
<h1>Members Requests</h1>
<% #users.each do |user| %>
<%= user.email %>
<%= form_for user, url: newcomers_path, method: :patch do |f| %>
<%= f.submit "Approve" %>
<% end %>
<% end %>
and in my routes I have resources :newcomers
So, I do not know how to make the button work the way it should. Meaning it should just update the attribute "approved" and set it to true. and return to the same page (index)
Try following code
<h1>Members Requests</h1>
<% #users.each do |user| %>
<%= user.email %>
<% if user.approved %>
<%= link_to 'Unapprove', newcomer_path(user, approve: false), method: :put %>
<% else %>
<%= link_to 'Approve', newcomer_path(user, approve: true ), method: :put %>
<% end %>
controller
def update
#user = User.find(params[:id])
#user.update_attribute :approved, params[:approve]
respond_to do |format|
format.html { redirect_to newcomers_path, notice: 'Member was successfully approved!' }
end
end
Just use a link_to in your view an point it to the update action in your controller:
<%= link_to 'Approve', newcomer_path(user_id), method: :put %>
In your controller just update the user with the given id an redirect to index path as you already do.
If you want it somewhat more fancy you can add a remote: true to your link_to and respond with an js to delete only the affected row from your view.
Make below changes
In view
<%= form_for user, url: newcomer_path(user, approved: true), method: :patch do |f| %>
<%= f.submit "Approve" %>
<% end %>
and in controller
def update
if params[:user].nil?
#user = User.find(params[:id])
#user.update_attribute :approved, true
respond_to do |format|
format.html { redirect_to newcomers_path, notice: 'Member was successfully approved!' }
end
end
end
let me know if it is not working...

Using Ajax requests in rails

Hi I want to build an app using Ajax. Whenever a user visits an other user page he can add him as a friend by clicking add friend link. This is my current code in users/show page
<% if current_user.friend?(current_user,#user) %>
<%= link_to "Unfriend", relation_path(#relation), user: #user, method: :delete, data: { confirm: 'Are you sure? This action cannot be undone' }, class: 'btn btn-default' %>
<% elsif #user != current_user %>
<%= link_to "Add Friend", friendships_path(:friend_id => user), :method => :post, class: 'btn btn-default' %>
<% end %>
My code in relations controller
def create
if params[:friend_id]
if Relation.where(user_id: current_user.id, friend_id: params[:friend_id]).present?
redirect_to user_path(params[:friend_id]), notice: "Already friends"
elsif current_user.id == params[:friend_id]
redirect_to user_path(params[:friend_id]), alert: "Invalid Request"
else
#relation = current_user.relations.new(friend_id: params[:friend_id], subject: Constants::Subject::MAKE)
if #relation.save
friend = User.find(params[:friend_id])
friend.relations.create!(friend_id: current_user.id, subject: Constants::Subject::MAKE)
redirect_to user_path(params[:friend_id]), notice: "Added as friend"
else
redirect_to user_path(params[:friend_id]), alert: "Could not add as friend"
end
end
else
redirect_to current_user, notice: "Invalid Request"
end
end
I am following this Ryan Bates rails casts. How can I make the link_to add friend Ajax request instead of html request. The current code is working fine. I want to add Ajax functionality for this. I have seen a lot of questions but I could not understand what exactly to be done. Please help.
Add remote: true to the link_to tag. There is more information in the guides abou rails and ajax. You will need a respond_to block to handle the response.
Start with adding remote: true and use the console to see the call being made and what the response is. Then you can figure out how to handle the response.
<%= link_to "Add Friend", friendships_path(:friend_id => user), :method => :post, remote: true, class: 'btn btn-default' %>
Please take a look:
Move your buttons into a partial
Render it inside a div with ID = "actions"
Update your controller response with format js
Add field create.js.erb which render your buttons by javascript
Render your flashes box by javascript by the same way (if needed)
your view_file.erb
<div id="actions">
<%= render "views/realtions/actions", relation: #relation, friend: #user %>
</div>
views/realtions/_actions.html.erb
<% if current_user.friend?(current_user, friend) %>
<%= link_to "Unfriend", relation_path(relation), user: friend, method: :delete, remote: true, data: { confirm: 'Are you sure? This action cannot be undone' }, class: 'btn btn-default' %>
<% elsif friend != current_user %>
<%= link_to "Add Friend", friendships_path(friend_id: friend.id), method: :post, remote: true, class: 'btn btn-default' %>
<% end %>
views/realtions/create.js.erb
<%- if #friend.present? %>
$("#actions").html("<%= j render 'views/realtions/actions', relation: #relation, friend: #friend %>")
<%- end %>
// render your flashes to DOM here!
controllers/relations_controller.rb
def create
if params[:friend_id]
#friend = User.find(params[:friend_id])
if Relation.where(user_id: current_user.id, friend_id: #friend.id).present?
flash[:notice] = "Already friends"
elsif current_user.id == params[:friend_id]
flash[:error] = "Invalid Request"
else
#relation = current_user.relations.new(friend_id: params[:friend_id], subject: Constants::Subject::MAKE)
if #relation.save
#friend.relations.create!(friend_id: current_user.id, subject: Constants::Subject::MAKE)
flash[:notice] = "Added as friend"
else
flash[:error] = "Could not add as friend"
end
end
else
flash[:notice] = "Invalid Request"
end
respond_to do |format|
format.js
end
end
Hope this help

How to pass parameters with form_for to controller ruby on rails

I have a user model and a course model, and user can upload courses for themselves after they login.
However, I want admin to be able to upload for users to in case the user is not savvy enough.
My thought was to use the same create action for both user-upload and admin-upload, with an if statement.
The admin will select the user before he uploads for him in users/:id view page:
<%= link_to 'Upload Course for User', new_course_path(user_id: params[:id]), class: 'btn btn-primary' %>
Then I was able to see the create page with the parameter:
http://localhost:3000/courses/new?user_id=10
and I submit this form
<%= form_for(#course, html: {class: "form-group"}) do |f| %>
...
<%= f.submit "Create Course", class: 'btn btn-primary' %>
to the create action in the controller:
def create
#course = Course.new(course_params)
#course.user_id = params[:user_id] || current_user.id
if #course.save
redirect_to course_path(#course), notice: 'The course has been created successfully!'
else
render 'new'
end
However I'm never getting the user_id params, always just the current_user.id, which is the admin_user's id and that's not good.
How do I manage to pass in the user_id parameter to the controller create action so that it knows I'm trying to create for another user, not myself? Is there a better way to handle this than my logic?
Thanks!
You can try this.
in Form.
<%= form_for(#course, html: {class: "form-group"}) do |f| %>
<%= hidden_field_tag "course[user_id]", "#{#user_id}" %>
<%= f.submit "Create Course", class: 'btn btn-primary' %>
In controller create method.
def new
#user_id = params.has_key?("user_id") ? params[:user_id] | current_user.id
##OR
##user_id = params[:user_id] || current_user.id
end
def create
#course = Course.new(course_params)
## OR
##course.user_id = params[:user_id] || current_user.id
if #course.save
redirect_to course_path(#course), notice: 'The course has been created successfully!'
else
render 'new'
end
end
private
def course_params
params.require(:course).permit(:user_id)
end
<%= f.hidden_field :user_id, :value => params[:user_id] %>
So it will be passed as form element

Update a record with a button in Rails?

I'm trying to update a record in my Rails app using a button. I have a User and I want to update its school_id value. I have a School view page where a User can click on a button to add that school's id to the User school_id field. I'm struggling with the implementation. Here's what I have so far:
User controller:
def add_school
#user = User.find(params[:user_id])
#user.update_attributes(:school_id)
respond_to do |format|
flash[:notice] = "School has been added!"
format.html { redirect_to :back }
format.js
end
Button on School show page:
<%= button_to "Add School", add_school_user_path, :method => "put" %>
I tried to do this a different way by just adding code to the update action in the User controller but I couldn't get that to work either:
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:school_id])
flash[:notice] = "School has been added!"
redirect_to #user
end
if #user.update_attributes(params[:user])
flash[:notice] = "Successfully updated account and profile!"
end
end
What's the best way to pass the School's id into the User school_id column?
Thanks!!
EDIT 1: Routes
resources :users do
member do
get :following, :followers
put :add_school
end
Updated controller:
def add_school
#user = current_user
#school = School.find(params[:id])
#user.update_attributes(school_id: params[:school_id])
respond_to do |format|
flash[:notice] = "School has been added!"
redirect_to #user.school
end
end
Updated button link:
<%= button_to "Add School", add_school_user_path(#user, school_id: #school.id), :method => :put %>
Routing error:
No route matches {:action=>"add_school", :controller=>"users", :school_id=>1, :id=>nil}
You need a form for that instead of just abutton
<%= form_tag add_school_user_path(#user), method: put do -%>
<%= hidden_field_tag :school_id, #school.id -%>
<%= submit_tag 'Add school' -%>
<%- end -%>
you didn't provide the context code, maybe #user and #school are not the real variable names but you can get the idea from this
The provided answer is no longer entirely accurate. You can pass data and update a record with a button_to, so long as you aren't attempting to pass arbitrary data.
The button_to syntax would be something like this -- please note, this is my implementation of it, and it is not adjusted to your specific implementation as your controller would need additional adjustments from what you've specificed to accept certain params --:
<%= button_to "Mark Completed", todo_path(todo.id),
params: {:todo => { :id => todo.id, :completed => true, :user_id => current_user.id }},
method: :put, data: { confirm: "Mark this To-Do as being completed? This will hide it from view." } %>
You need to pass the whole hash into the call to .update_attributes.
Preferably, you will put school_id inside of user, so it will look like
# params[:user] = { school_id: 1 }
#user.update_attributes(params[:user])
Or you could code the school id manually
#user.update_attributes(school_id: params[:school_id])
Or, better yet, validate the association
#user.school = School.find(params[:school_id]
The path you would want is
user_add_school_path(#user, school_id: 1)
This is an old Q, but nevertheless for the sake of completeness. You do not necessarily need a form for a simple form-alike submission with a button/link. You can rely on jquery-ujs and data-params.
<%= link_to add_school_user_path(#user), class: "btn btn-xs btn-primary",
title: "Add school",
data: {remote: true, confirm: 'Are you sure?', method: 'put',
params: {user: {schoold_id: #school.id}}} do %>
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
Add school…
<% end %>
Note that you'd want to have school_params method in your controller akin to params.require(:user).permit(:school_id)

Rails: AJAX + destroy action in controller not working?

Hi I am currently making an app with users, albums, and photos. I managed to make the AJAX work for the create action when I upload pics, but I can't get AJAX to work for the delete. Instead, it redirects me to an empty show page for the pic. Can anyone give me some guidance?
photos controller:
def destroy
#user = User.find(params[:user_id])
#album = #user.albums.find(params[:album_id])
#photo = #album.photos.find(params[:id])
# #photo.destroy
flash[:success] = "Photo successfully deleted."
respond_to do |format|
if #photo.destroy
format.js
# format.json { render json: #photo, status: :created, location: #photo}
# redirect_to user_album_path(#user, #album)
end
end
end
destroy.js.erb (I'm supposed to have this right?)
$('.destroypicswrapper').remove(".<%= #photo.avatar.url %>");
_photodestroy.html.erb partial:
<div class="picthumb <%= photo.avatar.url %>">
<%= link_to image_tag(photo.avatar.url ? photo.avatar.url(:small) : #album.name), root_url %>
<br>
<%= link_to "Delete", user_album_photo_path(#user, #album, photo), :remote => true, method: :delete, data: { confirm: "Are you sure? "} %>
</div>
and finally the albums/edit.html.erb page where the delete is initially happening:
<% provide(:title, "Edit album") %>
<%= render 'form' %>
<div class="destroypicswrapper">
<% if #album.photos.any? %>
<%= render :partial => 'photodestroy', :collection => #album.photos, :as => :photo %>
<% end %>
</div>
I don't think you want to render the full url of an image as a class of a div. Also, your Jquery is wrong. Try something like this:
destroy.js.erb
$('.destroypicswrapper > #photo_<%= #photo.id %>').remove();
Adjust your _photodestroy.html.erb to:
<div class="picthumb" id="photo_<%= photo.id %>">

Resources