I've got a total of 11 users in my seeds.rb. however, in my user index, it displays 11x11 = 121 users. each user is listed 11 times. Also, whenever I create a new user on the website (sign up), it keeps on multiplying. +1 signed up user leads to a total of 12 users in the db and 12x12 = 144 users being displayed (THEY ARE NOT IN THE DB!) in the index... what's wrong here?! I checked my users controller create action for any weird stuff but couldn't find anything out of the usual.. any help?
this is my user index view:
<% provide(:title, 'Users') %>
<h1>List of Users</h1>
<%= will_paginate %>
<ul class="users">
<% #users.each do |user| %>
<%= render #users %>
<% end %>
</ul>
<%= will_paginate %>
As Solarflare mentioned in the comment, you're rendering the entire user list (#users) at every iteration of that loop. You should update your loop to be:
<ul class="users">
<% #users.each do |user| %>
<%= render user %>
<% end %>
</ul>
That way you're rendering the page for each individual user in the loop.
Related
I’m completely new to ruby on rails, I’m creating a simple article search application that would use the Guardian API and just display the news titles. It just needs to work like this: a user enters the page, fills in the search form and views the news titles.
I want to simply select the request result’s ‘webTitle’ keys and display their values as list items, but I get a big chunk of data and I’m not sure how can I do that.
Here is the request result:
{"response"=>{"status"=>"ok", "userTier"=>"developer", "total"=>2153270, "startIndex"=>1, "pageSize"=>10, "currentPage"=>1, "pages"=>215327, "orderBy"=>"relevance", "results"=>[{"id"=>"books/2017/jul/16/fall-down-7-times-get-up-8-naoki-higashida-review-autism", "type"=>"article", "sectionId"=>"books", "sectionName"=>"Books", "webPublicationDate"=>"2017-07-16T06:00:13Z", "webTitle"=>"Fall Down 7 Times Get Up 8 review – a window on the world of autism", "webUrl"=>"https://www.theguardian.com/books/2017/jul/16/fall-down-7-times-get-up-8-naoki-higashida-review-autism", "apiUrl"=>"https://content.guardianapis.com/books/2017/jul/16/fall-down-7-times-get-up-8-naoki-higashida-review-autism", "isHosted"=>false, "pillarId"=>"pillar/arts", "pillarName"=>"Arts"}, {"id"=>"football/2017/jul/07/gold-cup-2017-predictions-usa-mexico-costa-rica-football", "type"=>"article", "sectionId"=>"football", "sectionName"=>"Football", "webPublicationDate"=>"2017-07-07T09:00:08Z", "webTitle"=>"Gold Cup picks: USA to tip under-strength Mexico and in-form Costa Rica", "webUrl"=>"https://www.theguardian.com/football/2017/jul/07/gold-cup-2017-predictions-usa-mexico-costa-rica-football", "apiUrl"=>"https://content.guardianapis.com/football/2017/jul/07/gold-cup-2017-predictions-usa-mexico-costa-rica-football", "isHosted"=>false, "pillarId"=>"pillar/sport", "pillarName"=>"Sport"}, {"id"=>"world/2017/jul/15/stream-of-floating-bodies-near-mosul-raises-fears-of-reprisals-by-iraqi-militias", "type"=>"article", "sectionId"=>"world", "sectionName"=>"World news", "webPublicationDate"=>"2017-07-15T08:00:01Z", "webTitle"=>"Stream of floating bodies near Mosul raises fears of reprisals by Iraqi militias", "webUrl"=>"https://www.theguardian.com/world/2017/jul/15/stream-of-floating-bodies-near-mosul-raises-fears-of-reprisals-by-iraqi-militias", "apiUrl"=>"https://content.guardianapis.com/world/2017/jul/15/stream-of-floating-bodies-near-mosul-raises-fears-of-reprisals-by-iraqi-militias", "isHosted"=>false, "pillarId"=>"pillar/news", "pillarName"=>"News"}]}}
API consumer class:
#app/clients/guardian_api_client.rb
class GuardianApiClient
include HTTParty
API_KEY = ENV['GUARDIAN_CONTENT_API_KEY']
BASE_URL ="https://content.guardianapis.com/search?"
API_PARTIAL_URL = "api-key=#{API_KEY}"
def query(q)
request = HTTParty.get(BASE_URL+"q=#{q}&""api-key=#{API_KEY}")
puts request
request
end
end
Controller:
class SearchController < ApplicationController
def search
#app = GuardianApiClient.new
#results = #app.query(params[:q])
end
end
View:
<%= form_with(url: '/search') do |f| %>
<%= f.text_field :q %>
<%= f.submit 'search' %>
<% end %>
<% if #results != nil %>
<ul>
<%= #results.each do |r| %>
<li><%= r["webTitle"] %></li>
<% end %>
</ul>
<% else %>
<p>No results yet</p>
<% end %>
Routes:
Rails.application.routes.draw do
get '/search' => 'search#search'
post '/search' => 'search#search'
end
The response is some JSON, so you need to learn how to map through it and get the results that you want.
To see the data more clearly try printing it with:
puts JSON.pretty_generate(#results)
in your controller, then see the output in your rails console.
Anyway, you have a few options:
Option 1: Likely you just need to drill down further into #results in your view. In the JSON that is returned, the webTitles are nested, so changing the third line below should work. Also note on that line that I removed the = sign to prevent the return value from being displayed.
<% if #results != nil %>
<ul>
<% #results["response"]["results"].each do |r| %>
<li><%= r["webTitle"] %></li>
<% end %>
</ul>
<% else %>
<p>No results yet</p>
<% end %>
Option 2: You may consider getting the list of articles in your controller, which I think was your original intent and also is probably more "rails" like:
class SearchController < ApplicationController
def search
#app = GuardianApiClient.new
#results = #app.query(params[:q])
#articles = #results["response"]["results"].map do |article|
article
end
end
end
In your view, then call render to a partial:
<%= render 'articles' %>
Then create a partial view called _articles.html.erb in whatever directory your other view is in, and then add some code to display each article:
<ul>
<% #articles.each do |article| %>
<li><%= article["webTitle"] %> <% link_to 'Link', article["webUrl"] %></li>
<% end %>
<ul>
By separating out each article that was returned in the #articles array, it will probably be easier for you to get other attributes as well in a more readable way. As you can see, above I included a link to the actual article.
I'm struggling to get data from two separate tables to display on the same index page.
I have data from one table displaying as a list this table is called "transactions".
Now in my model for transactions I have defined that it has many "notes. which is my other table I want to display data from on this same index.
I want each transaction to display the notes associated with it by the id of the transaction and the id in the notes table under transaction_id.
For the life of me I have yet to figure out how to do this.
Here is what my transactions index.html.erb looks like:
<% #transactions.each do |transaction| %>
<div class="element">
<%= trash_ico(transaction) %>
<%= edit_ico(transaction, edit_transaction_path(transaction)) %>
<%= link_to "<h2><span class=\"el_header\">#{Asset.find(transaction.asset_id).nmc_name} : Assigned to #{User.find(transaction.user_id).name}</span></h2>
<div class=\"el\">Created: #{transaction.created_at}</div>
<div class=\"el\">Ended: #{transaction.finished}</div>
<div class=\"el\">Type: #{if ! transaction.transaction_type.nil? then transaction.transaction_type.name end}</div>
<div class=\"el\">Status: #{if ! transaction.transaction_status.nil? then transaction.transaction_status.name end}</div>
<br clear=\"all\" />".html_safe, transaction %>
<% note.each do |note| %>
<%= link_to "<div>#{note.notes}</div>".html_safe, note %>
<% end %>
</div>
<% end %>
And this is how the controller is defined for the index:
def index
unless params[:asset_id].nil?
#transactions = Transaction.find_all_by_asset_id(params[:asset_id])
else
#transactions = Transaction.all
end
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #transactions }
end
end
I'm very green to programming but mostly to rails. I see what the task is that I need to do, but I'm not sure what the syntax must be to do it.
I have a similar view setup for my show def. I just can't get notes to show underneath their respective transaction on the index.
I am thinking, something like this;
<% transaction.notes.each do |note| %>
<%= link_to "<div>#{note.notes}</div>".html_safe, note %>
<% end %>
Since you declared notes belonging to transactions. Rails allows you to access them this way.
I have 3 models
Users: id , name
Jobs: id, user_id, title
Applications: id, job_id, user_id
In Job#show page I am trying to put a button which is visible only to people who haven't applied to the job, haven't created the job and are logged in . I am using devise. I have managed to build correct relationship in these models (thanks to SO) as following.
user.jobs #list all jobs posted by the user
jobs.applicants #list all applicants on the job
Question is how to formulate if else condtion which shows button which submits a form (hidden) to the job#show page and puts job_id and user_id in the application model.
I tried
<% if user_signed_in? %>
<% if job.user_id = current_user.id %>
<div style="text-align:center;" class="widget">
<%= link_to(new_user_session_path, :class => "g-btn type_primary") do %>
<i class="icon-external-link"></i> Apply for the job
<% end %>
</div>
<% end %>
<% end %>
I can't seems to get the idea on how to get around error of object.id nil.
You seem to have missed an = sign.
You can improve your if condition like this
<% if user_signed_in? && job.present? && job.user_id == current_user.id %>
your logic here
<% end %>
how does a user apply for the job? using what controller?
you code has the user logging in again,
does the user need to create an application object and does it require additional information from the user to complete the process, or is more along the lines of send existing information from the user to information stored in the job.
If the latter you can do something like this.
resources :jobs do
member do
post 'apply'
end
end
<% if user_signed_in? %>
<% unless job.user == current_user %>
<div style="text-align:center;" class="widget">
<%= link_to 'Apply', apply_job_path(job), method: :post %>
</div>
<% end %>
<% else %>
<%= link_to 'Sign in to apply', new_user_session_path %>
<% end %>
then in your jobs controller
def apply
if Application.create job_id: params[:job_id], user: current_user
redirect_to jobs_path, notice: "You have applied, good luck!"
else
... do something for failure...
end
end
Try this instead
<% if user_signed_in? %>
<% if job.user_id == current_user.id %>
<div style="text-align:center;" class="widget">
<%= link_to "Apply for the job" new_user_session_path, :class => "g-btn type_primary" %>
</div>
<% end %>
<% end %>
and it might be better to change this line
<div style="text-align:center;" class="widget">
to
<div class="widget center">
and add a class named center to the relevant css sheet
I have a sidebar that contains links to all of a users :shopping_lists. Upon clicking on one of those links, I'd like to render a page showing the :list_items in that particular list. Here's my sidebar partial:
<aside class="sidebar-nav-fixed">
<h1>My Lists</h1>
<% if user_signed_in? %>
<% current_user.shopping_lists.each do |l| %>
<ul>
<%= link_to "#{l.name}", '#' %>
</ul>
<% end %>
<% else %>
<h5><%= link_to "Sign in to manage lists.", new_user_session_path %></h5>
<% end %>
</aside>
My question is: what path would I be putting in place of my current stub link in order to route to the correct list? Thanks in advance!
That will depend on how your routes are setup. I would expect shopping lists to always be in the context of a user, so probably something like this:
<%= link_to l.name, user_shopping_list_path(current_user, l) %>
If shopping lists are a top level route, then probably something like this:
<%= link_to l.name, shopping_list_path(l) %>
There are couple of things you can do, granted your routes are setup correctly:
The easiest is:
link_to "#{l.name}", l
Rails should create a link something similar to http://host/shopping_lists/2
The above is a shorthand for
link_to "#{l.name}", shopping_list_path(l)
To see a list of available routes and methods you can run:
bundle exec rake routes
in the root of your rails app
I am implementing an activity feed for my application, much like the facebook news feed. Whenever a user does something (creates a post, comments on a post, creates a photo album, comments on a photo) a row is created in an Activities table, which contains user_id, category, and data. Data is a serialized hash that is different for each type of activity (post contains post title and post id, photo comment contains something else, etc). The view then loops through all of the activities and prints something depending on the category of activity. Pretty simple, and it works. The problem is that it's SUPER slow, so I must be doing something wrong. Here's the code:
#activity.rb snippet
def post?
category == "post"
end
def post_comment?
category == "post_comment"
end
def album?
category == "album"
end
def photo_comment?
category == "photo_comment"
end
#controller snippet
#Activity = Activity.all(:order=> 'created_at DESC', :limit=>"5")
#view snippet
<% #Activity.each do |a| %>
<div class="activity_item">
<div class="avatar" style="background-image: url(<%= small_pic_url(a.user)%>) "></div>
<div class="text"> <%= a.user.username %>
<% if a.post? %>
posted <%= link_to a.data["post_title"], post_path(a.data["post_id"]) %>
<% elsif a.post_comment? %>
commented on <%= link_to a.data["post_title"], post_path(a.data["post_id"]) %>
<% elsif a.album? %>
created a <%= link_to "Photo Album", album_path(a.data["album_id"])%>
<% elsif a.photo_comment? %>
commented on <%= link_to "#{a.data["username"]}'s photo", upload_path(a.data["photo_id"])%>
<% end %>
</div>
</div>
<% end %>
I added a user_id index on the activity table, but that didn't seem to do much. Rendering the 5 activity items/avatars takes over 3 seconds, so there must be a better way to handle this.
Do you have an index on created_at? If you don't, that'll be what's slowing you down - MySQL will have to read through every row in your activities table to make sure it got the latest five (this applies to just about anything using an ORDER BY clause).
And a couple more suggestions, but these are minor. Might shave a few milliseconds off, but nothing on the order of three seconds:
Include the user when you select your activities. This'll let you get your activities and their users in a single DB query. :include => :user should do the trick, or there's a Rails 3-style .include(...) method, if you prefer.
I've heard that serialization can be kinda slow. Perhaps you could use a polymorphic association, and then choose what to display based on a.whatever_type?
Hope this helps!