How do I insert into different tables from one controller? - ruby-on-rails

I'm developing an application to create a fishbone diagram.
I created several models to handle different levels of causes and effects. The thing is, the application will have one form to introduce data to all the different levels, so how can I do it?
Can I have only one controller to insert info into all the different tables?

Some simple inheritance will do the trick if you are going to be treating them with different logic.
Have a base model
class Bone < ActiveRecord::Base
end
Then three that inherit from it.
class BackBone < Person
end
class RibBone < Person
end
class OutSideBone < Person
end
Then you can handle all three of the classes in the person controller using person as the base. Each will also have their own logic if needed.
If need be you can even do a ownership on to itself, which might be helpful in this case.
class Bone < ActiveRecord::Base
has_many :bones
belongs_to :master_bone, :class_name => "Bone", :foreign_key => "bone_id"
end

Related

Should I mock AR associations?

I'm trying to test my Order AR model in "isolation", but because it lives into a complex "context", I need to create a lot of associated AR models before.
My models are:
class Order < ApplicationRecord
belongs_to :registration #it's required!!!
end
class Registration < ApplicationRecord
belongs_to :event #it's required!!!
end
class Event < ApplicationRecord
has_many :registrations
belongs_to :account #An account belongs_to an organization
#This model a couple of required associations also
end
Is some way to "mock" the associations of my Order model??? Should I?
Thanks in advance!
I think, that with proper factory_girl setup, there will be absolutely no issues to easily setup context, that you need. During my experience I haven't faced any cases when associations were stubbed.
From my point of view, if you have some complex method inside your Order model, then you should move it into separate entity (service object, separate library, decorator). Then you can easily test this logic, without any need to setup associations, objects, etc.
I don't remember the last time I really needed to test my modal in isolation after I start making correct design of my application. I suspect, that your issue is also like a bell for you about your design. I treat models only as a set of validations(tested inside rails), associations(tested inside rails) and trivial methods, so usually there is no need to test your models

What is the best way to configure inheritance in this scenario?

So here is the scenario. Lets say that you have 10 different suppliers that provide products that you sell. Now for this scenario assume that each supplier has their own methods for order processing and each require their own class. This is a big assumption, but I am trying to simplify my real scenario without all of the details.
Solution with Single Table Inheritance (STI)
class Supplier < ActiveRecord::Base
has_many :products
# Methods that can be inherited by each supplier go here
end
class MySupplier1 < Supplier
# Custom per-supplier methods go here
end
class MySupplier2 < Supplier
# Custom per-supplier methods go here
end
What is strange about this solution is that you will have 10 rows in your suppliers table. For example, you will never have more than one instance of MySupplier1.
Here is another solution:
Alternative Modular Solution
class Supplier < ActiveRecord::Base
has_many :products
end
class Suppliers::Base
# Methods that can be inherited by each supplier go here
end
class Suppliers::MySupplier1 < Suppliers::Base
# Custom per-supplier methods go here
end
class Suppliers::MySupplier2 < Suppliers::Base
# Custom per-supplier methods go here
end
With this solution, I like that it feels more modular, but the relationship between the ActiveRecord Supplier and the Suppliers::MySupplier1 is really awkward. Basically, I have to store the supplier class in the suppliers table so I know what class to instantiate for processing.
Does anyone think there is a right or wrong or maybe even a better approach?

Best practice about empty belongs_to association

Imagine the following situation:
I have a dog model and a house model. A dog can belong to a house, and a house can have many dogs, so:
Class Dog < ActiveRecord::Base
belongs_to :house
end
Class House < ActiveRecord::Base
has_many :dogs
end
Now, imagine that I also want to create dogs that don't have a house. They don't belong to house. Can I still use that relationship structure and simply don't inform a :house_id when creating it?
Is there a better practice?
Obs.: I used this analogy to simplify my problem, but my real situation is: I have a model a user can generate instances of it. He can also create collections of those instances, but he can leave an instance outside a collection.
Be careful with this in Rails 5...
#belongs_to is required by default
From now on every Rails application will have a new configuration
option config.active_record.belongs_to_required_by_default = true, it
will trigger a validation error when trying to save a model where
belongs_to associations are not present.
config.active_record.belongs_to_required_by_default can be changed to
false and with this keep old Rails behavior or we can disable this
validation on each belongs_to definition, just passing an additional
option optional: true as follows:
class Book < ActiveRecord::Base
belongs_to :author, optional: true
end
from: https://sipsandbits.com/2015/09/21/whats-new-in-rails-5/#belongs_toisrequiredbydefault
I think it is absolutely normal approach.
You can just leave house_id with null value in database for the models which don't belong to other.

ActiveRecord relationships between HAVE and IS

So I have the following models in my Ruby on Rails setup: users and courses
The courses need to have content_managers and those content_managers are made up of several individuals in the users model.
I'm a newbie, so bear with me. I was thinking of creating a new model called content_managers that has a user_id and a course_id that links the two tables. It makes sense to me that courses HAVE content_managers. However from the users model, it doesn't make sense that users HAVE content_managers. Some of them ARE content_managers.
From that point of view I believe I'm thinking about it incorrectly and need to set up my ActiveRecord in a different manner from what I'm envisioning. Any help is appreciated.
Thanks!
There's no "have" or "are" in ActiveRecord, only "has_many", "has_one" and "belongs_to". With those tools you should be able to do what you want.
An example:
class Course < ActiveRecord::Base
has_many :content_managers
end
class ContentManager < ActiveRecord::Base
has_many :content_manager_members
has_many :users,
:through => :content_manager_members,
:source => :user
end
class ContentManagerMember < ActiveRecord::Base
belongs_to :course_manager
belongs_to :user
end
class User < ActiveRecord::Base
has_many :content_manager_members
has_many :content_managers,
:through => :content_manager_members
end
Be sure to index these correctly and you should be fine, though navigating from User to Course will be slow. You may need to cache some of this in order to find the level of performance you want, but that's a separate issue that will be uncovered during testing.
Whenever implementing something like this, be sure to load it up with a sufficient amount of test data that will represent about 10x the anticipated usage level to know where the ceiling is. Some structures perform very well only at trivial dataset sizes, but melt down when exposed to real-world conditions.

Rails STI models with the same name but inheriting from another model

My Rails application uses STI where I have two different types of Customers. One is a Person Customer and the other is a Company Customer.
So in my People controller I want to instantiate a Customer. (So that the type attribute of a Person is Customer).
My Customer model inherits from the Person model. The model filename is called customer.rb In my companies controller I also want to instantiate a Customer, which again uses customer.rb, but this won't work because it inherits from Person still.
How can I use the same model, but each model needs to inherit from another model?
#models/customer.rb
class Customer < Person
end
#models/customer.rb
class Customer < Company
end
I tried moving customer.rb to different directories, e.g. person/, company/ but I'm not sure if this is correct. Maybe I should use modules?
That will not work. You cannot have two distinct classes with the same name, and a class cannot inherit from two classes.
Maybe you can use a polymorphic association between Customer and Person/Company.
class Person
has_many :customers, :as => :customer_entity
end
class Company
has_many :customers, :as => :customer_entity
end
class Customer
belongs_to :customer_entity, :polymorphic => true
end
The reason this won't work is that in the example you gave, the second class definition for Customer will change the inheritance from Person to Company, which is not what you want.
If the polymorphic suggestion won't work for you, another solution would be to create two classes, CustomerPerson and CustomerCompany (i recommend using better names!) and extract out any common functionality to a module and then include/extend it into each class.

Resources