How to carry a variable from one page to another - ruby-on-rails

Kinda new to ruby, rails and devise but i'm trying to make a website where users(student) are enrolled in courses, which has its own unique id.
On my loggedin user home page I have a list that displays all courses the student is enrolled in, that pairs the student id to course id on the enrollment table.
<td><%= enrolment.course_id %></td>
<td><%= link_to "Complete Course", home_completeTask_path, class:"btn btn-dark" %></td>
The code I have in my for loop to fill the table of courses the student is enrolled in.
I would like to take enrolment.course_id value from here to home_completeTask where it is used to display the course modules and tasks.
In appllication controller
I have declared a variable:
#Cid
I havn't set it to anything as it would change depending on what the user clicks.
In Home controller
Both pages are in the home directory, and tried to define a method there.
def courseComplete(cid)
link_to "Complete Course", home_completeTask_path, class:"btn btn-dark"
#Cid = (cid)
end
This method didn't work and honestly I can't figure out another way to user that variable.
Any suggestions on this would be great, thanks.

You can pass any parameter as below.
<td><%= enrolment.course_id %></td>
<td><%= link_to "Complete Course", home_completeTask_path(course_id: enrolment.course_id), class:"btn btn-dark" %></td>
and in controllers method you will get same under params[:course_id].

Related

Rails resources routes miss parameters yet match documentation

Using Rails' resources directive, I have created a set of routes for a controller (contacts). I'm now editing the default views they come with to include some of my own content. However, the link_to method is failing, telling me that I'm missing a required parameter.
No route matches {:action => 'show', :controller => 'contacts', :id => nil} missing required keys [:id]
It's obvious why this is happening - the link_to method is not being supplied with an ID, instead it's getting nil. However, the code I'm using matches the documentation for link_to.
This is the view in question:
<% #contacts.each do |contact| %>
<tr>
<td><%= contact.first %></td>
<td><%= contact.last %></td>
<td><%= contact.title %></td>
<td><%= contact.city %></td>
<td><%= contact.phone %></td>
<td><%= contact.email %></td>
<td><%= link_to 'Show', contact %></td>
<td><%= link_to 'Edit', edit_contact_path(contact) %></td>
<td><%= link_to 'Delete', contact.id, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
#contacts is a set of contacts returned from the controller. The line that sets that is:
#contacts = Contact.select("title, first, last, city, phone, email")
.where("created_by" => #current_user.id)
The relevant content of the routes.rb file is simply resources :contacts.
The documentation states:
Because it relies on url_for, link_to supports both older-style controller/action/id arguments and newer RESTful routes. Current Rails style favors RESTful routes whenever possible, so base your application on resources and use [...]
link_to "Profile", #profile
This appears to be what I'm using with link_to 'Show', contact.
Why is the ID not getting passed to link_to?
What can I do to remedy this?
Change
Contact.select("title, first, last, city, phone, email")
to
Contact.select("title, first, last, city, phone, email, id")
the contact's id is nil because it isn't in the select query.
Also, although it doesn't seem to be causing problems right now, I would reccomend using an array of symbols instead of a comma-separated string, so that the sql query is more specific. For example:
Contact.select("title, first").to_sql #=> SELECT title, first FROM contacts
Contact.select(:title,:first).to_sql #=> SELECT "contacts"."title", "contacts"."first" FROM contacts
This way if you do a join with another model, it won't complain about the unspecific id in select. If you feel like you're typing too much, you can use the %i(...) syntax:
Contact.select(*%i(title first last city phone email))
Your code seems fine.
Maybe you have an instance in the #contacts array that is not saved and therefore, has no id?
Another way to put the same (again, your code is fine) would be:
= link_to 'Show', contact_path(contact)
I would suggest posting the routes file.

Ruby on Rails proper way to add a favorite button for front end

So far I have two tables User and Company. Users are able to favorite many companies. I established all the back end code to add favorites (a join table with many to many relationship) I also have a general setup to add favorites.
I need some help with the front end side though.
So far what I have is a search page where users can query a company ticker to get companies. I display it like the following
<% if #results %>
<h4>Search results for <%= #symbol %></h4>
<table>
<tr>
<th>ID</th>
<th>Symbol</th>
<th>Name</th>
</tr>
<% #results.each do |res| %>
<tr>
<td><%= res.id %></td>
<td><%= res.symbol %></td>
<td><%= res.name %></td>
<td><%= link_to "Favorite", create_favorite_path(current_user.id, res.id), method: :post, :remote => true %></td>
</tr>
<% end %>
</table>
<% end %>
Right now I have a "favorite button" implemented with
<td><%= link_to "Favorite", create_favorite_path(current_user.id, res.id), method: :post, :remote => true %></td>
It seems messy and I dont think this is right. I also want to add a few more features
I want to know if the post method was successful or not
Based on the post, I want to be able to change the button text to something like "saved"
later change the link to have a star button icon
I would love suggestions to improve this and do it properly
I prefer using a front-end framework to handle things like this. They allow the components to be much more dynamically interactive.
re: I want to know if the post method was successful or not
in the absence of a front-end framework you can catch failed save in the favorites_controller and add a flash[:error] to the page.
flash[:errors] = #favorite.errors.full_message unless #favorite.save!
re: Based on the post, I want to be able to change the button text to something like "saved"
You can use jQuery to change the button CSS on click of the favorite button.
<% if #results.favorited? %>
# render button with favorited class (with star)
<% else %>
# render button without favorited class (without star)
<% end %>

Ruby show associated asset data in table

I'm new to RoR, so please be gentile. I'm not sure, if I search for the right topic. However, I've spent the whole day trying to figure out, how to work with the has_man, belongs_to and so forth asset associations.
Right now I have two assets:
sqlite> pragma table_info(meetups);
0|id|INTEGER|1||1
1|name|varchar(255)|0||0
2|owner|integer|0||0
3|dateOfInception|datetime|0||0
4|homeTown|varchar(255)|0||0
5|created_at|datetime|0||0
6|updated_at|datetime|0||0
7|activity_id|integer|0||0
sqlite> pragma table_info(activities);
0|id|INTEGER|1||1
1|name|varchar(255)|0||0
2|location|varchar(255)|0||0
3|startDate|datetime|0||0
4|duration|integer|0||0
5|description|varchar(255)|0||0
6|created_at|datetime|0||0
7|updated_at|datetime|0||0
8|image|varchar(255)|0||0
9|meetup_id|integer|0||0
So I can create a new meetup and select multiple saved activities. For every meetup we can select a multiple activities. If I create a meetup, they corresponding activities are also stored correctly, as you can see in the image below:
Image
However, it's not useful to output them just like an array. It would be great, if the activity name would appear. But how is that possible? I tried so many things, renaming the db foreign keys, create a find method in the meetup controller... but nothing worked. Please help me out here - I think I'm very near but someting I dont know doesnt work.
<% #meetups.each do |meetup| %>
<tr>
<td><%= meetup.name %></td>
<td><%= meetup.owner %></td>
<td><%= meetup.dateOfInception %></td>
<td><%= meetup.homeTown %></td>
<td><%= meetup.activity_ids %></td>
<td><%= link_to 'Show', meetup %></td>
<td><%= link_to 'Edit', edit_meetup_path(meetup) %></td>
<td><%= link_to 'Destroy', meetup, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
class MeetupsController < ApplicationController
before_action :set_meetup, only: [:show, :edit, :update, :destroy]
# GET /meetups
# GET /meetups.json
def index
#meetups = Meetup.all
end
Many thanks for your help!
Try this in your view:
meetup.activities.map(&:name).join(',')
That should show the data you want. For performance reasons, you'll want to add .include(:activities) to
the controller action that loads your list of meetups.
It sounds like you're trying to model a Has And Belongs To Many relationship, though? You'll need a third table to model that correctly.
If that's not what you're wanting to model, you should remove the activity_id column from the meetups table.

Get ID of an element which is not accessible in the controller

On my project, I am displaying all the rows in the database of a model. However, I am doing this on the index page of another model. And I have a button associated with each row so that when clicked, it'd execute the related action on the associated model. I hope my question is clear enough.
To illustrate the problem, let's say I have two models: Teacher and Student. Every teacher has many students. And in the index page for each teacher, I display all his students as a list of rows. Now, I want to have a button for each row which will change the name of the student when clicked. It doesn't matter where I have the action. It might be in Teacher(or somewhere else). I just wanna find a way for how I will know which student is being clicked. Is it the first or second student whose button got clicked?
How can I do that?
Thank you very much in advance
Something like this?
<% students = Student.all %>
<% students.each do |student| %>
<tr>
<td><%= student.name %></td>
<td><%= link_to 'Change name', '#', onclick: 'alert("ID: "' + "#{student.id})" %></td>
</tr>
<% end %>

CRUD Ownership of Items/Microposts in Rails App

I have a simple rails app where users can create 'items', but on the master index page that lists all the items, there are 'Show, Edit, and Delete' links next to each 'item'. I understand that this is due to the fact that I used scaffolding to accomplish the items, but I'd like to make sure that people can only edit the ones that they created. This logic is a little above my head at the moment, as, like I've said before, am totally new to rails.
User Controller:
class UsersController < ApplicationController
def show
#user = User.find_by_username(params[:id])
end
def index
#user = User.find(:all)
end
end
Master Item View:
<div class="well">
<h1>All Items</h1>
<table>
<tr>
<th>Title</th>
<th>Details</th>
<th>Inquire</th>
<th></th>
<th></th>
<th></th>
</tr>
<% #items.each do |item| %>
<tr>
<td><%= link_to item.title, item_path(item) %></td>
<td><%= item.content %></td>
<td><%= mail_to item.email, "Inquire", :cc => "michaelomchenry#gmail.com",
:subject => "OverFlow Inquiry Regarding " + item.title %></td>
<td><%= link_to 'Show', item %></td>
<td><%= link_to 'Edit', edit_item_path(item) %></td>
<td><%= link_to 'Destroy', item, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New Item', new_item_path %>
</div>
Item Model:
class Item < ActiveRecord::Base
attr_accessible :content, :user_id, :title
validates :content, :length => { :maximum => 140 }
belongs_to :user
delegate :email, to: :user
end
There is a lot of stuff there. First of all, to be able to filter the items (or the actions) based on the user, you need to know who is logged at the time, and so enable users to login. This could be done for example using Devise, an authorization gem for Rails. Devise is largely used and well documented.
Once Devise is setup, you can check whether the user is logged (for example using a before_filter), and Devise will create a "current_user" variable for you to use (this is shown in Devise tutorial). You can then use it to filter your item lists with something like :
editable_items = current_user.items
And then use the editable_items on your view. I would advise you to go read the Devise tutorial as what you are doing is a quite common and well documented task.
I would comment if I could, but I feel that this must be said in reference to the answer posted by #momchenr (answering their own question) as a follow up to the chosen answer.
#momcher wrote:
I ended up doing this:
<% if item.email == current_user.email %>
and it worked... is that ok?
Probably not. But that depends on how your system is set up. If users can edit their email addresses and/or email addresses aren't forced to be unique, they may be able to gain editing access to another user's "items" by changing their email address temporarily or just signing up as a new user with a known user's email address.
Even if you never display email addresses of users in your application, there is an inherent vulnerability when you leave that much of the authentication process in a user-provided field.
Not knowing exactly how things are set up in Devise—only based on the info you have provided—I'd try the following:
These two might be are a touch slower depending on the state of ActiveRecord when called
<% if item.user == current_user %>
<% if item.user.id == current_user.id %>
This one ought to be a touch faster since you are not getting the user object from the item object (you are just pulling directly from the user_id method of the user object)
<% if item.user_id == current_user.id %>
No matter if I am right or wrong in my guesses at speed, this is generally a better solution than the one you said works for you. Since the user's ID is never under their control directly—unless there are major holes in your code—they cannot easily pose as other users.
I ended up doing this:
<% if item.email == current_user.email %>
and it worked... is that ok?

Resources