How to display contents from a sequel database connection in the view file in Ruby? - ruby

I am trying to retrieve data from a PostgreSQL database with Sequel in Sinatra.
DB = Sequel.connect('postgres://connection_data')
items = DB[:items]
Then I try to get an entry with a specific ID:
get '/:id' do
#item = items.filter(:id => params[:id])
erb :edit
end
In my edit view I would like to display the content of the #item variable. The problem is that I don´t know how to get for example the ID.
<% if #item %>
Do something
<% else %>
<p>Item not found.</p>
<% end %>
I tried using #item.id and #item[:id] but both don´t work. I get an error undefined method 'id' for #<Sequel::Postgres::Dataset:0x007fac118b7120>. What would be the right way to retrieve the values from the #item variable?

#item = items.filter(:id => params[:id]) returns a dataset. If you want a single item, you should do: #item = items.first(:id => params[:id].to_i)
Also #item.id is probably not want you want. Given that items = DB[:items], you are using a plain dataset and then #item = items.first(:id => params[:id].to_i) is going to give you a hash. You need to do #item[:id] to get the item's id.
You may want to look at using models instead:
# model file
class Item < Sequel::Model; end
# sinatra code
#item = Item[params[:id].to_i]
# template
#item.id

Actually #item.id is the right way. The only problem I can see in your code is
#item = items.filter(:id == params[:id])
which should be
#item = items.filter(:id => params[:id].to_i)
EDIT:
Try this:
#item = items.where(:id => params[:id].to_i)
#item.select(:id) #to embed
params[:id] is giving a string, so convert it to an integer.

Related

how to display json and parse json in ruby using httparty

I am working on a food app in ruby on rails which requires to get calorie value of food item from food api.In my controller i am getting the JSON response but i am unable to parse and display the calorie value of food item in a index.html.erb file here is my controller code.
require 'rubygems'
require 'httparty'
class FoodsController < ApplicationController
def index
#foods = Food.all
end
def show
#food = Food.find(params[:id])
end
def new
#food = Food.new
end
def edit
#food = Food.find(params[:id])
end
def create
#food = Food.new(food_params)
#response = HTTParty.get('http://api.nutritionix.com/v1_1/search/'+#food.name+'?fields=item_name%2Citem_id%2Cbrand_name%2Cnf_serving_size_unit%2Cnf_calories%2Cnf_total_fat&appId=696d1ad4&appKey=aec2c4766d40d7f6346ed89d5d82fe75')
#http_party_json = JSON.parse(#response.body)
if #food.save
redirect_to foods_path
else
render 'new'
end
end
def update
#food = Food.find(params[:id])
if #food.update(food_params)
redirect_to #food
else
render 'edit'
end
end
def destroy
#food = Food.find(params[:id])
#food.destroy
redirect_to foods_path
end
private
def food_params
params.require(:food).permit(:name, :quantity)
end
end
Any suggestions are highly welcome as i am newbie on stackoverflow so dont know proper editing forgive please! help me how to display calorie value in html page
You can add a new function to Food model to get you the Calorie:
class Food
def calorie
response = HTTParty.get("http://api.nutritionix.com/v1_1/search/#{self.name}?fields=item_name%2Citem_id%2Cbrand_name%2Cnf_serving_size_unit%2Cnf_calories%2Cnf_total_fat&appId=696d1ad4&appKey=aec2c4766d40d7f6346ed89d5d82fe75")
json = JSON.parse(response.body)
end
end
and then simply in your index.erb if you loop over foods collection you do the following:
<% #foods.each do |food| %>
<%= food.name %>
<%= food.calorie %>
<% end %>
but in that case performance will not be good, as you do remote access for each item each time you display data, so as calorie value is always the same for same food, then after its created you can do remote query and store the calorie to calorie attribute in your Food model
You can do the following:
class Food < ActiveRecord::Base
before_create :set_calorie
private
def set_calorie
response = HTTParty.get("http://api.nutritionix.com/v1_1/search/#{self.name}?fields=item_name%2Citem_id%2Cbrand_name%2Cnf_serving_size_unit%2Cnf_calories%2Cnf_total_fat&appId=696d1ad4&appKey=aec2c4766d40d7f6346ed89d5d82fe75")
self.calorie = JSON.parse(response.body)
end
end

Rails dummy object added to Active Record Array

I use rails 4.2 and I found a weird issue:
#tweet = current_user.tweets.new
#tweets = current_user.tweets
When I loop over in Views like:
<%= render #tweets %>
I get an Extra Record with null id.
Example:
You build this empty Tweet yourself in your controller:
#tweet = current_user.tweets.new
#tweets = current_user.tweets
There are several ways to avoid this problem. You could build the new Tweet without adding it to the #tweets array:
#tweet = Tweet.new(user: current_user)
#tweets = current_user.tweets
Or you could change your your to exclude tweets that haven't been saved to the database yet:
<%= render #tweets.select(&:persistent?) %>

undefined method `each' for nil:NilClass -- again-- i dont get it. Constantly getting this error

class ProfileController < ApplicationController
def show
#user = current_user
#first_name = #user.first_name
#last_name = #user.last_name
end
def settings
end
def pics
#photos = current_user.photos.all
end
end
in the view of _pics.html.erb, I have
<% #photos.each do |p| %>
<%= image_tag p.image(:medium) %>
<% end %>
If I change it to current_user.photos.each do |p|, it works, which is weird. I don't get an error from this code on my other computer.
In a comment you said, that you render the pics partial from your show view. Since the show view is rendered by the show action and the show action does not set the #photos variable, you can't use that variable. So to fix your problem, you'd need to set the variable in the show action.
You seem to think that rendering the pics partial will invoke the pics action, but that's not the case. An action will only be invoked if an URL is accessed that's mapped to that using the routing system. Rendering partials does not invoke any actions.
Also it should just be #photos = current_user.photos without the all.

Undefined local variable or method 'id' for #<moviesController:0xb3314d64> on Rotten Potatoes

I've been working on an Edx problem Homeowrk 2 for about 2 hours. I'm officially stuck. How do you make something. This problem has to do with
What I have to do is link Movie Title to as sort, so that it would sort Movie in order.
-# This file is app/views/movies/index.html.haml
%h1 All Movies
%table#movies
%thead
%tr
%th= link_to 'Movie Title', new_movie_path
%th Rating
%th Release Date
%th More Info
%tbody
- #movies.each do |movie|
%tr
%td= movie.title
%td= movie.rating
%td= movie.release_date
%td= link_to "More about #{movie.title}", movie_path(movie)
= link_to 'Add new movie', new_movie_path
According to the homework, I'm supposed to edit the index to so that it puts "all Movies" in order. I've looked up the sort method for ruby, and it is movie.order(). I don't know what to put in the parenthesis.
class MoviesController < ApplicationController
def show
id = params[:id] # retrieve movie ID from URI route
#movie = Movie.find(id) # look up movie by unique ID
# will render app/views/movies/show.<extension> by default
end
def index
#movies = Movie.order(id)
end
def new
# default: render 'new' template
end
def create
#movie = Movie.create!(params[:movie])
flash[:notice] = "#{#movie.title} was successfully created."
redirect_to movies_path
end
def edit
#movie = Movie.find params[:id]
end
def update
#movie = Movie.find params[:id]
#movie.update_attributes!(params[:movie])
flash[:notice] = "#{#movie.title} was successfully updated."
redirect_to movie_path(#movie)
end
def destroy
#movie = Movie.find(params[:id])
#movie.destroy
flash[:notice] = "Movie '#{#movie.title}' deleted."
redirect_to movies_path
end
end
So the root problems, I dont know how to edit the method index correctly to give my "Movie" directory order, and I dont know how to assign the header Movie Title to point to index.
In the view
%th= link_to 'Movie Title', movies_path(sort_param: 'title')
and in the controller
def index
#movies = Movie.order(params[:sort_param])
end
You could do the same for other headings like 'Rating', 'Release Date' etc as well.
You can check ordering with Rails. The variable id in your index function does not exist.
Make a scope in your model. This is the most suggested way. Your controller does not need to know how to retrieve your results. Just ask model what you need!
In the scope, design it how you want. Check the doc for more info.
In your movie model file, put something like:
scope :ordered, order("id ASC")
Then in your controller index:
#movies = Movie.ordered
This will give your sorted movie collection

Why can I not save tweets into the database?

I want to save the tweets into the database, but it doesn't work! I'm using the twitter gem.
My controller:
class TweetsController < ApplicationController
def save_tweets_into_database
#tweets = Twitter.search("#em2012" "#Italy" "#Spain", :lang => "en", :rpp => 25).results
#tweets.each do |tweet|
#tweet = tweet
#tweet.create
end
end
end
My Model
require "rubygems"
require "twitter"
class Tweet < ActiveRecord::Base
end
My view
<% #title = "liste" %>
<h2>Liste der Tweets über das EM-Finale</h2>
<ul>
<% #tweets.each do |tweet| %>
<li><%= tweet %></li>
<% end %>
</ul>
my routes
Em2012tweet::Application.routes.draw do
match '/save_tweets', to: 'tweets#save_tweets_into_database'
end
This error is displayed:
undefined method `create' for Twitter::Status:0x007fac9c80a160
Rails.root: /Users/xyz/Desktop/Workspace/em2012tweet
app/controllers/tweets_controller.rb:7:in `block in save_tweets_into_database'
app/controllers/tweets_controller.rb:5:in `each'
app/controllers/tweets_controller.rb:5:in `save_tweets_into_database'
save the tweets into the database
In Rails, following REST convention, index action is associated with simply displaying all the objects of a model already stored in database. And this is actually what you did with the code as well. Your index action isn't doing anything that will save the tweets into the database.
I don't think you are trying to save tweets here. You are trying to simply display them. Try this if you want to simply display tweets in index view file.
def index
#tweets = Twitter.search("#em2012" "#italy" "#spain", :lang => "en", :rpp => 25).results
end
If you want to save tweets, create an action like this.
def save_tweets_into_database
#tweets = Twitter.search("#em2012" "#italy" "#spain", :lang => "en", :rpp => 25).results
#tweets.each do |tweet|
Tweet.save(tweet)
end
end
tweets_controller.rb:
class TweetsController < ApplicationController
def save_tweets_into_database
#tweets = Twitter.search("#em2012" "#Italy" "#Spain", :lang => "en", :rpp => 25)
#tweets.each do |tweet|
Tweet.create(twitter_tweet: tweet)
end
end
end
tweet.rb:
class Tweet < ActiveRecord::Base
serialize :twitter_tweet
end
Note that this requires you have a migration where a tweets table is created with a text column named 'twitter_tweet', e.g.
class CreateTweets < ActiveRecord::Migration
def change
create_table :tweets do |t|
t.text :twitter_tweets
t.timestamps
end
end
end
This will allow you to call save_tweets_into_database and save the 25 returned tweets into the database. This isn't a very good strategy, as you are serializing each of the Twitter::Status objects and storing them as YAML in your database. This means you lose the ability to use all the nice ActiveRecord helpers, and instead must deserialize all of the objects you want to work with before actually using them. A better strategy would be to create an ActiveRecord object that has the same attributes as those in the Twitter::Status object you wish to save. Then you can map the fetched Twitter::Status objects to the new ActiveRecord Tweet objects and retain all the benefits of using ActiveRecord.
I'll not say anything about your routing structure, other than it definitely doesn't appear to be following the 'Rails' way, which, from experience, typically leads to quite a few headaches.

Resources