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

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

Related

rails buttons click counter

This is another I'm-totally-new-to-Ruby-please-have-mercy situation.
So i'm trying to figure out how to make a database of all my buttons to save the click count each time they're clicked. I started a new rails to try it out and generated a model Buttonand a controller buttons index
route.rbs
Rails.application.routes.draw do
resources :buttons
root 'buttons#index'
end
migration
class CreateButtons < ActiveRecord::Migration[5.0]
def change
create_table :buttons do |t|
t.integer :clicks
t.timestamps
end
end
end
buttons_controller
class ButtonsController < ApplicationController
def index
#button = Button.find(1)
end
def doit
#button = Button.find(1)
#newcount = #button.clicks + 1
Button.find(1).update_attributes(:clicks => #newcount)
end
end
Now.. i need to trigger the doit method.. is it possible to trigger a non CRUD operation ?
i tried this but it doesn't seem to work
index.html.erb
<h1>Hello, This is button and my click are :</h1>
<h1><%= #button.clicks %></h1>
<%= link_to 'click me', method: :doit %>
I know there's something I'm not getting here...
Ruby have been doing so much magic that I can't do a simple ruby method.. it have been really hard for me getting the part were methods are taking place without calling them by name..
Specially when I trigger a delete method and the destroy method is triggered by that.. I really need to get used to this too-much-magic coding
Several things to improve, I think. Please get back to me if something is not working (I did not run the code)
Make your index action list all the buttons
Controller:
def index
#buttons = Button.all
end
View:
<h1>These are all my buttons</h1>
<% #buttons.each do |button| %>
<%= link_to("Button #{button.id}", button_votes_path(button), method: :post) %>
<% end %>
It's common to have index show a list of resources.
Only create the routes you need, make increment a separate action
I'd chose to call it "vote". You could also call it "clicks" or "presses" or whatever.
resources :buttons, only: [:index] do
resources :votes, only: [:create]
end
Add the votes controller
class VotesController < ApplicationController
def create
button = Button.find(params[:id])
button.clicks += 1
button.save
redirect_to buttons_path
end
end
No error handling here. So this is just to get you started.
For the next steps I suggest you follow a tutorial or start with simpler stuff.

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

How to display contents from a sequel database connection in the view file in 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.

#users variable empty. forget to pass the collection object for will_paginate?

Problem localhost:3000/users/ won't display
I enter humbly as I am trying to make it through the rails tutorial for the first time. I am in chapter 10 and I have been trouble shooting this for 5 hours. When I attempt to visit localhost:3000/users/ I get an error (I believe this has something to do with factory_girl) that explain that the #users variable is empty and that I forgot to pass a collection object for will_paginate.
I'm currently at chapter 10, section 10.23 and each time I run:
$ bundle exec rake db:reset $ bundle exec rake db:populate
$ bundle exec rake db:test:prepare
I get an error explaining that
rake aborted!
Factory already registered: micropost
This is my second time trying this chapter as I encountered problems the first time and started from chapter 9. Please help and be clear and detailed when providing directions. I am happy to post whatever files that will be helpful.
Here is my index.html.erb - I save these as HTML, should they be saved as ruby files instead?
<% provide(:title, 'All users') %>
<h1>All users</h1>
<%= will_paginate %>
<ul class="users">
<%= render #users %>
</ul>
<%= will_paginate %>
Here is my users controller
class UsersController < ApplicationController
before_filter :signed_in_user, only: [:index, :edit, :update, :destroy]
before_filter :correct_user, only: [:edit, :update]
before_filter :admin_user, only: :destroy
def show
#user = User.find(params[:id])
#microposts = #user.microposts.paginate(page: params[:page])
end
end
def new
#user = User.new
end
def index
#title = "All users"
#users = User.paginate(:page => params[:page])
end
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Do more of the things you love!"
redirect_to #user
else
render 'new'
end
end
def edit
end
def update
if #user.update_attributes(params[:user])
flash[:success] = "Profile updated"
sign_in #user
redirect_to #user
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User destroyed."
redirect_to users_url
end
private
def signed_in_user
unless signed_in?
store_location
redirect_to signin_url, notice: "Please sign in."
end
end
def correct_user
#user = User.find(params[:id])
redirect_to(root_path) unless current_user?(#user)
end
def admin_user
redirect_to(root_path) unless current_user.admin?
end
In your Users controller, make sure you have #users and if you are using will_paginate, make sure you call .paginate(page: params[:page], per_page: 20] and in your view, have <%= will_paginate #users %>.
/users should point to UsersController#index. Make sure you are assigning the collection #users.
For instance it could look like this at the most basic level:
def index
#users = User.all # not paginated
#users = User.paginate(page: params[:page]) # paginated
end
As far as the test database error, I'm guessing that's because you define a :micropost factory more than once.
Instead of #user = User.find(params[:id]) this you should use
#users = User.paginate(page: params[:page])

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