making an each in the right way - ruby-on-rails

In movie_controller I added this
def the_followers
#movie = Movie.find(params[:id])
#followings = #movie.followings.where(user_id: params[:user_id])
.page(params[:page]).per(10)
render layout: nil
end
the_followers is the name of the file in view/movies/the_followers
in movie (view) I added this. but It did not work. Why?
<% #followings.each do |following| %>
Username: <%= following.user.username %>
<% end %>
I have a blank list. Did I miss anything?

You may have different issues providing the list empty. Try following steps to isolate the problem.
remove scopes
#followings = Following.all.paginate(page: 1, per_page: 100)
Add them one by one
#followings = #movie.foollowings.all.paginate(page: 1, per_page: 100)
then try
#followings = #movie.foollowings.where(user_id: params[:user_id]).paginate(page: 1, per_page: 100)
finally
#followings = #movie.followings.where(user_id: params[:user_id])
.page(params[:page]).per(10)
See for yoursellf, at what step you'r array becomes empty.

You can use the simplest debugging method to locate the problem.
def the_followers
#movie = Movie.find(params[:id])
# Check movie followings array is empty?
puts "---movie following num: #{#movie.followings.count}---"
# Check the user_id param is present?
puts "---user_id: #{params[:user_id]}---"
# Check movie followings with user_id is empty?
puts "---movie following with user_id num: #{#movie.followings.where(user_id: params[:user_id]).count}---"
#followings = #movie.followings.where(user_id: params[:user_id])
.page(params[:page]).per(10)
# Check the result is empty?
puts "---result num: #{#followings.count}---"
render layout: nil
end
If all puts correct, then check the views code.

Related

Rails: How to query a record using each_with_index while seeding a database

I have a posts table with 100 blank posts which I plan to seed with content from a post_content.csv file. The csv has the HTML content of each post in each row.
seeds.rb
File.open("post_content.csv", "r") do |f|
f.each_with_index do |line, index|
content = line.chomp
n = index + 1
#post = Post.find_by_id(n)
#post.update(content: content)
end
end
However, when I seed the content, I get an error:
undefined method 'update' for nil:NilClass
How do I correctly find each post based on the index number?
To get the value based on index, you can use offset as in below code :
File.open("post_content.csv", "r") do |f|
f.each_with_index do |line, index|
#post = Post.offset(index).first
#post.update(content: line.chomp) if #post.present?
end
end
Offset is used to skip records.
Reference:
https://apidock.com/rails/ActiveRecord/QueryMethods/offset
There are some Post ID not available in database so your script crash. Run below script to know which ID not available.
File.open("post_content.csv", "r") do |f|
f.each_with_index do |line, index|
content = line.chomp
n = index + 1
#post = Post.find_by_id(n)
if #post
#post.update(content: content)
next
puts "The Post with id #{n} was not found."
end
end

Rails saving arrays to separate rows in the DB

Could someone take a look at my code and let me know if there is a better way to do this, or even correct where I'm going wrong please? I am trying to create a new row for each venue and variant.
Example:
venue_ids => ["1","2"], variant_ids=>["10"]
So, I would want to add in a row which has a venue_id of 1, with variant_id of 10. And a venue_id of 2, with variant_id of 10
I got this working, and it's now passing in my two arrays. I think I am almost there I'm not sure the .each is the right way to do it, but I think that I'm on the right track haha. I have it submitting, however, where would I put my #back_bar.save? because this might cause issues as it won't redirect
Thanks in advance.
def create
#back_bar = BackBar.new
#venues = params[:venue_ids]
#productid = params[:product_id]
#variants = params[:variant_ids]
# For each venue we have in the array, grab the ID.
#venues.each do |v|
#back_bar.venue_id = v
# Then for each variant we associate the variant ID with that venue.
#variants.each do |pv|
#back_bar.product_variant_id = pv
# Add in our product_id
#back_bar.product_id = #productid
# Save the venue and variant to the DB.
if #back_bar.save
flash[:success] = "#{#back_bar.product.name} has been added to #{#back_bar.venue.name}'s back bar."
# Redirect to the back bar page
redirect_to back_bars_path
else
flash[:alert] = "A selected variant for #{#back_bar.product.name} is already in #{#back_bar.venue.name}'s back bar."
# Redirect to the product page
redirect_to discoveries_product_path(#back_bar.product_id)
end
end # Variants end
end # Venues end
end
private
def back_bar_params
params.require(:back_bar).permit(:venue_id,
:product_id,
:product_variant_id)
end
as i said in comments
this is untested code and just showing you how it's possible to do with ease.
class BackBar
def self.add_set(vanue_ids, variant_ids)
values = vanue_ids.map{|ven|
variant_ids.map{|var|
"(#{ven},#{var})"
}
}.flatten.join(",")
ActiveRecord::Base.connection.execute("INSERT INTO back_bars VALUES #{values}")
end
end
def create
# use in controller
BackBar.add_set(params[:venue_ids], params[:variant_ids])
# ...
end

RoR Active record 'where' doesn't work properly

This is my code, the first part is the problem, and the second is perfectly working.
def show
if #user.cooker?
#pushs = #user.pushs.where(taked_by = #user.id)
else
#pushs = #user.pushs
end
end
Well the code say, if I'm a cooker, I want to display all the push where the variable :taked_by is has the same id than my user.id
And the second par say that if I'm not a cooker, display all my own push.
Do taked_by: #user.id or :taked_by => #user.id
def show
if #user.cooker?
#pushs = #user.pushs.where(taked_by: #user.id)
else
#pushs = #user.pushs
end
end
Let me know if it worked.

Ruby why is my object saving without an ID?

I feel like I'm missing something very basic, and someone can look at this and very quickly telling me what that is...
def create
#user = User.find_by_id(create_params[:user_id])
#plan = #user.plans.new(create_params)
if #plan.save
puts #plan.inspect
end
end
Right now the puts statement returns this:
#<Plan id: nil, zipcode: "02114", selected_plan: 5, user_id: 1>
So basically.. all the attributes are there, but there's no id...
More info:
create_params = {zipcode:"02114", selected_plan:"5", user_id: 1}
And if it's helpful to know, save! does work and successfully saves the plan with an id... and plan.save == true returns true
Your code should have the following pattern.
#user = User.find(create_params[:user_id]) # see changes
#plan = #user.plans.new(create_params)
if #plan.save
puts #plan.reload.inspect #reload object to see if the object has been saved!
else
puts #plan.errors.messages.inspect # if object is not saved there should be Object#errors.messages should have messages
end

routing and searching a db ruby

I want to retrieve all the tweets that have a certain hashtag in them.
At first I add the hashtags in my 2 tables :
def add_hashtags(tweet)
tweet.content.scan(/(?:\s|^)(?:#(?!(?:\d+|\w+?_|_\w+?)(?:\s|$)))(\w+)(?=\s|$)/){ |tag|
#allhashes = Hashtag.all
#hash = Hashtag.find_by_name(tag[0].strip)
unless #hash
#hashtag = Hashtag.new(name: tag[0].strip)
#hashtag.save
#hashrel = Hashrelation.new(tweet_id: tweet.id, hashtag_id: #hashtag.id)
#hashrel.save
else
#hashrel = Hashrelation.new(tweet_id: tweet.id, hashtag_id: #hash.id)
#hashrel.save
end
}
end
then I want to route to the show method of tweet controller :
get 'tweets/show/(.:format)' => 'tweets#show', as: :hashtag
The links in the hashtags are as follows:
def twitify(tweet = '')
tweet.gsub(/(?:\s|^)(?:#(?!(?:\d+|\w+?_|_\w+?)(?:\s|$)))(\w+)(?=\s|$)/) do |tag|
" " + link_to("#{tag.strip}", hashtag_path(tag.strip), {:name => tag.strip})
end.html_safe
end
And finally the show method of the tweet controller is :
def show
#hashtag = Hashtag.find_by_name(params[:name])
#tweet_ids = Hashrelation.find_by_hashtag_id(#hashtag.id)
#feed_items = Tweet.find_by_id(#tweets_ids.id)
end
When I click on the link I get :
undefined method `id' for nil:NilClass
which means that params[:name] is either nill or it isn't like the one I have in the DB.
Could you guys help me figure this out ?
The link I see that is called is 'http://localhost:3000/tweets/show/.%23dadawea' which means I have extra things why would I ?.
I would do the following
def add_hashtags(tweet)
tweet.content.scan(/(?:\s|^)(?:#(?!(?:\d+|\w+?_|_\w+?)(?:\s|$)))(\w+)(?=\s|$)/).flatten.each do |tag|
hashtag = Hashtag.where(name: tag.strip).first_or_create
Hashrelation.create(tweet_id: tweet.id, hashtag_id: hashtag.id)
end
end
Then change the twitify method to look like
def twitify(tweet = '')
tweet.gsub(/(?:\s|^)(?:#(?!(?:\d+|\w+?_|_\w+?)(?:\s|$)))(\w+)(?=\s|$)/) do |tag|
" " + link_to("#{tag.strip}", hashtag_path(name: tag.strip))
end.html_safe
end
And the show method
def show
#hashtag = Hashtag.find_by_name(params[:name])
#tweet_ids = Hashrelation.where(hashtag_id: #hashtag.id).pluck(:id)
#feed_items = Tweet.where(tweet_id: #tweets_ids)
end
This should be what you are looking for. Now for whats changing:
Removed Duplicate logic in the add_hashtags to use create instead.
twitify method is passing name as an html option not a url option so I fixed that. Right now it thinks you want to set the format to the name of the hashtag and name the link the name of the hashtag**
show method is using find_by which will only return a single result not what you wnat for tweet_ids so i changed it to where clause and just grabbed the ids. Then changes feed_items to search Tweet for all tweet_ids in the Array.
To strip the # just use tag.strip[1..-1]

Resources