I haven't found a clear explanation for what the association method does and how to use it properly -- I see several examples where model Alpha has_many Beta and then when creating a new Beta using a Factory we say beta.association :alpha or something along those lines. But isn't Alpha also associated with Beta (Beta belongs_to Alpha)... so I'm just pretty confused. I thought an association (at least in normal English) is usually mutual, so I am not understanding what this method is supposed to do. Can someone please clarify this?
In addition to understanding it on a broad conceptual level, I would also like to know exactly what it does on a syntactical level (ie. is it adding methods like attr_accessor does? like what is this actually doing??)
Sorry I just have not found a clear explanation for this -- if anyone can explain this to me that would be great!!
From my experience you define "association" in FactoryGirl when you need to instantiate associated object while creating other object by factory, and without this association your new object would be invalid.
Let's say you have Company and Worker models, and in your application you have validations which prevent creating Worker with invalid company_id attribute. You can have Company without workers (that's why you shouldn't define association for workers in factory), but you can't have Worker without Company. You then add association in factory to lazy-instantiate Company for every Worker created.
So to summarize - you define association when you have belongs_to in model, and when your association in model also have presence validation.
Related
This is a simple question but I can't find a straight answer anywhere. It's the base concepts I'm interested in so I've kept it simple...
Say I have a 'post' model for a blog, I'm going to have to use a getAllPosts method at some point - retrieving all the posts from the database, and instantiating a Post object for each so I can display a list of them
If a User owned the Posts then knowing where to put this code would be easy - you'd put a getPosts method on the User model and it would return posts belonging to the user.
The question is: Where do you put methods which handle multiple instances of a Model which aren't owned by anything else in the system?
I've considered these options, and listed my concerns:
Just interact with the database from the index method of a PostController. Surely this can't be right because my Controller shouldn't know about the database, I want them decoupled so that future changes won't be hard to implement
Put a getAll method on the Post model as a static method so that you don't need a Post instance to call it. I've read that static methods make things hard to test and that this is against the principles of OOP
Create a PostRepository with a getAllPosts method. This is my current preferred option but having read up about the repository pattern - with its links to unit of work etc. - it feels like overkill. It would also implement similar methods to those I think I'm supposed to have on the Post model, like update and delete
Create a PostCollection class which has responsibility for anything relating to many Posts, and leave the Post class for anything related to a single Post. This is ok, but I haven't seen any mention of it elsewhere
Create a pointless 'owner' of the posts, like a User or Admin class, of which there is only 1 instance, and it simply houses a getUserPosts method
What's the simplest way to solve this?
Option #3 is the best one, and it's preferred to create Unit of Work pattern in case there is transactional operations.
Another option is to create a service layer (ManagePostsService) which may be used as a DomainService that works with multiple entities, this service will invoke the repository or unit of work, see Domain-Driven Design.
Bear in mind, that in all cases it's not preferred to communicate with data sources e.g.database from Domain Entities (User, Post), these are independent and should only contain their natural behavior through encapsulation.
You may find these architectures helpful:Clean Architecture, The Onion Architecture, Hexagonal architecture and Ports & Adapters Architecture
I am having trouble figuring out why rails is showing validation errors. The relevant details of my app are as follows:
Programs are offered in Sessions (many to many) (ProgramSession associates Program and Session)
Courses are offered by Instructors (many to many) (CourseInstructor associates Course and Instructors)
Exams are conducted and each Exam has many Papers.
I have generated all resources using scaffold.
Problem: when I try to create a new paper Rails shows
2 errors prohibited this paper from being saved
- Program session must exist
- Course instructor must exist
Entire code is available on github repo, and has also been deployed on heroku
I would really appreciate all the help I can get.
Making following changes in app/models/paper.rb fixed the problem:
belongs_to :program_session, foreign_key: 'program_sessions_id'
belongs_to :course_instructor, foreign_key: 'course_instructors_id'
check if the value and id of foreign-key is the same as it has set in DB.
and can you provide the controller and model to troubleshoot more
I am new to ruby and rails development and have this question in mind. If i have a concern with scope created say latest_records which gives me latest data for a customer
Now what is the best practice to use scope in this situation. should scopes be in model or in controller?
I read some online articles and it talks about fat model and skinny controller and since scopes are do database related work then i am guessing they should be in model.
Any suggestions or thoughts?
You guessed it right.
Scopes belong to model and needs active record classs object to work on.
Scopes are nothing but a activerecord query divided in parts and it helps look your query elegant and dry.
e.g.
If you want to get users with confirmed emails, you would:
User.where(confirmed: true)
But with scopes in your user model:
scope :confirmed, -> { where(confirmed: true) }
And you would simply:
User.confirmed
For more detailed please refer this answer here
A scope could only be defined in a model so it would have to be on a model.
I want all of my db interactions for a specific model to go through the mongo primary in my cluster, so I set the model to use strong consistency.
class Photo
include Mongoid::Document
with consistency: :strong
field :number, type: Integer
# let's say a photo number is unique in the db
validate :unique_number
end
But this does not seem to work, because I still run into validation errors when I save two Photo photos very close together.
photo1 # db has number=1 for this object
photo1.update_attributes(number: 2)
photo2.number = 1
photo2.save! # <= this raises a validation exception
My understanding of strong consistency is that there shouldn't be a race here. It should do the write and then do the read, and since it's all off the primary there shouldn't be a conflict. What am I missing?
What you area experiencing looks like it is persistence. The update_attributes is making an atomic change on the document, and it looks like it is not updating the persisted photo1.Your photo2 validation is fired from within the persistence (i.e. on the rails server and not in mongo) and is looking at the records it has. If you ran photo1.reload after the photo1.update_attributes this may sort this for you.
It's been a while since I used mongoid 3, 4 has been the staple for a while and recently upgraded to 5.You won't find this type of issue in mongoid 4.
If the reload does not help, please output photo2.errors so I can pin point the issue for you.
It turns out calling with(consistency: :strong) at the class level only applies it to the next query. So the class method is called when the class is loaded, setting strong consistency for the first query,
but subsequent queries don't trigger the same class method leaving their persistence operations to operate with eventual consistency. From the Mongoid 3.1.7 documentation:
Tell the next persistance [sic] operation to store in a specific collection, database or session.
This method does not enforce the persistence options that can be passed in (like a few other methods in the class), so we can also pass in consistency: :strong.
Hack Fix
In order to apply this to every* persistence operation, I added it to a default_scope.
class App
default_scope -> { with(consistency: :strong); where({}) }
end
In this case, the default scope expects to have a Mongoid Criteria object returned, so we return a noop where clause after setting the consistency level on the in-progress persistence operation.
* This will not be applied if the developer decides to call unscoped and strip off the default_scope.
Question:
In a post-attr_accessible Rails 4 world, in what way do you recommend, if at all, annotating your ActiveRecord model class files to communicate its (database) attributes?
Further Thoughts
As part of a Rails 3 -> 4 upgrade, we are making a switch, and happily so, away from attr_accessible and to strong parameters in the controller. I understand and agree with the improvement in security via this switch. If you want to know more about this, the information is out there, and it's not hard to find.
But, I enjoyed, in my Rails 3 world, having those reminders of what attributes made up a class up there at the top of the model file. Especially since we're moving toward a world in which ActiveRecord classes are just DAOs, what else is the class but a collection of database attributes? I don't want to go to the schema.rb file just to remember them.
Am I thinking about this incorrectly? In a DAO world, should I be creating my ActiveRecord model class file and then never opening it again?
I know about the annotate_models gem and used it way back in the day. I was not a fan of having the attributes described in commented-out lines. (unreadable, hackish, fragile)
Thoughts? Opinions?
How about:
Person.column_names
If you are using an IDE or and editor that has a console feature this becomes an easy way to be reminded what attributes there are. I am no Ruby or Rails expert, still pretty new here, but I've been using Rails 4 almost exclusively and it just seems like you wouldn't need to see the attributes that often in the model. The params get whitelisted in the controller because that is where they will usually be used, no? If you don't want to use comments you could store an array of the attributes in the model:
my_attr = [:fname, :lname, :age, :height, :weight]
But is that really any more useful than a comment? Would there be a case of attributes that would have been in attr_accessible that wouldn't be in your whitelist in your controller? It would be trick if you put some code in a rake task that would run every time you ran
rake db:...
that would update the my_attr array in your model so you wouldn't have to remember to do it when you modified the model. I go into my models to add class methods and scopes, so I do see a value in it. But I work in RubyMine so I just click on the DB tab on the left side if I need to be reminded of columns that aren't in my whitelist.