I am doing Hartl's tutorial and I want to make other users admins. Can I create a button that links to a action that updates the user's attributes to make them an admin?
<%= button_to "Make Admin", {action: "make_admin" }, method: :put %>
Users controller
def make_admin
update_attribute(:admin, true)
redirect_to users_url
end
routes.rb
put 'admin' => 'users#make_admin'
Had trouble referencing the right user. Any suggestions or a sure-fire way?
Thanks
Route is missing an :id. Change it to
put 'admin/:id' => 'users#make_admin', :as => "make_admin"
Also, for button_to:
<%= button_to "Make Admin", {action: "make_admin", id: current_user.id }, method: :put %>
and UsersController:
def make_admin
user = User.find params[:id]
user.update( :admin => true )
redirect_to users_url
end
Related
I’m using Rails 4.2.3. I have this in my controller file, “./app/controllers/users_controller.rb” …
def edit
#user = User.find(session["user_id"])
render 'edit'
end
def update
#user = User.find(session["user_id"])
if #user.update_attributes(user_params)
flash[:success] = "Profile updated"
end
render 'edit'
end
And I have this in my “./app/views/users/edit.html.erb” file
<%= form_for(#user) do |f| %>
…
<%= button_to "Save", { :action => "update" }, :method => :post, :class => 'button' %>
But when I visit my url “http://localhost:3000/users/edit”, I get this error
No route matches {:action=>"update", :controller=>"users"}
This is what I have in routes/config.rb so I’m not sure why its falling apart …
get "users/edit" => "users#edit"
resources :users
I believe you need to use PUT/PATCH method for the update action, while POST is used for the create action as per the Rails documentation:
<%= button_to "Save", { :controller => "users", :id => #user.id }, :method => :put, :class => 'button' %>
Also, rake routes is a really useful command for debugging routing issues that dumps all defined routes.
I'm using an application based on Devise, CanCanCan and Rolify to handle private resources.
Using Rolify (https://github.com/RolifyCommunity/rolify) to assign different roles to users.
I'd like to give access to a web manager who could then assign the multiple roles to users via a UI.
User Controller:
def update
#user = User.find(params[:user_id])
params[:user][:role_ids] ||= []
if #user.update_attributes(params[:user_id])
redirect_to users_path, :flash => { :success => 'User was successfully updated.' }
else
redirect_to users_path, :flash => { :error => 'User was unsuccesfully updated.' }
end
end
View:
Accessible via route:
get "users/:user_id/edit" => 'user#edit', :as => :edit_user
HTML:
<%= form_for #user do |f| %>
<% Role.all.each do |role| %>
<%= check_box_tag "user[role_ids][]", role.id, #user.role_ids.include?(role.id) %>
<%= role.name %><br />
<% end %>
<%= f.submit %>
<% end %>
Route:
match "users/:user_id" => 'user#show', via: [:get], :as => :user
However, when I click "Update User", I get the following error:
Any idea how I can fix this up to get my form working?
You have route to show action, accessible via get. You should also have a route to update action, accessible via patch. You can achieve this easily using resources:
resources :users, only: [:show, :update, :edit]
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)
I'm noob in Ruby on Rails and I have a dumb question:
in my session_controller I have
def create
user = User.find_by_email(params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to root_path, :notice => "Logged in!"
else
flash.now.alert = "Invalid email or password"
render "new"
end
end
in routes I have
match '/signin', to: 'sessions#new'
in new.html.haml I have
= simple_form_for :session do |f|
= f.input :email
= f.input :password
= f.button :submit, 'Sign in!'
When I press "Sign in" button, I expect that method "create" will be called (how it works in my user model), but debug shows me "new" method and I have "authenticity_token" withot filling email and password.
Could somebody explane me what heppens?
I don't understand when method "new" calls and then other methods.
This behavior has nothing to do with the simple_form. You don't specify an url for your action to be called, you don't pass any model to infer its path, so you'll end up with the url_for() method called on empty hash. The result of this calling is the current page, which is obviously is the same path where your form was displayed, but with the POST as the HTML-verb.
To call your sessions_path instead of your new_session_path you can do the following:
= simple_form_for :session, url: :sessions do |f|
Being processed through the url_for, it's effectively the same as specifying url: sessions_path but is making a magician out of you.
I don't use haml I use erb, but I suspect the work alike. In erb your form would need to call an action for example:
form_for :session, :url => {:action => "create"} do |f|
That would call the create method of your session controller. So I guess haml would be
simple_form_for :session, :url => {:action => "create"} do |f|
hope this helps
I have a model User that has_one user_profile and a User_Profile belongs_to user
in the User controller I have:
def personal
#user = User.find_by_id(params[:id])
#user_profile = #user.user_profile
#user_profile ||= #user.build_user_profile
end
def update_personal
#user = User.find_by_id(params[:id])
if #user.user_profile.update_attributes(params[:user_profile])
flash[:notice] = "OK"
redirect_to #user
else
flash[:notice] = "Fail"
render :action => 'update_personal'
end
end
In my personal.html.erb view I have:
<% semantic_form_for #user_profile, :url => { :action => "update_personal"} do |form| %>
<%= form.inputs %>
<%= form.buttons %>
<%end%>
And on the rountes I have:
map.resources :users, :member => {
:personal => :get,
:update_personal => :put
}
Now the strange thing is that I can do:
users/1/personal
to see the form but when I submit I get this error:
Unknown action
No action responded to 1.
It's trying to find an action with the name 1.
Can anyone point me out on the right direction?
I just got the problem again, and finally understood the problem and found the solution.
This time i was using an ajax call using getJason.
Because the call was a get, and in my routes I had a update_xxxxxx => :put,
the route was ignored and the default :controller/:action/:id was used.
I just had to put the update_xxxx => :get and the problem was solved.
Maybe this will help someone.