Rails newbie here. I have an array of hashes that contain Facebook Friends that I'd like to optionally turn into 'Contacts'. I have an index view that lists all of the users's 'friends'. I'd like to have a custom button that enables the user to turn each friend into a contact. How do I do this in Rails?
Index view - I am currently listing each user with their avatar & name. I'd like to add the button in each list item.
Note: I do not have a Friend model, as I am simply pulling this data in from the Facebook Graph API as an array of hashes.
<% #friends.each do |friend|%>
<li> <%= image_tag(fb_avatar(friend["id"], "type=square"))%> <%=friend["name"]%> #put button here </li>
<% end %>
Custom make_friend_contact method in Application Helper (to be called on a friend):
def make_friend_contact
Contact.new(name: self["name"], uid: self["id"], avatar_url: fb_avatar(self["id"], "type=square"), user_id: params[:user])
end
Any help is much appreciated. I've done quite a bit of reading, and I can't seem to crack this one. Thanks!
One solution might be to use button_to. You can check it out in the Rails API. Here is one of their examples:
<%= button_to [:make_happy, #user] do %>
Make happy <strong><%= #user.name %></strong>
<% end %>
# => "<form method="post" action="/users/1/make_happy" class="button_to">
# <div>
# <button type="submit">
# Make happy <strong><%= #user.name %></strong>
# </button>
# </div>
# </form>"
where the button calls the make_happy action in the Users controller on #user.
You could do something similar by making an action in your Users controller that creates a new Contact, using a friend parameter.
def make_friend_contact
friend = params[:friend]
Contact.new(name: friend["name"]...
end
Then you just have to send the friend parameter with the button's POST request.
Related
I am very novice at Ruby and Ruby on Rails.
I am trying to update a web application that has signed up volunteers that require approval before they can access full website functionality. I added a boolean field to the volunteers database model called :approved that defaults to false when a volunteer signs up, and requires a logged in administrator to update it to true.
I created an administrator class in my project that can view a list of pending volunteers from the controller:
def view_pending_volunteers
#navbar = true
#volunteers = Volunteer.where(approved: false)
end
In the administrator view I want to use checkboxes associated with volunteer, which when submitted will allow the administrator to update the :approved field in the volunteer table.
I have several issues that are not clear to accomplish this task:
In my administrator model I use has_many :volunteers with a migration that put the volunteer_id as a foreign key in the administrator database table. Is that sufficient to accomplish the task at hand, or do I need to create a join table for :approved? I can't have volunteers belong_to :administrators because they would not be able to sign up on their own, they need to be created by administrators.
I am not sure exactly how to configure the code for checkbox helpers in my administrator view. I am using form_with but I am sure my code is not correct. I would like to pass an array of parameters for each check_box associated with the :approved field for the list of pending volunteers back to the controller.
<p><b style="color:blue;font-size:24px;">
<%= form_with(model: #volunteer, local: true) do |f| %>
<% #volunteers.each do |v| %>
<li>
Volunteer: <%= x.first_name%> <%= x.last_name%> Age: <%= x.age%> Description: <%= x.description%>
<%= f.check_box (#volunteers, v.approved, options = {}, checked_value = "1", unchecked_value = "0")%>
</li>
<% end %>
<%= f.submit "Approve" %>
<% end %>
</b></p>
I am not exactly sure how to handle the array of checkbox values that get returned to the administrator controller in order to update the volunteer database table. Do I need to create a hash in the view (how to do that?) and then loop through the hash to update_attribute(:approved, true) for each checked volunteer? I have created an update_pending_volunteers method in the administrator controller for the POST operation, but am unclear on the code that should be there because I am unsure the checkbox approach.
Thanks in advance for your patience with a newbie. This seems like such a simple thing to do but I am not sure of the proper approach. I have spent quite a bit of time reviewing APIs and videos and stack overflow articles but cannot seem to piece together information that will give me confidence in a particular approach to do this correctly. Again it seems like such a simple thing to accomplish but has become a source of frustration.
See the comment from Rockwell Rice. Don't create a relationship of any kind for this functionality.
Use the URL feature of form_with, not model. You're not acting on one volunteer, you're acting on many. Create a post route (ie. approve_volunteers). In the view you would create the checkboxes like this:
<%= form_with(url: approve_volunteers_path, local: true) do |f| %>
<% #volunteers.each do |v| %>
<div class="field">
<label class="checkbox">
Volunteer: <%= x.first_name%> <%= x.last_name%> Age: <%= x.age%> Description: <%= x.description%>
<input type="checkbox" name="volunteers[]" value="<%= v.id %>">
</label>
</div>
<% end %>
<%= f.submit "Approve" %>
<% end %>
That should send params through the form like {"volunteers" => ["1", "3"]} and leave the rest empty. You might have to play around with those a little. Check your console for the params.
Then in your controller something like:
def approve_volunteers
volunteer_ids = []
volunteers = Volunteer.where(approved: false)
volunteers.each do |v|
if v.id.in?(params[:volunteers])
volunteer_ids << v.id
end
end
Volunteer.where('id IN (?)', volunteer_ids).update(approved: true)
end
See above.
The checkbox code provided by Sam worked perfectly. My url for the view is "update_pending_volunteers_path." I need to improve the formatting a little bit.
The code in the controller that worked to loop through the array of volunteer ids that was passed back into the controller is as below:
def view_pending_volunteers
#navbar = true
#volunteers = Volunteer.where(approved: false)
end
def update_pending_volunteers
#navbar = true
params[:volunteers].each do |value|
Volunteer.find(Integer(value)).update(approved: true)
end
redirect_to (administrator_dashboard_path)
end
The volunteers passed into the view have already been parsed to just those that have not been approved, so the volunteer_ids returned as checked are only from that list.
I have a notification system in my rails app. On my notifications model I have:
message
user_Id
read
link_path
The following code works great for showing me the notifications for the current user, and then showing me the notifications that are read. I'm looping through each of these records where this criteria is true, and then doing a link_to #link do, and then outputting the whole code.
Basically the whole block I can then click on and it will take me to the proper record. That works like a charm.
The default for all new notifications is :read => false.
However, when user clicks on the link, I'm trying to pass :read => true into that record, so that when I come back that particular notification will no longer show, since it's only showing me :read => false notifications.
What is the easiest way to go about this? I've tried wrapping everything in a form_for and trying to pass this value of :read => true into the record, but I can't get that to work. Thoughts?
Controller
#x = Notification.where(:user_id => current_user, :read => false)
View
<% #x.where(:user_id => current_user).each do |notify| %>
<% #link = notify.link_path %>
<%= link_to #link do %>
<div class="row notifyrow">
<div class="col-sm-7">
<p> <%= notify.message %></p>
</div>
<div class="col-sm-3">
<p> <%= time_ago_in_words(notify.created_at )%> ago</p>
</div>
</div>
<% end %>
<% end %>
What you seem to want to do is to update the read attribute on a particular Notification when the user clicks the link. That's absolutely what a Controller method is for. For example, assuming the route for your notify_link is something akin to get '/notifications/:id', to: 'notifications#show', you'd do the following:
class NotificationsController < ApplicationController
...
def show
#notice = Notification.find(params[:id])
#notice.update!(read: true)
end
end
That updates the read attribute on the record, so when you go back to the main view it will no longer appear in your unread list.
By the way, in your controller you run a query to get all the unread notifications for the current user, and then run where() again in your view. It should be sufficient to just do #x.each in your view.
EDIT
To summarise the comments discussion below, since the linked path doesn't include the Notification object ID, you just need to include it in the query parameters. The Rails-generated URL helpers take a hash (following any parameters required to complete the path) and includes them in the query string. So, something like:
national_race_path(#national_race.id, notify_id: notify.id)
will append the ID as <whatever_path>?notify_id=1234 and it will be accessible in the controller via params[:notify_id]. You'll need to handle what happens if no or invalid ID is passed, etc., but that should give you what you need.
I've been struggling to get this to work following a tutorial. I've got Users that have profiles, and a Client model that, through a 'many to many' join table, establishes the relationships between the user and the clients.
What I'm trying to do is create a list of check boxes generated from the list of clients in the DB that you can tick on or off, and then when you submit it, the user will have the relationship to those clients through the join table.
It's sort of working with static data as you can see below:
/profiles/show.html.erb
<% #clients.all.each do |client| %>
<li>
<%= check_box_tag "user[client_ids][]", client.id %>
<%= client.client_name %>
</li>
<% end %>
<%= link_to 'Add Clients', '../assign_clients/' + #profile.user.id.to_s , class: 'btn btn-default' %>
Routes
get 'assign_clients/:id', to: 'users#assign_clients'
And finally in my users_controller.erb
def assign_clients
#user = User.find(params[:id])
#user.client_ids = [1,2]
redirect_to :back, alert: 'Assigned Users'
end
Obviously it's just using hard coded values of 1 and 2. What I'm not sure how to do is wrap the checkboxes in the correct form tag/simple_form (which I am using), and then with the 'submit' button, have that do the 'assign_clients' action that passes through the values.
Thank you for any help.
What I'm not sure how to do is wrap the checkboxes in the correct form
tag/simple_form (which I am using), and then with the 'submit' button,
have that do the 'assign_clients' action that passes through the
values.
In order to create a form that will trigger the assign_clients method a route needs to be setup in your routes.rb file like the following:
resources :users do
patch 'assign_clients', to: 'users#assign_clients', as: 'assign_clients'
end
This sets up a route for a user that you can use the http patch method with (ie. UPDATE). The plan is to pass the client_ids to the users controller as params from the form. I gave it a path name so that we can reference it in the form as user_assign_clients_path(:user_id)
Now that we have the route set up...using the default rails form tags you can structure the form along the lines of this:
<%= form_for #user, url: user_assign_clients_path(#user) do |f| %>
<% #clients.each do |client| %>
<li>
<%= check_box_tag "user[client_ids][]", client.id, #user.clients.include?(client) %>
<%= client.client_name %>
</li>
<% end %>
<%= f.submit "Add Clients", class: "btn btn-default" %>
<% end %>
This will create a form allowing you to post the selected clients as an array of ids to the assign_clients method.
Finally, the assign_clients method can then retrieve the client_ids from the params hash (via params[:user][:client_ids] most likely) and update the user instance (retrieved using user_id from params hash also). You will probably have to add client_ids: [] to the end of your strong parameters list for user to whitelist it - but this essentially should behave like a typical update method.
def assign_clients
#user = User.find(params[:user_id])
#user.update(user_params)
redirect_to wherever_path
end
def user_params
params.require(:user).permit(
client_ids: []
)
end
You need to understand several basic concepts, let me explain to you:
on: member routing - in order to solve your issue directly, your route should be something like:
resources :users do
post '/assign_clients/:client_id', on: :member
end
so that other than user_id, the :client_id can be also passed in as a parameter. For the details, you can read about rails guides on routing.
For the checkbox way, you need nested_attributes - http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html. So that you can achieve what u need with a simple update call on users.
You can also implement a customised logic, with the client_ids passed in as parameters. In order to learn how forms & parameters work in rails, you can build a form, submit it, and see how it goes in the rails server log.
If anything is unclear, simply comment below & I'll try to update.
My entire code :
<% query.inline_columns.each do|column| %>
<% if column.css_classes.to_s != "assigned_to" %>
<td class="<%= column.css_classes %>"> <%= column_content(column, issue) %> </td>
<% else %>
<td class="<%= column.css_classes %>"> <%= test = column_content(column, issue) %> </td>
<% end %>
<% end %>
I have something like that:
test = column_content(column, issue)
and when i go on the website it give me something like that:
<a class="user active" href="/users/5">Test</a>
My question is how can I get the value of href ?
I tried test.href, test.link_to and test.link but don't work.
And after when we have the href it's possible to only have the id in href ? (In the href above it's 5)
BUT I don't want to go on page and get the id, I just want to have it so I can load the picture of user in the table.
I'm beginner in ERB language, thank's for help !
EDIT:
My solution to get the id :
test.to_s.split("href=\"").last.to_s.split("\"").first.to_s.split("/").last.to_s
Thank's guy to try to help me !
The Request cycle:
In Rails and in MVC every request follows a cycle:
Let's say you type in http://localhost:3000/users.
The request hits your Rails server and goes through Rack to your routes.
Rails picks a controller and action which matches the request.
Rails runs your UsersController#index and renders the view.
The rendered html is sent back to the client.
So why am I telling you this?
It has nothing to do with ERB.
You simply render the view and send it to the client - all done. The client can interact by clicking links or submitting forms. But it's not your actual view communicating back.
When the user clicks the link it starts a whole new request - it's a whole new process*.
Routes & Params
Routes are kind of like regular expressions - with superpowers.
If you want your rails app to handle the request to /users/1 you need to create a route:
# config/routes.rb
get `/users/:id`, to: 'users#show'
See the :id part? That means we can get the ID passed in the url from params[:id].
class UsersController
def show
#user = User.find(params[:id])
end
end
Of course writing your routes like that is pretty tedious. So instead we write:
resources :users
Try running rake routes from the console to see what it does.
I'm working on simple contact manager that supports multi-user. I'm using with Rails, Device, and MongoDB with MongoID.
With devise, I easily attached basic login functionality with devise, and used embedded_in for attaching contact model to user model.
However, I can't make user's dashboard page(and RESTful API endpoint) that displays user's contact list. I should make every users' contact list private to each user.
EDIT : I followed RailsApp tutorial, and this is what I've done so far. I have index page that displays every users' list, and detail view for adding contact data.
The problem is, when user sign up, every user can see everyone's contact. I want to restrict every user should only see their contact list.
And one more thing, I want to unify API endpoint for every user like:
http://domain.tld/contact.json for logged in user's contact.
Devise will give you this helper current_user. So you can do this in your controller.
# dashboard_controller.rb
before_filter :authenticate_user!
def index
#contacts = current_user.contacts
end
Then in your view
# dashboard/index.html.erb
<% #contacts.each do |contact| %>
<p>
<strong><%= contact.name %></strong> <br />
Phone: <%= contact.phone %>
Mobile: <%= contact.mobile %>
Email: <%= contact.email %>
</p>
<% end %>
Is that what you're after?