Ruby on Rails - inconsistency when needing to reload model? - ruby-on-rails

I found something which seems a bit confusing to me being new to Rails. I was told I need to do reload! in the console whenever I made a change in the model.
Let's assume I call reload! before these two senarios.
Let's say I have scenario A, with a model with a specific syntax error as such:
class Article < ActiveRecord::Base
validator :title, presence: true
end
Running Article.new(title: "Test 1") will throw a NoMethodError, as it understandably would. But if I then go in and fix the error, even if I don't run reload!, running Article.new(title: "Test 1") works now.
Scenario B, going in the opposite direction. I have a model with the correct syntax as such:
class Article < ActiveRecord::Base
validates :title, presence: true
end
Running Article.new(title: "Test 1") will work with no error, as it should. But if I then go in and change validates to validator. If I don't run reload!, running Article.new(title: "Test 1") still works despite the article.rb file having a syntax error. It isn't until I run reload! explicitly that I now get a NoMethodError.
What's exactly going on here? I know it's very specific, but I don't see why this would be the case. It seems like sometimes you have to run reload! to update the model (like scenario B) and sometimes, like in scenario A, you don't.

In your first example, Rails was not able to load the class because it raised an error. After fixing the error there was no need to class reload because the class was not loaded successfully before.
In your second example, the class was loaded successfully. Therefore you need to call reload! to tell Rails to reload the class into memory.

Related

ActiveRecord::Base.transaction validation missing

Rails 4.1.16 or 4.2.7
Lets, for example, we have
class Foo < ActiveRecord::Base
validate :name, presence: true
end
Then in IRB we will get
Foo.create # => validation error
Foo.transaction{ Foo.create } # COMMIT
I can figure out, that there is no raise in transaction block, it mean, that it will be committed (on course I can use create!, but it does not cancel the question). But validation fails! IMHO this behaviour is not less than strange.
Can you clarify, why it was made in this way? May be I'm do not understood some specific in this case?
It will be perfect, if you know how to make ActiveRecord failing loudly, with no sense of !(bang) at the and of the command.
Thank you!

Why does adding a bang make create work?

Rails convention of adding a bang to the end of a method makes it throw an exception if it fails. But my experience isn't matching that behavior.
My controller for a many-to-many relationship (an audit trail). The relationship object cannot be created, only updated by posting events to the audit trail object. (Which means you create by updating...)
I have a User object and a Foo object I'll call the relationship Bar.
bar=Bar.where(:user_id=>params[:user_id]).where(:foo_id=>params[:foo_id]).first
if bar
authorize! :update, bar
else
user=User.find(params[:user_id])
authorize! :bar_create, user
foo=Foo.find(params[:foo_id])
bar=Bar.create!(:user_id=>user.id, :foo_id=>foo.id)
end
The create method does not work. I debugged, and bar.save worked fine, but the entire point of create is to avoid having to make that second call to save. I experimented, and discovered that create! works just fine.
Edit:
As I continued on, I discovered that create! did not, in fact, always save. No errors in the underlying object, just mysteriously not saved.
I've had to do a create call followed by a save call, which... honestly, I just don't understand.
Edit: Per request, adding model code -- simplified to the relevant statements by removing unnecessary methods, validation calls, and the like. (While writing this, I noticed that I haven't yet added the has_many :through calls, but... doesn't seem like those should be relevant to the issue at hand.
class User < ActiveRecord::Base
has_secure_password
has_many :progresses
end
class Bar < ActiveRecord::Base
belongs_to :user
belongs_to :foo
has_many :bar_events
validates :user, :presence=>true
validates :foo, :presence=>true
scope :user_id, -> (user_id){ where user_id: user_id}
scope :foo_id, -> (foo_id){ where foo_id: foo_id}
end
class Foo < ActiveRecord::Base
end
There is a validation error or more in one of the associations in Bar foo or user. Try inspecting those objects:
bar=Bar.create!(:user_id=>user.id, :foo_id=>foo.id)
puts bar.errors.inspect, bar.user.errors.inspect, bar.foo.errors.inspect
That will print the errors of all those objects to the terminal running rails server. The only reason create would not save is due to validation errors in itself or nested associations.

Rails simple validations not working

class User < ActiveRecord::Base
attr_accessible :email, :name
validates :name,:presence=>true,
:length=>{:maximum=>15}
validates :email,:presence=>true,
:length=>{:maximum=>15}
end
I am new to rails and the simplest of the validators are not working. I think I may be making a very silly mistake . I have a User model with 2 attributes only and when I create a new user in ruby console with wrong validations like no name or a longer name than 15 characters it gets added happily Please suggest.I am using rails version:3.2.13 and ruby version:1.9.3
If you are on rails console, be sure to type reload! after making changes to models. In this way, all changes will be reloaded in the console instance.
Moreover, are you sure you are saving these models? You should try something like this:
user = User.new(email: "john.doe#gmail.com")
user.save
If the result of the last line is false, you can view the validation errors with
p user.errors

Parent model method is undefined

I'm an absolute beginner to Ruby on Rails; I literally started last night. I'm following the Getting Started with Rails tutorial, although I've made a few modifications. Instead of a blog with posts and comments, I'm making a simple task-tracking application in which Projects have Tasks associated with them.
Everything was going quite well until step #9 (Deleting Comments). According to the tutorial, I should be able to get the parent model for a comment by calling comment.post, the analogue of which in my case is task.project. But when Rails tries to render the partial in which I've got task.project, it raises a NoMethodError:
undefined method `project' for #<Task:0x7fb0011cf058>
My models are as follows:
class Project < ActiveRecord::Base
validates :name, :presence => true
has_many :tasks, :dependent => :destroy
end
class Task < ActiveRecord::Base
validates :name, :presence => :true
belongs_to :project
end
Using the rails console, I determined that my tasks do have a project_id method which returns the ID of the associated project. Thus, I can get around the problem by using Project.find(task.project_id) instead of task.project in my partial. That seems "wrong," though, and makes me wonder if the relationship between my two models is somehow broken.
What's going on here?
Update: If I comment out the validates line in the Task model, then all of its methods work properly. I don't understand why that is the case, though.
Update 2: Figured it out. I was using the symbol :true instead of the simple boolean value in the validates line of my Task model. Had I paid more attention to the stack trace in the first place, I would have figured it out much sooner. What an embarrassing mistake!
Your code looks perfect. But if you were trying that into console try reloading first and then try again
reload!
task = Task.find(<record-id>)
task.project
It should be working.

How does Ruby on Rails work with an "inclusion" validation?

I am using Ruby on Rails v3.0.9 and I have the following code in a my model:
class User < ActiveRecord::Base
validates :users_role,
:inclusion => {
:in => UserRole.all.map(&:role)
},
:presence => true
end
When I browse an UserRole related page (that is, a page where an user object instance is involved - for example, the RoR conventional "show" or "index" views), and I inspect the log file I see that the UserRole SQL query is performed. That is, the UserRole.all.map(&:role) run.
I would like to know how Ruby on Rails works for the above case. It concerns the performance? Is the UserRole.all.map(&:role) lazy loaded?
In your dev environment you will probably see that query running on any request which validates user, as code is reloaded on each request. Try it in production mode once, it should not happen in that case, as code is loaded once only and you haven't put the query in a lambda. There should be no lazy loading here as you already called map on the resultset.

Resources