Rails dummy object added to Active Record Array - ruby

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?) %>

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 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.

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.

Do calculation using radio_button variable to nested form controller - Rails 3

I have a edit form which I have a radio_button that I would like to pass to a controller action and then use it to do a calculation. In the view I have:
<div class="field">
<%= radio_button_tag(:rating_select, "Up") %>
<%= label_tag(:rating_select, "Good.") %>
<%= radio_button_tag(:rating_select, "Down")%>
<%= label_tag(:rating_select, "Bad.")%>
</div>
In the controller I have:
def rating
#post = Post.find(params[:id])
.....
end
def update
#post = Post.find(params[:id])
##rating_select = params[:rating_select]
if #post.rating_select == "Up"
#post.score += 5
elsif #post.rating_select == "Down"
#post.score -= 5
end
......
end
Currently it is ignoring the if statement so the parameter isn't getting set properly. Ideally I would like to just use a temp variable from the view to use in the if statement to decide if I need to add or subtract in the update. But I also have a rating_select field in post if I need to use it also. Thanks.
UPDATE:
Thanks. That makes sense, I changed it to below but it still isn't incrementing or decrementing the score based on the radio box. So it seems it isn't getting the rating_select?:
def update
#post = Post.find(params[:id])
if params[:rating_select]=="Up"
#post.score += 5
elsif params[:rating_select]=="Down"
#post.score -= 5
end
respond_to do |format|
....
UPDATE2:
Finally figured it out, used another model Ratings to store association. I used the before_save in the Post model and it allowed me to do the calculation and save. What a headache.
before_save :set_rating
def set_rating
if self.rating.rating_select=="Up"
rating.score += 5
elsif self.rating.rating_select=="Down"
rating.score -= 5
end
end
Well, first off, in the code you're showing the post loaded in your update action is not receiving the params from your view.
Your code for an update action should typically look like this:
def update
#post = Post.find(params[:id])
if #post.update_attributes(params[:post])
... do stuff ...
else
render :edit, :alert => 'Unable to update post.'
end
end
Second, since you're using form_tag helper and not form_for, then you're not getting the params all setup for your model (ie. nested under params[:post]). So, in this case, your rating_select option is just a value by itself, which you can test for like this:
if params[:rating_select]=="Up"
...
else
...
end
The big thing to understand from your code is #post doesn't know anything about params[:rating_select], even if you used #post.update_attributes(params[:post]), because radio_button_tag as you have it set up is not building a hash of post attributes, it's just a standalone field.
I hope that makes sense, if you don't understand please leave comments and I'll try to explain more.

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