ActiveAdmin doesn't recognize "self" within a model - ruby-on-rails

When I GET /admin/consoles/1/edit, for instance, this happens:
Couldn't find Brand with 'id'=
And then it is highlighting the following code fragment which I have in
/app/models/console.rb:
def full_name
brand = Brand.find(self.brand_id).name
"#{brand} #{self.name}"
end
Seems like it isn't recognizing self.brand_id. Ideas?

I would need to see your app/models/console.rb to be sure, but it seems that you should have a belongs_to relation and then you could just use that relation ...like this:
class Console < ActiveRecord::Base
belongs_to :brand
def full_name
"#{brand.name} #{name}"
end
end
But maybe you should have something guarding that like this:
def full_name
("#{brand.name} " if brand.present?) << "#{name}"
end

You could avoid the error with a test for the presence of brand_id parameter:
def full_name
if self.brand_id.present?
brand = Brand.find(self.brand_id).name
"#{brand} #{self.name}"
else
self.name #or other combination of parameters not using the brand model
end
end
Let us know if this helps you.

Related

How to get attribute of object in Model - Ruby on Rails

How can I get the attribute first_name of an entity called Applicant when I'm in a different model called Billing. So far I am able to make it work however, what is returned is the object and not only the attribute.
The following is my code:
class Billing < ActiveRecord::Base
def self.to_csv
attributes=%w{tenant bill_type_dec total_amount created_at datetime_paid paid }
CSV.generate(headers:true) do |csv|
csv<<attributes
all.each do |bill|
csv <<attributes.map{|attr| bill.send(attr)}
end
end
end
def bill_type_dec
if bill_type!=nil
if bill_type==1
"Water"
else
"Electricity"
end
else
"#{description}"
end
end
def tenant
#applicants=Applicant.where(id: tenant_id)
#applicants.each do |appli|
"#{appli.first_name}"
end
end
end
You probably want to use .map instead of .each.
You can get all the names of the applicants in an array by doing this:
#applicants.map { |appli| appli.first_name }
#=> ['John', 'Mary']
As you can see, .each returns the array itself.
.map will return the array generated by executing the block.
Or use pluck and avoid creating the ruby objects
def tenant
Applicant.where(id: tenant_id).pluck(:first_name)
end
BTW - I see you have a tenant_id, if that means you have a belongs_to :tenant on the Billing class, you will want to pick a different method name (maybe "tenant_first_names"). If this is the case, and tenant has_many :applicants you can do this:
def tenant_first_names
tenant.applicants.pluck(:first_name)
end

Rails when creating record, inserting belongs_to association

i have a question about associations in rails. The situation is the following:
Models:
class Character < ActiveRecord::Base
has_one :character_stats
end
class CharacterStats < ActiveRecord::Base
belongs_to :character
end
Now i need to create stats when a new character is created.
What i doo is this at the moment, i feel like this is a workaround with rails. Is there a more "raily" way to do this?
after_save :character_init
def character_init
create_stats
end
def create_stats
stats = CharacterStats.new
stats.character_id = self.id // this bothers me!
stats.save
end
But i feel there should be something like this:
stats.character << self
Thank You in advance :)
EDIT:
here is how my model look in real life:
def create_stats
race_stats = Race.find(race_id).race_stats
class_stats = RaceClass.find(race_class_id).class_stats
stats = CharacterStats.new
stats.character_id = self.id
stats.health = race_stats.health + class_stats.health
stats.mana = race_stats.mana + class_stats.mana
stats.intellect = race_stats.intellect + class_stats.intellect
stats.armor = race_stats.armor + class_stats.armor
stats.magic_resist = race_stats.magic_resist + class_stats.magic_resist
stats.attack = race_stats.attack + class_stats.attack
stats.defence = race_stats.defence + class_stats.defence
stats.save
self.character_stats_id = stats.id
end
first of all if you want to create CharacterStats after Character is created use after_create callback. About your question you can use ActiveRecord methods which looks like create_character_stats for creating model and build_character_stats for initializing model. So you can change your create_stats method to something like this
def create_stats
self.create_character_stats
end
or you can change your after callback to this
after_create :create_character_stats
and then you don't need any method for this, but in this case you don't have ability to pass attributes to model creating.
also this question mentioned here Using build with a has_one association in rails
in rails way you can use the build_association method refer doc. Also the association should be created only when parent object is created so use after_create callback
class Character < ActiveRecord::Base
has_one :character_stats
after_create :create_stats
def create_stats
state = self.build_character_stats({}) # empty hash as you are not passing any attributes
state.save
end
end
Also, the model name CharacterStats looks plural and that can violate the naming convention and can cause some issue like resolving association class on run time and so.

Is possible to append a key value to an ActiveRecord object

I want to have an object that has an associated value added to it.
This is what I am attempting to do:
#users = #search.results
#user_results = []
#users.each do |user|
#user_results = #user_results.push user << {photo_url: UsersPhoto.find_by_user_id(user.id).image_name}
end
I'm getting:
NoMethodError (undefined method `<<' for #):
Is there a way to do something like this?
This is what associations are for. You should just add an association to your User for the UsersPhoto you're trying to find, and use #user.users_photo.image_name.
class User < ActiveRecord::Base
has_one :users_photo
end
Failing that, add a photo_url method to your User model, which wraps up the UsersPhoto.find...:
class User < ActiveRecord::Base
def photo_url
UsersPhoto.find_by_user_id(id).image_name
end
end
Failing that, you can do what you're trying to do, but you'll need to add a attr_accessor :photo_url to your User model, and your syntax is all wrong:
class User < ActiveRecord::Base
attr_accessor :photo_url
end
#users.each do |user|
user.photo_url = UsersPhoto.find_by_user_id(user.id).image_name
end
Why don't you use the .pluck method?
#users = #search.results
#user_results = UsersPhoto.where(user_id: #users.pluck(:id) ).select(:image_name)
To explain, at least from what I am understanding, you want an array of image_names for the results #users. So just get their ids, find those UsersPhotos that match those ids and just get the image_name column

Mongoid: cannot embed different classes in one array

I have Mongoid classes as follows:
class Order
include Mongoid::Document
embeds_many :animals
end
class Animal
include Mongoid::Document
embedded_in :order
def self.has_gender
field :gender, type: String
end
end
class Deer < Animal
has_gender
end
and when I call animals on any order, even empty one:
Order.new.animals
I get the following error:
undefined method `has_gender' for Deer:Class
Any ideas?
The problem is somewhere else. Your code works on my machine. (I'm using Mongoid 3.0-rc, though).
order = Order.new
order.animals << Animal.new
order.animals << Deer.new
order.save
puts Order.first.animals
# >> #<Animal:0x007fca04bae890>
# >> #<Deer:0x007fca04bb4b50>
I think that the problem is in the way I create sub-classes:
class Game
include Mongoid::Document
TYPES = {'deer' => Deer, 'pig' => Pig, 'duck' => Duck}
def self.new_of_type(type, attrs={})
TYPES[type].new attrs
end
end
because when I commented out line when I define TYPES, error disappeared, so the problem may be with calling subclasses when defining TYPES (Deer, Pig, Duck).
Any ideas for a better solution for creating sub-classes? i'm doing it this way in controller:
class GamesController < ApplicationController
def create
#game = Game.new_of_type params[:type], params[:game]
#game.save
end
end

Stack level too deep error in Ruby on Rails

I'm having a stack level too deep error using Ruby 1.8.7 with Rails
3.0.4 and with the rails console I performed the following commands.
leo%>rails console
Loading development environment (Rails 3.0.4)
ruby-1.8.7-head > leo = Organization.find(1)
SystemStackError: stack level too deep
from /app/models/organization.rb:105:in `parents'
Here is the object that is having issues..
class Organization < ActiveRecord::Base
has_many :group_organizations, :dependent =>
:delete_all
has_many :groups, :through => :group_organizations
has_many :orders
has_many :product_contracts
has_many :people
accepts_nested_attributes_for :people
has_many :addresses
accepts_nested_attributes_for :addresses
has_many :organizations
has_many :departments
has_many :organization_credits
has_many :documents
validates_presence_of :name
def self.parents
#organizations = Organization.where("is_company = ?",true)
##organization_parents = []
select_choice = I18n.t("select") + " "+ I18n.t("segments.description")
#organization_parents = [select_choice]
for organization in #organizations
#organization_parents << [organization.name, organization.id]
end
return #organization_parents
end
This error generally happens when you accidentally recursively changing an attribute. If you have a username attribute in User model, and a virtual attribute named username, that is directly changing the username, you end up calling the virtual, the virtual calls the virtual again and so on.. Therefore, take a look on whether something like that happens somewhere in your code.
The stack level too deep error occurs also, if you want to destroy a record and you have an association with :dependent => :destroy to another model. If the other model has a association with :dependent => :destroy back to this model, the stack level is too deep, too.
I had a "stack-level too deep" issue too. it was due to recursiveness in one of my functions and had been caused by a typo as you can see from below:
def has_password?(submitted_password)
encrypt_password == encrypt(submitted_password)
end
private
def encrypt_password
self.salt = make_salt unless has_password?(password)
self.encrypted_password = encrypt(password)
end
I realised I had to change the second line to encrypted and it worked. Just checkout for recursion in your code it must be happening somewhere. Unfortunately I can't be of better use since I can't look at all your code files.
I was getting same stack level too deep error & it turns out that the issue was of recurring rendering of a partial.
I happened to call render a_partial in main view and then in the partial, I accidentally called the same partial again.
HTH
As you are not showing all the code, I can only speculate that you have defined inspect or to_s to build a string containing, among other things the parents.
Your current parents method doesn't seem to be doing anything reasonable, as it returns all organisations that are companies, no matter which association you start from. Thus, any company has itself as parent. Attempting to convert it to string will induce an infinite loop to try to show the parents' of the parents' of ...
In any case, the bulk of your parents method should be in a helper, called something like options_for_parents_select, because that's what it seems to be doing? Even then, the first empty choice should be passed as allow_null to select.
The fact that it sets instance variables is a code smell.
Good luck
I've found the solution to this issue...
I'm using Rails 3 and my class looks like this (and the problematic methods was this too)
class Organization < ActiveRecord::Base
def self.parents
#organizations = self.find :all, :conditions => ['is_company = ? ',true]
select_choice = I18n.t("select") + " "+ I18n.t("segments.description")
#organization_parents = [select_choice]
for organization in #organizations
#organization_parents << [organization.name, organization.id]
end
return #organization_parents
end
#...
end
I did have to hack a lot in the code to find out something was wrong with the named_scope on the line
#organizations = self.find :all, :conditions => ['is_company = ? ',true]
So I had to change it to something like this
#organizations = Organization.where("is_company = ?",true)
But it was wrong too.. So I decided to add an scope for this below the class name so the final code looks like this:
class Organization < ActiveRecord::Base
scope :company, where("is_company = ?",true)
def self.parents
#organizations = self.company
select_choice = I18n.t("select") + " "+ I18n.t("segments.description")
#organization_parents = [select_choice]
for organization in #organizations
#organization_parents << [organization.name, organization.id]
end
return #organization_parents
end
#...
end
So using this line with the scope
#organizations = self.company
it worked flawlessly in every part of the code.
I was wondering if the named_scope is deprecated when using class methods or they are not supported from now and throws an error and not a warning before
Thanks for your help
Leo
If you are getting this error it means rails version that you are using in your application is not compatible with Ruby Version.
Solutions you can use to solve this issue.
1) You need to downgrade the ruby version to older version.
2) or you need to upgrade Rails to latest version.
I got this error when incorrectly creating a has_many relationship like this:
has_many :foos, through: foo
So don't put the same model as 'through' or it will loop endlessly.

Resources