Custom id column issue - ruby-on-rails

in my listing model i setup a method
def set_listing_number
listing_number="TM#{created_at.year}#{id}"
end
i have a couple of records that was created before i ran the migration to create the listing_number column. i wanted to update all the records at once but keep receiving this error.
here's the code that i ran that produce the error in console verifying if the method . it works i cannot save the assignment.
listing_number=listing.set_listing_number
=> "TM2014574"
2.0.0-p247 :003 > listing_number.save
NoMethodError: undefined method `save' for "TM2014574":String
i tried a couple with no success , that i also found here like this one
Listing.all.each{|n| n.update_attributes(:listing_number =>"TM#{n.created_at.year})}
the question how do i update the previous record at once. probably it's pretty basic but can't figure it out. thanks

# This method in Listing Model
def set_listing_number
listing_number="TM#{created_at.year}#{id}"
end
# In controller
Listing.all.each do |listing|
listing.set_listing_number
listing.save
end
or you can refactor this as
Listing.all.each do |listing|
listing.update listing_number: "TM#{listing.created_at.year}"
end

You're calling save on a string. You need listing.save in your code.

Related

Error in active record when query result from array

If we do on console:
> Product.all == Product.all.to_a
true
But if we do:
> Product.all.to_a.where(name: "something")
!! #<NoMethodError: undefined method `where' for #<Array:0x000055b42c6a3f20>>
That's not a problem if we won't run this method 'to_a'.
The point is that on this heroku cache article they show this method bellow to use caching:
def self.all_cached
Rails.cache.fetch('Contact.all') { all.to_a }
end
And the query result that returned from this method cannot use active_record because it gets the same error that I explained before.
My main goal is to use caching and to know if it is possible to overcome this issue with active_record acknowledge as workable query when it is arrayed.
I solved the problem to use activerecord on cached query result with this change:
from:
def self.all_cached
Rails.cache.fetch('Contact.all') { all.to_a }
end
to:
def self.all_cached
Rails.cache.fetch("all_contacts") do
Contact.all
end
end
Now it is not arrayed variable.
This issue is only partially solved once the heroku article told that the best approach is to convert to array:
Note that we cache all.to_a instead of all. This is because since
Rails 4 Model.all is executed lazily and you need to convert
Contact.all into an array with to_a in order to cache the actual
contacts.

Models Logic in View--Rails

My Article model has_many instances of my Comment model, which has a text attribute.
However, in my view, when I call through iteration article.comments.last.text I get undefined method error.
I must say that when I call it through the console, it does return the text attribute.
The log's only relevant response to this error is:
ActionView::Template::Error (undefined method `text' for nil:NilClass):
View code:
- #articles.each do |article|
.article
%comment= article.comments.last.text
Update your view code to following. I hope it works for you.
- #articles.each do |article|
.article
%comment= article.comments.last.try(:text)
You should do some defensive coding when trying something like this. article.comments.last.text. There will always be a possibility when article.comments is blank. It returns an empty array [].So when you execute something like .last.text. It will break the code throwing error.
You can check something like article.comments.present? and then access the last comment.
To add to the accepted answer, the problem is defined with the error:
--
undefined method `text' for nil:NilClass
It means you're calling text on a class / variable / data-set which isn't populated (nil).
As mentioned, the way to do this is to evaluate whether an article has any .comments. Whilst .try(:x) is the best way to do it, the more verbose way is to use conditional logic:
%comment= article.comments.last.text if article.comments.any?
--
it does return the text attribute
Maybe the comment exists, but it isn't associated to article.
Calling article.comments only calls the comments associated to article (through their respective foreign keys). If the comment is not associated to article, it won't appear in the collection.
Thus, if you're checking whether text exists for a comment, you also need to make sure the comment is associated with article. A simple way to do this is through the Rails Console:
$ rails c
$ article = Article.first
$ comment = Comment.first
$ article.comments << comment
First thing to mention is that you have N+1 problem here. You are querying your database on each article to get all it's comments. It's may slowdown your system.
I suggest the next approach for this solution.
Define new relation in Article
class Article < ActiveRecord::Base
has_one :last_comment, -> { where(created_at: :desc) }, class_name: 'Article'
end
Load this relation in your controller
def your_action
# you can continue querying as I show you with 'where' and 'your_scope', the 'includes' is a must to
#articles = Article.includes(:last_comment).where(...).your_scope
...
end
Then in your view just use the next code
- #articles.each do |article|
.article
- if article.last_comment.present?
%comment= article.last_comment.text

Undefined method update when updating a record in Rails

I'm having trouble parsing through a hash and then saving certain parts to my database. I'm able to iterate through it to get to the information that I need. My problem is updating the record in my database. I'm trying to update an existing record in my database based on if the country code for each country matches the country code in the XML parse.
In my controller I have:
class CountriesController < ApplicationController
def index
#countries = Country.all
travel_alerts = request_data('http://travel.state.gov/_res/rss/TAs.xml')
travel_warnings = request_data('http://travel.state.gov/_res/rss/TWs.xml')
# Sets warnings
warnings_array = travel_warnings["rss"]["channel"]["item"]
warnings_array.each do |warning|
#country = Country.find_by(code: warning["identifier"].strip)
#country.update(title: warning["title"],
description: warning["description"])
end
end
end
...
I've tried using .update and .save, but neither works. When I try update I get:
undefined method `update' for nil:NilClass
Does the update method need to be explicitly defined in the Country model? If so, what's the best way to have access to the parsed information since that's being done in the controller?
It raises an error, because Country by given code was not found, then find_by returns nil, on which update method does not exist.
Instead of find_by executrun find_by! - you should get ActiveRecord::RecordNotFound error
If it is expected some countries do not exist put your update statement within if block
if #country
#country.update ...
end

updating column for all users method

I am trying to create a method that will update a column for all my users at a specific time. I am doing this with the 'whenever' gem but I don't really know where to place the method.
My Users table has a column with :grades that I want to update based on another method (grade). In the rails console, when I do:
user.update(:grades => user.grade)
This works fine. When I define the method within the rails console that I want like this:
def update_grades(users)
users.each do |user|
user.update(:grades => user.grade)
end
end
#users = User.all
update_grades(#users)
This works as well and updates the grades for all the users.
The problem is that I don't know where to place this method for it to work in my scheduler. I tried putting it in the user.rb model file but then when I call update_grades(#users) it gives me this error:
NoMethodError: undefined method `update_grades' for main:Object
I changed it to remove the (#users) and try to call update_grades or #users.update_grades neither of these work and I get this error:
NoMethodError: private method `update_grades' called for #<User::ActiveRecord_Relation:0x007fbb753b1b58>
Any ideas where I can place the method so that I can call update_grades(#users) or update_grades?
You can make it a class method on User
class User
def self.update_grades
all.each do |user|
user.update(:grades => user.grade)
end
end
end
This can be called as User.update_gradesa
Consider wrapping it in a transaction to speed it up:
def self.update_grades
transaction do
all.each do |user|
user.update(:grades => user.grade)
end
end
end

Twitter Bootstrap error when running 'bootstrap:themed', with Mongo

This occurs when I try to run rails g bootstrap:themed Associations in my terminal:
C:/Users/ruby/.pik/rubies/Ruby-193-p327/lib/ruby/gems/1.9.1/gems/twitter-bootstrap-rails-2.1.9/lib/generators/bootstrap/themed/themed_generator.rb:87:in `block in retrieve_columns': undefined method `columns' for Association:Class (NoMethodError)
It just can't seem to work, I've tried many ways, searched everywhere, never succesful. I'm using Mongo.
I just got exact same error. I created two identical project - one with mongoid and one without. I only get the error on the mongoid project.
Found this workaround that seems to solve the problem:
Remove references to ActiveRecord (around line 87) in the file:
/home/ubuntu/.rvm/gems/ruby-1.9.3-p327/bundler/gems/twitter-bootstrap-rails-b8b7eb22614a/lib/generators/bootstrap/themed/themed_generator.rb
I changed ...
def retrieve_columns
if defined?(ActiveRecord)
rescue_block ActiveRecord::StatementInvalid do
#model_name.constantize.columns
end
else
rescue_block do
#model_name.constantize.fields.map {|c| c[1] }
end
end
end
to this ...
def retrieve_columns
rescue_block do
#model_name.constantize.fields.map {|c| c[1] }
end
end
To get the views working I needed to make sure that my model class had a created_at field that wasn't nil (alternatively edit the generated views).
Hope this helps.
PS: Wow ... it seems you've got twitter-bootstrap-rails working on windows - I didn't know that was possible!

Resources