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.
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 am trying to load a view with a list of Product Type. I need the view to be displayed on every page. But the action is not getting called in other pages, please tell me where I'm going wrong and suggest any alternatives.
index.html.erb
<h1>Listing the types of products</h1>
<% content_for :sidebar do %>
<% #types.each do |type| %>
<li><%= link_to type.name, product_type_path(type)%> <!-- go to product_type controller show action-->
<%= link_to "Edit", edit_product_type_path(type) %> <!-- go to product_type controller edit action -->
<%= link_to "Delete", product_type_path(type) , method: :delete, data: { confirm: "Are U Sure?" }%> <!-- go to product_type controller delete action and a pop to confirm the action -->
</li>
<% end %>
<h3><%= link_to "New Type Of Product", new_product_type_path %></h3>
<h3><%= link_to "All Types of Products", products_path %></h3> <!-- All types of products listed for admin's ease -->
<% end %>
This is the Application layout I'm using.
Application.html.erb
<!DOCTYPE html>
<html>
<head>
<%= render 'layouts/title' %>
<%= render 'layouts/rails_defaults'%>
<%= render 'layouts/shim' %>
</head>
<body>
<aside><%= yield: sidebar %></aside>
<%= render 'layouts/header' %>
<%= render 'layouts/flash' %>
<div class="container">
<%= yield %>
</div>
<%= render 'layouts/footer' %>
</body>
</html>
As you can see I'm using yield: sidebar , but its not working properly, in the sense the action index is not getting called if I go to different page.
Product_types Controller
class ProductTypesController < ApplicationController
def index
#types = ProductType.all #to get all the records to an instance variable(array in the case) lasts only until the scope lasts. Since the is defined in index, it lasts only till you are using the index view
end
def new
#type = ProductType.new #to create a new record into the respective model
end
def show
#type = ProductType.find(params[:id]) #Finding the type of product click on
#products = Product.where(value: #type.value) #finding all the products whose value field is same as the type of product value(primary key)
end
def create
#type = ProductType.new(type_params) #type params defined below in private class
if #type.save #save the product created
redirect_to root_url #and redirect to root
else #if doesnt save and error occurs
render 'new' #error occurs and render 'new' view
end
end
def edit
#type = ProductType.find(params[:id])
end
def update
#type = ProductType.find(params[:id])
if #type.update(type_params) #update the params
redirect_to root_url #if updated redirect to root
else
render 'edit' #else if error occurs render 'edit' view again
end
end
def destroy
ProductType.find(params[:id]).destroy #destroy the record
redirect_to root_url #redirect to root
end
private
def type_params
params.require(:product_type).permit(:name,:value) #used to only permit type and value thorugh request(to prevent hacking) used in create and update action above
end
end
The action is not getting called whenever i jump to another page.
please suggest alternatives.
content_for / yield are for the current view only invoked by just the current action. So if the other pages dont have a content_for :sidebar in their views, then they wont have a sidebar. And if you just include in the content_for directly, it still wont execute any extra controller logic required.
Use a helper or partial like your layouts/header if you want resuable content, rather than a reusable "space".
For things you dont want to do only in a partial, but also not only in direct Ruby (with content_tag, etc.), you might combine a partial and a helper.
class ApplicationHelper # Or any other helper
def products_sidebar
products = Product.where(show_on_sidebar: true).order(:popularity) # Or whatever you like
render partial: "shared/products_sidebar", locals: {products: products}
end
end
shared/_products_sidebar.html.erb (Id definitely give consideration to other template engines)
<div id="products_sidebar">
<% products.each do |product| %>
<div><%=product.name%></div> <!--whatever you want it to look like-->
<% end %>
</div>
Then in your index, you can just call it, and it wont depend on the action/controller currently being processed.
<body>
<aside><%= products_sidebar %></aside>
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.
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 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!