Polymorphic join table and nested forms - ruby-on-rails

I don't know what's the best way to solve this problem and I'll appreciate your help.
This is what I want to achieve:
There is an Act model. And it has many Organizations.
An Organization can have many Groups and also, a Group can have many Subgroups.
The Groups are loaded dynamically depending on the selected Organization, and the Subgroups are also loaded depending on the selected Group.
An Organization could have a Group or not, and also a Group could have a Subgroupor not
Here you are a mock-up of what I have explained above:
In the new Act form there is a section to add Organizations, something like this:
When you write an Organization it loads the options for the Group selector, and the same happens with a selected Group and the Subgroup selector:
When you click the add button, a new Organization section appears
A field can be empty. (This is a valid form)
Also, If you want to edit the Act, the form should show the Organizations added before:
I have this DB:
ActOrganizations is a polymorphic table, and also a join table
My main problems are about the form: how to build it to retrieve and persist the data easily and how to retrieve the stored Organizations to show them in the edit form. (I'm using simple-form)
I tried many approaches, but they were not very elegant. I'd like to know the closest way to the "rails-way" to do this.
Thank you very much for your time

Related

Octopus gem dynamically select shard for an associated model based on shard_id

We have a users table. Users have many listings.
We'd like to shard the association model Listing such that all users stay on database "master" shard. Users will get a shard_id column and listings will be split into different databases "shard1", "shard2".
We can augment our code to access the listings on the correct shard using the using method:
Listing.where(user: current_user).using(current_user.shard_id)
However that is a big code change. Ideally we want to just keep using our existing association statements like this:
current_user.listings
And have it automatically use current_user.shard_id beneath the hood.
Any suggestions for doing this?
According to the documentation, current_user.listings should work out of the box.
Octopus also handles associations. When you try to get a object that is associated to another object, you could use normal ActiveRecord syntax to get the objects
https://github.com/thiagopradi/octopus/wiki/How-Octopus-Works

Rails, managing history of model updates

I'm not sure what's the best approach in my situation, I would like an opinion.
My situation is:
I have a "Ticket" model, having several fields of many kinds: text, numerical and associations. Tickets support comments through the acts_as_commentable gem.
The tickets are generated by users, who can comment and modify their own tickets.
Because the fields of a ticket can change over time I would like to allow my users to modify several of them. What I need though is to keep a commented history of all the changes, so that at any moment they can see in a ticket what, why and when was changed, in the comment, timestamp and list of changes that they can see together with the comment.
I was thinking to solve this by generating a "TicketUpdate" model, have the TicketUpdates generated in the Comments form (using fields_for and accepts_nested_attributes_for).
Basically the user could select in a drop down list (i.e. a select tag) the field they want to change, changing the value of the drop down would trigger an event to show an appropriate input field (input for the text and numeric fields, select for the associations) with the old value pre-populated
I could intercept the TicketUpdates in the "comment/create" controller performing the updates.
This approach would look nice and sweet to the user, but I don't see how to implement in a neat or DRY way.
Because ticket has many fields and they are mixed decimals and associations, I would have to implement specific logic for each field, both in the view and in the controller.
I'm not sure if there's maybe a better approach, or there's actually any gem or trick to get this done easily.
anyone got anything to recommend me here?
I'm using rails 3.2.8.

Database schema - polymorphic association vs separate tables

Users have many tasks. (tasks.user_id = user_id)
tasks have many tags (implemented through Acts as taggable on
Users have many lists -> which have many tasks (A list is just a wrapper for multiple tags, for example {List id => 1, name => "shopping vacation summer"} will retrieve all tasks tagged with all of those tags)
If, for example, a user goes to the url tags/shopping%20vacation, my code would do a lookup for:
Task.all.tagged_with(["shopping", "vacation"])
There is no Lookup table or foreign key for task.list_id
I want users to be able to share tasks, lists, and tags with other users.
A user sharing a task shares just that task with another user.
A user sharing a list opens up all the tasks in that list to another user.
A user sharing a tag opens all of that users tasks tagged with that tag to another user.
To me, there are a few options, and I'd like some input on the pluses and minuses of each that I may not have thought about.
One is a distinct table for each shareable item:
shared_tasks: task_id, shared_to_id(or user_id)
shared_lists: list_id, shared_to_id
shared_tags: tag_id, shared_to_id
OR: a polymorphic association with
shareables: shared_id(item_to_share), shared_to_id, shared_type
What are the pluses and minuses of each?
Is there another solution that I haven't thought of?
Personally I would change the schema design. Taking Tasks as an example i would now treat it as a many-to-many relationship with User instead of many-to-1 as it is currently. So this would mean removing column tasks.UserId and adding a new table called UserTasks which links Tasks with Users defined as (UserId, TaskId, IsOwner). IsOwner is set to 1 for the user who the task belongs to and 0 if it is shared but belongs to someone else. This will make queries easier for example you could do do a single select to get both owned and shared tasks rather than 2 separate queries and also avoid union's.

In a single form, linking two instances of two models with habtm

I am using Rails 3.
I have a Product model and a Group model (a group has_many users, through membership).
I would like to build the new.html.erb form for the product model, and at the end of the form, I would like the user to be able to choose members from which group(s) can have access to the product he wants to add.
So, my goal is to list the groups to which the user belongs to, adding a checkbox for each of them. Then, create the associations between the product inserted and the different groups the user selected when the form is submitted, but I really do not understand how to achieve this, as all the documentation I have read use the BUILD or CREATE method that defines a new instance of group, instead of an existing one.
Is it possible with a nested form, and a HABTM relationship between product and group ? Or should I use a nested form with a has_many_through association using new model product_group_relationship ? Or should I use something else than a nested form ?
I'm quite new in Rails and a little bit lost here, so if some experienced guy could guide me a little bit, it would be very much appreciated!
The form_for helper comes with a nice package of extra methods like: fields_for wich makes you able to add nested attributes for has_many_through relations.
I suggest reading these:
http://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for
And make sure you set your model validations accordingly

ActiveAdmin -- How to create join table records?

I have two categories merchants and aliases who have a join table called aliases_merchants
In ActiveAdmin, how can I display a textbox whose content will get entered into the joining table?
I'm able to display the textbox but upon post it doesn't create the record in the joining table in the db.
Ideally, I would love to be able to get the functionality like the following (but I feel ActiveAdmin wouldn't be able to do it)...
I solved this by creating a sidebar and two member functions in the ActiveAdmin resource to accomplish this. Works just described above.

Resources