undefined method `each' for true:TrueClass when adding boolean values - ruby

In the console of my application I get "undefined method `each' for true:TrueClass" when attempting to set a Boolean to true or false.
For instance if I do
Man.create(guy: true) # or
Man.create(:guy => true) # etc
I have not worked on this application for several months and I believe everything was working fine before I stopped work on it. I am pretty new to Ruby and have limited programming knowledge so any help is much appreciated. creating rows and providing only string or integer values works fine. I am using an SQLite3 database if that matters.
guy is a Boolean
class AddMan < ActiveRecord::Migration
def change
create_table :men do |t|
t.boolean :guy
t.boolean :girl
t.boolean :dude
t.boolean :lady
t.boolean :albert
t.timestamps
end
end
end
class Man < ActiveRecord::Base
has_many :guys
has_many :girls
end

This:
has_many :guys
has_many :girls
assumes, by Rails convention, the presence of Integer columns :guy_id and girl_id, which should be foreign keys into the guys and girls tables, respectively. These are not present in your schema, so I assume that's the root cause of the error you're seeing.
In general, try avoiding column names that may be in conflict with other models (I assume you have models named Guy and Girl. Try renaming your boolean columns to something like is_guy and is_girl.

From your Man Model I assumes that you have guys and girls different tables. And from your console it seems that you want to assign value to Man table's guy attribute.
If this is the case then you can assign value to your Man table's guy attribute like
man = Man.new
man.guy = true

Related

Rails Newby: Strong parameters in Rails 5 not letting specified parameter Through - HABTM

I'm new to rails, and I'm currently trying to develop an API based app using Rails 5, on one of my controllers I have a function to filter the allow parameters like so
def provider_params
params.require(:provider).permit(:name, :phone, :email, :website, :address, :provider_id, :bio, :specialty_ids => [])
end
Then posting from Paw I noticed that the arguments that are not attributes of the table are no included in provider_params, the parameter I'm supposed to receive is an array, which is defined by a HABTM relation-ship.
This is how my models look like
specialty.rb
class Specialty < ApplicationRecord
has_and_belongs_to_many :providers
end
provider.rb
class Provider < ApplicationRecord
has_and_belongs_to_many :specialties
end
And this is how the join table was created via migration
class CreateProvidersSpecialties < ActiveRecord::Migration[5.0]
def change
create_table :providers_specialties, :id => false do |t|
t.integer :provider_id
t.integer :specialty_id
end
add_index :providers_specialties, :provider_id
add_index :providers_specialties, :specialty_id
end
end
The JSON I'm posting
{
"name": "the name",
"specialty_ids": [
1,
2
]
}
So as I mentioned, the array specialty_ids doesn't seem to be coming through, and even if it did, I suspect there's still something else I need to do in order for rails to insert the content of specialty_ids in the ProvidersSpecialties Table
So the problem was finally solved by removing the requir call from the method provider_params, since I wasn't wrapping the json-payload in a provider key. Apparently once you add the require(:key) call you would only be able to add parameters that belong to the Model, which is weird since an error should be raised when the key is not present, what was the case with my payload, lacking the provider key.

How can I create a field using the id from the same row in ActiveRecord Ruby

-----UPDATE-----
Well, seems that the problem was in last.id. When database is created works OK, but when not fails. Now the question is different: How can I create a field using the id from the same row?
--------ORIGINAL------
I'm working with active record in pure ruby (without Rails), and I'm literally getting crazy with this.
This is my code
class Enviroment < ActiveRecord::Base
#self.table_name = 'enviroments'
self.connection.create_table(:enviroments, :force=>true) do |t|
t.column :name, :string, :default=>'env-'+ (last.id-1).to_s
t.column :ssh, :string, :default=>nil
end
end
and here the error:
ActiveRecord::StatementInvalid: Could not find table 'enviroments'
from /usr/lib/ruby/gems/1.8/gems/activerecord-3.2.3/lib/active_record/connection_adapters/sqlite_adapter.rb:465:in `table_structure'
if I useself.table_name = 'enviroments' still not working. I've updated the gems and neither.
I'm newbie with ruby and databases, but I can't understand this problem, I think this same code worked in the past :S
Your code to create the table (very odd to have that in the model by the way) is calling last.id, and of course to call last the table must already exist.
Because you're passing :force => true to create_table you'll actually destroy the table if it already exists.
You could probably make your code work if you stashed the value of last.id in a local variable before the call to create_table but I don't understand why you are creating tables like this.
Finally, this was my solution:
class Enviroment < ActiveRecord::Base
after_create :create_default
private
def create_default
if name == nil
s = 'env-' + self.id.to_s
self.name = s
self.save
end
end
end
class CreateSchema < ActiveRecord::Migration
create_table(:enviroments, :force=>true) do |t|
t.column :name, :string, :default=>nil
t.column :ssh, :string, :default=>nil
end

(Object doesn't support #inspect)

I have a simple case, involving two model classes:
class Game < ActiveRecord::Base
has_many :snapshots
def initialize(params={})
# ...
end
end
class Snapshot < ActiveRecord::Base
belongs_to :game
def initialize(params={})
# ...
end
end
with these migrations:
class CreateGames < ActiveRecord::Migration
def change
create_table :games do |t|
t.string :name
t.string :difficulty
t.string :status
t.timestamps
end
end
end
class CreateSnapshots < ActiveRecord::Migration
def change
create_table :snapshots do |t|
t.integer :game_id
t.integer :branch_mark
t.string :previous_state
t.integer :new_row
t.integer :new_column
t.integer :new_value
t.timestamps
end
end
end
If I attempt to create a Snapshot instance in rails console, using
Snapshot.new
I get
(Object doesn't support #inspect)
Now for the good part. If I comment out the initialize method in snapshot.rb, then Snapshot.new works. Why is this happening?
BTW I am using Rails 3.1, and Ruby 1.9.2
This is happening because you override the initialize method of your base class (ActiveRecord::Base). Instance variables defined in your base class will not get initialized and #inspect will fail.
To fix this problem you need to call super in your sub class:
class Game < ActiveRecord::Base
has_many :snapshots
def initialize(params={})
super(params)
# ...
end
end
I had this symptom when I had a serialize in a model like this;
serialize :column1, :column2
Needs to be like;
serialize :column1
serialize :column2
I ran into this issue when I used an invalid association name in a joins.
For example,
Book.joins(:authors).first
Should be
Book.joins(:author).first
Assuming a Book model belongs_to an Author model.
This can also happen when you implement after_initialize, particularly if you are attempting to access attributes which were not included in your select. For instance:
after_initialize do |pet|
pet.speak_method ||= bark # default
end
To fix, add a test for whether the attribute exists:
after_initialize do |pet|
pet.speak_method ||= bark if pet.attributes.include? 'speak_method' # default`
end
I'm not sure exactly why, but I got this error when I accidentally misspelled 'belongs_to' as 'belong_to' in the associated class definition.
I believe you forgot to
rails db:migrate
Try calling .valid? on the new object to see if you can get a more helpful error.
In my case, I got this error from a block of code that creates a new instance of one of my models and assigns values to its fields. It turns out that my code was assigning a value to one of the fields that Rails couldn't match with that field's type. Calling valid? on the new object gave me a more helpful error (undefined method `to_f' for #<MatchData...).
I ran into this problem after trying to integrate devise authentication with an existing User model, I solved it by running command below:
$spring stop
Don't know the exact cause but hope it helps someone.
This is a misleading and nonspecific error. For instance, I just got it because I made a scope like this:
scope :posted, -> { where('posted_on_date <= ?', Date.today) }
when it should have been:
scope :posted, -> { where('post_on_date <= ?', Date.today) }
In my case, this was due to my mistakenly using the posted_on_date attribute.
I get this problem if the model contains an after_find.
The same error if you put the attribute type wrong:
attribute :publicar, :integer, default: true
instead of
attribute :publicar, :boolean, default: true
I was getting this error when running an ActiveRecord .where clause/method.
It was simply because there was a typo in the column name. Once I fixed the typo the query worked exactly as expected.
Wrong:
Package.where(scrape_nunber: 2)
Right (fixed typo in column name, and it works now):
Package.where(scrape_number: 2)
Just double check there isn't a typo in your column name(s) in the where clause.

Rails -- self vs. #

I am following Michael Hartl's RoR tutorial, and it is covering the basics of password encryption. This is the User model as it currently stands:
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :name, :email,: password, :password_confirmation
email_regex = /^[A-Za-z0-9._+-]+#[A-Za-z0-9._-]+\.[A-Za-z0-9._-]+[A-Za-z]$/
#tests for valid email addresses.
validates :name, :presence => true,
:length => {:maximum => 50}
validates :email, :presence => true,
:format => {:with => email_regex},
:uniqueness => {:case_sensitive => false}
validates :password, :presence => true,
:length => {:maximum => 20, :minimum => 6},
:confirmation => true
before_save :encrypt_password
private
def encrypt_password
self.encrypted_password = encrypt(password)
end
def encrypt(string)
string
end
end
I posted a previous question about before_save not working, and it turns out that what I had accidentally done is written my encrypt_password as:
def encrypt_password
#encrypted_password = encrypt(password)
end
I understand that if self.encrypted_password sets the encrypted_password attribute, but why does #encrypted_password not do that as well? In the response to the previous post about before_save not working someone said that the instance variable was "forgotten" after the method ended with the way I had originally coded it -- why was this the case? Can someone please explain how self and # work differently in the context of the code above?
NOTE: I already took a look at the posts here and here, but they both say that "self" is calling the attribute = method, and I don't even understand how that method could exist here since I never created it or declared the encrypted_password w/ attr_accessor. So I am still confused, and this is not a re-posting of those questions.
The accessors for encrypted_password have been automatically added by Rails for you because a field by that name exists in the users table.
Any field you add to a table will be automatically made available via self.field_name.
Here is where Michael Hartl's tutorial creates the encrypted_password field in the users table.
Also look at the user_spec.rb (Listing 7.3) in the linked page, where the author is testing for the presence of the encrypted_password field.
UPDATED:
As #mu points out, the # is used for Ruby instance variables (aka "iv"). But encrypted_password is an "attribute" defined by Rails, and is not an instance variable.
If you run User.find(1).instance_variables, you will see that there is an iv called #attributes, which is of type Hash.
Inside that iv is where the encrypted_password is stored. Rails has defined accessor methods for encrypted_password, which gets/sets the data for that
attribute in the #attributes Hash.
Note that you could also get/set the data via #attributes["encrypted_password"] called from within the User class (but the accessor methods are convenient way to do just that).
If you let me, I'd like to rephrase the answer.
I explained in this post, that as soon as you create a (rails-) Model with the same (singular) name as one of the (plural) tablenames of your database, the "magic" of rails will create setters and getters in order to modify your table's records.
This is because your model inherits all methods from the ActiveRecord::Base Class, which defines basic CRUD accessors (Create, Read, Update, Delete).
The key point related to your question, is that you don't know how rails implements the instance variable related to your database table column, And you shouldn't. :) All you have to know is that at that point, you have setters and getters available to CRUD (create, read, update, delete) your database column "encrypted_password".
In your example, maybe rails uses an instance variable called #encrypted_password, maybe rails uses an hash-instance-variable called #attributes["encrypted_password"], or maybe rails uses an instance variable called #you_will_never_guess_encrypted_password.
-
And that's a good point you don't know about the internal rails behavior with instance variables. In 2019 Rails further development may lead the framework to use #complicated-hash-instance-variable to store the encrypted_password value.
In fact the best approach is to let rails manage its "private" "affair" ;) with instance variables, and just use the getter and setter methods it provides to you.
So your application will still work with encrypted_password in the next century (I hope so ^^).
So if you use #encrypted_password it may work with some "imaginary" version of rails and it won't work anymore with other rails versions. Actually with a current version of rails it doesn't work.
-
The second key point is that when you want to use the getter "encrypted_password" Rails created for your encrypted_password database table column, you prefix it with "self" in order to tells Ruby : "ok I want to use the encrypted_password method of my User instance variable."
In Ruby, a method is called by passing its name to a receiver.
You write it like this :
my_receiver.my_method
In your case we pass the method encrypted_password to the User instance variable. But we don't know how this instance variable will be named, so we use the word self to tell Ruby : "I'm talking about any instance variable of the User class that calls the encrypted_password method".
For instance we could have named our instance variable "toto" :
toto = User.new
so toto.encrypted_password would display the encrypted password, and self in this very case in our code would reference toto.
However, thanks to Ruby, if you don't give any receiver when calling a method, Ruby will assume you pass it to self.
Reference : Pragmatic Programmer's guide
So in your example, you even don't need to put "self." as prefix.
You could have it written like this :
class User < ActiveRecord::Base
def encrypt_password
encrypted_password = encrypt(password)
end
end
I hope this helps to clarify this interesting subject.
TL;DR -
Always write self.widget_count = 123 if you intend to save widget_count back to the database.
(But please do read the long answers, as the reason why is valuable to know.)

Ruby grammar question

I'm new to ruby. So I'm confused by the following lines of code:
class CreateProducts < ActiveRecord::Migration
def self.up
create_table :products do |t|
t.string :title
t.text :description
t.string :image_url
t.decimal :price, :precision => 8, :scale => 2
t.timestamps
end
end
def self.down
drop_table :products
end
end
one of the lines makes me most confused is :
t.string :title
I just can't understand it. So could any of you give me some hint on which part of ruby grammar I need to read in order to understand this single line of code? thanks in advance.
This is just normal Ruby messaging syntax.
t.string :title
means
dereference the block local variable t
send the message :string to the object referenced by t and pass the literal symbol :title as the only argument
I'm guessing a bit here, but as a basis for exploration
:title is a Ruby "symbol" - basically a hack to provide higher-efficiency string-like constants - so t.string :title is a bit like calling a t.string("title") in more popular OO languages, and given you seem to be declaring a record structure for the database, I'd say that's adding a field effectively "called" title with type "string".
You will find the answer within Why's poignant guide to Ruby
P.S. It's spelt grammar, but for code we'd usually use the word 'syntax'. :)
Check this out this might prove to be very helpful
This file is called migration file it creates the backend for your app
Another link
to fully understand that file, you need to understand classes, inheritance, modules, method calling, blocks and symbols.

Resources