Rails Admin Devise - How to edit other users? - ruby-on-rails

I have created a boolean on devise User to determine admins. Now that I have that, I have a list of Users. I want to make other users admins as well, so I put in Edit links, but they just keep linking to my own profile. Do I HAVE to use a gem like CanCan, or is there a way I can do this just with the boolean on a User?
admin_view.html.erb
<div>
<h1>Admin View</h1>
<table>
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Native Language</th>
<th>Learning Language</th>
<th>Admin?</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #users.each do |user| %>
<tr>
<td><%= user.first_name %></td>
<td><%= user.last_name %></td>
<td><%#= user.meeting_time %></td>
<td><%= user.admin %></td>
<td><%= %></td>
<td><%= %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<% end %>
</tr>
</tbody>
</table>
edit view
<h2>Edit <%= resource_name.to_s.humanize %></h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :first_name %>
<%= f.text_field :first_name, autofocus: true %>
</div>
<div class="field">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password, autocomplete: "off" %>
</div>
<div class="form-group">
<%= f.label :admin %>
<%= f.check_box :admin %>
</div>
<div class="actions">
<%= f.submit "Update" %>
</div>
<% end %>
Still very new to rails, so please let me know if I need to post anything else. Thanks!
UPDATE
profiler_controller.rb
def admin_view
#users = User.all
end

This is a case for authorization (whether a user has permission).
As you've rightly stated, you can use CanCanCan (CanCan is no longer maintained) to do this, although there are many similar gems such as Pundit etc.
If using CanCanCan, I would use the following:
#config/routes.rb
resources :users do
post :admin #-> url.com/users/:user_id/admin
end
#app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.admin?
can :manage, :user
end
end
end
This will allow you to use:
#app/views/admin/users/index.html.erb
<% #users.each do |user| %>
<tr>
<td><%= user.first_name %></td>
<td><%= user.last_name %></td>
<td><%= user.admin %></td>
<td><%= link_to "Admin?", user_admin_path(user), method: :post if can? :manage, user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
</tr>
<% end %>
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def admin
#user = User.find params[:user_id]
#user.toggle :admin if can? :manage, #user
redirect_to #user
end
end
I can provide more if required; this should answer your question though.

Related

checkboxs in a table created via form_for

I'm new to RoR so apologies if the answer is super simple. I'm trying to create a table that allows users to select other users that can collaborate on a wiki. The issue I'm having is that no matter which checkbox you select on the table. It only toggles the topmost option.
here is the code in question:
<%= form_for [#wiki, #wiki.collaborators.build] do |f| %>
<table class="bordered hoverable">
<tbody>
<% #users.each do |user| %>
<tr>
<td><%= user.name %></td>
<td class="right-align"><%= f.check_box :user_id %><%= f.label :user_id, "Give Access" %></td>
</tr>
<% end %>
</tbody>
</table><br /><br />
the controller values in new
def new
#wiki = Wiki.find(params[:wiki_id])
#collaborator = Collaborator.new
#users = (User.all - [current_user])
end
The problem here is that through check_box's you can't get more than one user selected. In order to select multiple data, you need to use f.collection_select.
Here's how:
<%= f.collection_select :user_id, #users, :id, :name, {prompt: "Please select collaborators"}, {multiple: true} %>
To select multiple the the name of the checkbox should not be :user but contain the user id. Try something like that:
<%= form_for [#wiki, #wiki.collaborators.build] do |f| %>
<%= f.fields_for :collaborators do |c| %>
<table class="bordered hoverable">
<tbody>
<% #users.each do |user| %>
<tr>
<td><%= user.name %></td>
<td class="right-align"><%= c.check_box user.id %><%= f.label user.id, "Give Access" %></td>
</tr>
<% end %>
</tbody>
</table><br /><br />
<% end %>
<% end %>
The controller would then recieve params like that:
{:collaborators => {1 => '0', 2 => '1'}
showing that user with id 1 was not checked, user with id 2 was checked

Form with route direction does not work

I have a form set up with the following code:
<h2>Add collaborators to the wiki </h2>
<table>
<tr>
<th>Name</th>
<th>Email</th>
<th>Give Access</th>
</tr>
<tr>
<%= form_for (#collaboration) do |f| %>
<% #users.each do |user| %>
<td><%= user.name %></td>
<td><%= user.email %></td>
<td> <%= f.collection_select :user_id, User.all, :id, :name, prompt: true %> </td>
</tr>
<%= f.submit %>
<% end %>
</table>
<%= f.submit %>
<% end %>
And my routes are set up like this:
resources :wikis do
resources :collaborations
end
And in my controller I defined my variables like this:
def new
#wiki = Wiki.find(params[:wiki_id])
#collaboration = #wiki.collaborations.new
end
But when I visit the page clicking on a link I created
<%= link_to 'Add Collaborator', new_wiki_collaboration_path(#wiki) %>
I still get this error:
undefined method `collaborations_path' for #<#<Class:0x007f8b6a5a8a00>:0x007f8b67820c90>
Any thoughts on what goes wrong here?
Your form here just goes to collaboration_path which you've not defined.
<%= form_for (#collaboration) do |f| %>
<% end %>
You need to include the wiki
<%= form_for ([#wiki, #collaboration]) do |f| %>
<% end %>

How to setup the actions with considering database design of rails3

Assume you have the model called 'Topic' as a parent, and 'Comment' as a child.
On the url 'topics/show/35' you can see all the comments that belongs to this topic ID#35.
When logged-in user want to post his new comment at this page,
should I write 'comment_create' action in topics_controller.rb?
or just write 'create' action in comments_controller.rb, and call it from this page?
Which one is regular way??
If I call 'create' action in comments_controller, how can I write in view to pass
'Model name' to add comments into
'Models ID#'
'comment body'
or should I just write actions separately like this?
controllers/comments_controller.rb
def create_in_topic
code here! to add new comment record that belongs to topic....
end
def create_in_user
code here! to add new comment record that belongs to user....
end
for your information, comment adding action should be something like this.
def create
#topic = Topic.find(params[:topics][:id] )
#user_who_commented = current_user
#comment = Comment.build_from( #topic, #user_who_commented.id, params[:topics][:body] )
#comment.save
redirect_to :back
flash[:notice] = "comment added!"
end
Example Updated!!!
views/topics/show.html.erb
<table>
<tr>
<th>ID</th>
<th>Title</th>
<th>Body</th>
<th>Subject</th>
<th>Posted by</th>
<th>Delete</th>
</tr>
<% #topic.comment_threads.each do |comment| %>
<tr>
<td><%= comment.id %></td>
<td><%= comment.title %></td>
<td><%= comment.body %></td>
<td><%= comment.subject %></td>
<td><%= comment.user.user_profile.nickname if comment.user.user_profile %></td>
<td> **Comment destroy method needed here!!!** </td>
</tr>
<% end %>
</table>
<%=form_for :topics, url: url_for( :controller => :topics, :action => :add_comment ) do |f| %>
<div class="field">
<%= f.label :'comment' %><br />
<%= f.text_field :body %>
</div>
<%= f.hidden_field :id, :value => #topic.id %>
<div class="actions">
<%= f.submit %>
<% end %>
controllers/topics_controller.rb
def add_comment
#topic = Topic.find(params[:topics][:id] )
#user_who_commented = current_user
#comment = Comment.build_from( #topic, #user_who_commented.id, params[:topics][:body] )
#comment.save
redirect_to :back
flash[:notice] = "comment added!"
end
I think the most straight forward implementation it's going to be an action (ie: add_comment) in your Topic Controller. Once the view call the TopicController#add_comment action you will have all your Topic information and also the comment data so you can easily add the comment to the Topic from there.
Let me know if you need further help.
FedeX
Well I'm not to sure because that gem, but you could try something like this:
<%=form_for #topic, url: url_for( :controller => :topics, :action => :add_comment ) do |f| %>
<table>
<tr>
<th>ID</th>
<th>Title</th>
<th>Body</th>
<th>Subject</th>
<th>Posted by</th>
<th>Delete</th>
</tr>
<% #topic.comment_threads.each do |comment| %>
<%= f.fields_for :comment_threads, comment do |comment_form| %>
<tr>
<td><%= comment.id %></td>
<td><%= comment.title %></td>
<td><%= comment.body %></td>
<td><%= comment.subject %></td>
<td><%= comment.user.user_profile.nickname if comment.user.user_profile %></td>
<td>Delete? <%= comment_form.check_box :_destroy %></td>
</tr>
<% end %>
<% end %>
</table>
<div class="field">
<%= f.label :'comment' %><br />
<%= f.text_field :body %>
</div>
<%= f.hidden_field :id, :value => #topic.id %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Let me know if it helps you! FedeX

authlogic and posts for current_user

I am using authlogic for users to login and once they do so, I would like them to be able to add posts. For some reason I keep getting "Couldn't find User without an ID". Below is my code:
posts controller
def create
#user = User.find(params[:user_id])
#post = #user.posts.create(params[:post])
redirect_to current_user_path(#current_user)
end
show page
<% #user.posts.each do |post| %>
<tr>
<td><%= post.postName %></td>
<td><%= post.body %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %> </td>
</tr>
<% end %>
</table>
<br />
<h2>Add a Post:</h2>
<%= form_for([#current_user, #user.posts.build]) do |f| %>
<div class="field">
<%= f.label :body %><br />
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I know it has something to do with current user, but I cannot get this working! Any help is greatly appreciated!
First, you should use current_user not #current_user
Second, you're doing #user = User.find(params[:user_id]) but I don't understand why you expect to have something like :user_id in your params. That's why you get that "Couldn't find User without an ID" error.

Rails 3 submit a form with multiple records

I'm new to rails so this is probably a basic question. I am trying to create a form where the user can create 3 records at once. I want the user to only have to click the submit button once. I'm submitting to my Review model a name, comment, and rating. Currently, only the last record is entered into the database.
<%= form_for([#user,#review]) do |f| %>
<table>
<tr>
<td>Rank</td>
<td>Name</td>
<td>Comment</td>
</tr>
<tr>
<td>1</td>
<td><%= f.text_field :name %></td>
<td><%= f.text_field :comment %></td>
<%= f.hidden_field :rating, :value=> "5" %>
</tr>
<tr>
<td>2</td>
<td><%= f.text_field :name %></td>
<td><%= f.text_field :comment %></td>
<%= f.hidden_field :rating, :value=> "3" %>
</tr>
<tr>
<td>3</td>
<td><%= f.text_field :name %></td>
<td><%= f.text_field :comment %></td>
<%= f.hidden_field :rating, :value=> "1" %>
</tr>
</table>
<div class="actions">
<%= f.submit "Create my top 3" %>
</div>
<% end %>
Any advice is appreciated. Thanks.
I would recommend using fields_for for this:
<%= form_for([#user, :reviews]) do |f| %>
<% #reviews.each do |review| %>
<%= fields_for review do |r| %>
<%= render "reviews/form", :r => r %>
<% end %>
<% end %>
<% end %>
To make this work, you will need to build as many review objects as you require in your controller:
def new
# you could also have this in a before_filter...
#user = User.find(params[:id])
#reviews = Array.new(3) { #user.reviews.build }
end
This would create new instances of review records for this user, which is different from new records. Instances are simply Ruby objects. Now because you've called #user.reviews.build three times, you'll see three reviews in your view.
def create
#user = User.find(params[:id])
#reviews = Review.create(params[:reviews])
# Some more logic for validating the parameters passed in
end
This will create three new Review objects and link them to #user, assuming all three are valid.
You'll need to tell rails its an array. First, read this section of this article:
For your purpose, you'll need to build the form by hand:
<%= form_tag 'foo' do %>
<% [1,3,5].each do |i| %>
<%= text_field_tag 'review[][name]' %>
<%= text_field_tag 'review[][comment]' %>
<%= hidden_field_tag 'review[][rating]', :value => i %>
<% end %>
<% end %>

Resources