How to query two tables from database in one controller - ruby-on-rails

I have two tables which are one to many (1 challenge to many entry)
I want to get the last entry for all challenges but I also want to get the title of the challenge for that last entry.
So far I have:
def index
#discovers = Challenge.all.map{|c| c.entries.last}
end
How to I also add the fact I want the Challenge.title?

def index
#challenges = Challenge.all
end
Then inside your view
<% #challenges.each do |challenge| %>
<%= challenge.title %> # will give you challenge title
<%= challenge.entries.last %> # will give you last entry for the challnge
<% end %>

Related

How to retrieve and output the last record by foreign id?

I have 2 Models in my application. Project & Note. A project has_many notes. This all works great but on the projects index page.html.erb I would like to show the last note for a project.
My question is how do I retrieve this and then display it, on the index screen?
You can get the last note using project.notes.last. In your view, add below :
<% projects.each do |project| %>
<% last_note = project.notes.last %>
<%= last_note.note unless last_note.nil? %> # get last note per project if it exists
<% end %>

How do you recurse if statements

Im trying to make a category system with parents. Here is how my database is structured.
- id
- name
- parent_id
Basically what I want it to do is check if there is a parent id, and if so then check if the parent id, and if that parent has a parent id, and so on. Then output the parents in order until it reached the child.
Currently what I am doing (in Ruby/Ruby on Rails) is this:
<% #cat = Category.find_by_id(#project.category) %>
<% if #cat.parent_id.nil? %>
<%= #cat %>
<% else %>
<%= Category.find_by_id(#cat.parent_id).name%> => <%= #cat.name %>
<% end %>
The problem with this is that it only gets one parent. I need it to recurse and constantly gather the parent until it hits and end, and also I dont want it to take up too much memory. Any help would be appreciated. Thanks! :)
Add a method on your model to search for the parent
class Category
# inline, less memory usage
def last_parent
last = self
while last.parent
last = last.parent
end
last
end
# recursive, better readability
def last_parent_recursive
if parent
parent.last_parent_recursive
else
self
end
end
end
then, on your view:
<%= #cat.last_parent %>

avoid issue in the mvc

I know that a view shouldn't have any knowledge, of the model or the controller but i am not to sure how to avoid it.
The issue is i am trying to fetch the information from the controller or the model before i need to manipulate it in my view.
Here the code
Model
USER LOCATION ARTICLE
id user_id title
first article_id ...
last
...
Relationship
user has many locations
article has many locations
location belongs to user
location belongs to article
controller
#userlocation = #user.locations
View
<% #userlocation.each do |event| %>
...
<% evTitle = Article.find_by_id(event.article_id) %>
<%= evTitle.title %>
<% end %>
Obviously its not the best not sure how to do the query in the controller, and evTitle doesnt report properly why?
In controller you can do like this:
#userlocations = #user.locations
#locations_articles = Article.find_all_by_id(#userlocations.map(&:article_id).uniq)
Then you can use #locations_articles in view. Avoid using db queries in view.
<% #locations_articles.each do |article| %>
<%= article.title %>
<% end %>
You can first watch the rails cast multiple form episode at here :-
http://railscasts.com/episodes/196-nested-model-form-part-1
and there is an attribute that first you should define in model to access the information at single view form.
def new
#survey = Survey.new
3.times do
question = #survey.questions.build
4.times { question.answers.build }
end
end

Rails 3.1 adding an object to an array returned by find_by_sql / can't show in erb file

I'm porting a php app to rails so I have a set of sql statements that I'm converting to find_by_sql's. I see that it returns a collection of objects of the type that I called on it. What I'd like to do is then iterate through this collection (presumably an array) and add an instance of a specific object like this:
#class is GlobalList
#sql is simplified - really joining across 3 tables
def self.common_items user_ids
items=find_by_sql(["select gl.global_id, count(gl.global_id) as global_count from main_table gl group by global_id"])
#each of these items is a GlobalList and want to add a location to the Array
items.each_with_index do |value,index|
tmp_item=Location.find_by_global_id(value['global_id'])
#not sure if this is possible
items[index]['location']=tmp_item
end
return items
end
controller
#controller
#common_items=GlobalList.common_items user_ids
view
#view code - the third line doesn't work
<% #common_items.each_with_index do |value,key| %>
<%=debug(value.location) %> <!-- works -->
global_id:<%=value.location.global_id %> <!-- ### doesn't work but this is an attribute of this object-->
<% end %>
So I have 3 questions:
1. is items an Array? It says it is via a call to .class but not sure
2. I am able to add location these GlobalList items. However in the view code, I cannot access the attributes of location. How would I access this?
3. I know that this is pretty ugly - is there a better pattern to implement this?
I would get any data you need from locations in the sql query, that way you avoid the n+1 problem
#items=find_by_sql(["select locations.foo as location_foo,
gl.global_id as global_id,
count(gl.global_id) as global_count
from main_table gl
inner join locations on locations.global_id = gl.global_id
group by global_id"])
Then in the view:
<% #items.each do |gl| %>
<%= gl.location_foo %> <-- select any fields you want in controller -->
<%= gl.global_count %>
<%= gl.global_id %>
<% end %>
If you want to keep it close to as is, I would:
def self.common_items user_ids
items=find_by_sql(["select gl.global_id, count(gl.global_id) as global_count
from main_table gl group by global_id"])
items.map do |value|
[value, Location.find_by_global_id(value.global_id)]
end
end
Then in the view:
<% #common_items.each do |value,location| %>
<%=debug(location) %>
global_id:<%=value.global_id %>
<% end %>

Alphabet Filter for Table in Rails

I'm new to rails, so forgive me if there is an easy answer. I'm trying to implement an "Alphabet Index" for a table in rails. I want to be able to click on a letter and have the table refresh - containing only the data on which the first letter of the last_name column matches the letter clicked.
My first thought was to generate an array of letter from the database
#visitor_array = []
#v = Visitor.all
#v.each do |visitor|
#visitor_array << visitor.last_name[0,1]
end
#visitor_array.sort!
#visitor_array.uniq!
This code gives me an array which has one of each of the first letters. I used this as my "alphabet". On my view I have the following code
<% #visitor_array.each do |visitor| %>
<%= link_to visitor, alphasort(visitor) %>
<% end %>
The thought here is to run a helper function when the letter is clicked. But here is where I'm stuck.
UPDATE:
Okay, thanks to the comments below, I was able to figure it out. In case anyone else was wondering, this is how it was accomplished.
CONTROLLER
# Create array consisting of the first letter of every visitor's last name
#visitor_array = []
#v = Visitor.all
#v.each do |visitor|
#visitor_array << visitor.last_name[0,1]
end
#Sort array alphabetically in ASC order
#visitor_array.sort!
#Remove duplicate elements
#visitor_array.uniq!
if (params[:letter] != nil)
#visitors = Visitor.order("last_name ASC").where("last_name like ?", params[:letter] +"%" )
else
#visitors = Visitor.order("last_name ASC")
end
VIEW
<% #visitor_array.each do |letter| %>
<%= link_to letter, :controller => "visitors" , :letter => letter %>
<% end %>
Use this to get the list of results for a specific letter:
visitors = Visitor.order("last_name ASC").where("last_name like '?'", letter)
Then on your view:
<% #visitor_array.each do |visitor| %>
<%= link_to visitor(visitor) %>
<% end %>
The syntax might be slightly off but the fundamental idea is there.
I'm not entirely sure what you mean by the last line though...

Resources