Rails active admin for a has_many through association - ruby-on-rails

How can I display the extra attribute of the join model(in a has_many through association), in active_admin forms?
f.input :ad_slots
Will only display the ad_slots model, but I have a join table called stream_slots which has an extra column called duration. I want to be able to choose an ad_slot as well as enter the duration.
These are the models:
#live_stream:
has_many :stream_slots, :dependent => :destroy
has_many :ad_slots, :through => :stream_slots
#ad_slot:
has_many :stream_slots, :dependent => :destroy
has_many :live_streams, :through => :stream_slots
#stream_slot:
belongs_to :ad_slot
belongs_to :live_stream
and stream_slot has the ids of the other two models as well as an extra attribute called duration.
Thank you.
-- Tried something else--
Instead of linking to ad_slots, this is what I did:
f.has_many :stream_slots do |association|
association.inputs do
association.input :ad_slot
association.input :duration
end
end
and in LiveStream class, I added:
accepts_nested_attributes_for :stream_slots
This way the form shows the ad_slots for me to choose from, as well as a text field for the extra attribute, however, It fails when I try to save it. I believe I know what the problem is but I don't know how to solve it. It's because the live_stream_id in the stream_slots table is empty. How do set it to the newly created live_stream? (The one I'm creating now..)
Any help would be appreciated..

I got it working, As mentioned in the question the problem was that when the form was submitted, the live_stream_id was empty.
So I just removed the validation in the stream_slot model which says that the live_stream_id must be present and it worked.
Not sure if that's the best way to do it.. but it's working for now.
If anyone has a better solution, please share.

Related

What is the good practice to dynamically add/remove nested attributes in the form in RoR?

Let's say I have three models, Paper, Author, and Authorship. A paper can have several papers, which are recorded through Authorship. To be specific:
class Author < ActiveRecord::Base
has_many :authorships
has_many :papers, :through => :authorships
end
class Paper < ActiveRecord::Base
has_many :authorships, inverse_of: :paper, :dependent => :destroy
has_many :authors, :through => :authorships
accepts_nested_attributes_for :authorships, :allow_destroy => true
end
class Authorship < ActiveRecord::Base
belongs_to :paper
belongs_to :author
validate: rank, presence: true # position of the author
end
Now I want to create/edit a paper. When the form pops out, I hope to dynamically enter any number of authors. The following is an illustration what I want to achieve:
For the sake of simplicity, we just use the author_id in the example. What is a good way to implement _form.html.erb in Paper view? I use nested form in the current implementation, and use javascript to add/remove input tags in html. Right now I don't have any problem to add a new paper, but when I visit edit action and try to remove authors, they are never removed. What is a good practice to achieve my goal?
P.S.
For the remove-the-last-author button, I've tried different combinations to manipulate the input tags in html, including totally removing any input related to one author (authorship_id, author_id, ...) and adding an input which set _destroy as true, all are no luck. Was also wondering how RoR knows when activerecords need to be deleted.
Get rid of the 'delete last author' and add a remove button for each row.
Then add a JQuery handler on each delete button. Give the delete buttons a data-id attribute so you can fetch the row id easily. $('.delete').click(function () { $(this).data('id')
Add a #destroy method on the PapersController that handles AJAX requests and responds with JSON. Delete the author in that method. #author.destroy
See http://guides.rubyonrails.org/working_with_javascript_in_rails.html for more.
Here is an alternate way, without AJAX: http://guides.rubyonrails.org/form_helpers.html#removing-objects

How do I remove a user association without destroying their records?

I am having difficulty with my associations and have been digging around trying to find an answer relevant to my problem. I have a selection box in my form that adds users to a study when it is created. The problem is that if I edit the list and remove a user from a study and then add them back it deletes their answers. I am still learning RoR and have been given the task of getting some existing code to function this way. The study model has many users through answers, so how do I edit the study users without deleting the answers? my form:
= select_tag("users[]", options_for_select(#users.collect { |ff| [ff.full_name, ff.id] }, #study.users.collect { |fs| fs.id }), | {:multiple=>true, :id => "users"}) |
my study.rb:
has_many :users, :through => :answers
has_many :answers, :group => :grouping_number
accepts_nested_attributes_for :answers
my user.rb
has_many :answers
has_many :studies, :through => :answers
my answer.rb
belongs_to :user
belongs_to :study
belongs_to :question
I realize that this may be something simple that I have overlooked, which is often the case when spending too long looking at something, but any point in the right direction would be much appreciated.
You might benefit from using a Soft Delete gem like acts_as_paranoid.
This way the associations will remain intact but be flagged as deleted instead of actually being removed from the database. The benefit of this is you can still query active record for user's answers even after their study association is 'deleted', while the behavior of the association actually having been deleted from the application will remain the same.
Does it make sense, that a User can belong to a study only if he gives answers? I would somehow assume an independent relation UserStudies. In your case as a separate model, not just a has_and_belongs_to_many relationship. This would allow you to have a flag "active" in this model and that way activate or deactivate the relation. Then you just add a condition to your belongs_to association.
That's roughly what gems like those Deefour already recommended would do.

Issues with has_many :through, cache, touch and counter_cache

I have a lot of has_many :through relations in my app. I am extensivley showing informations related to this, such as number of connected objects. Whenever user updates the relation, join table is modified, and I can catch this my Sweepers.
The problem is, that join table entries are deleted, not destroyed. If relation is gone, I have no resonable way to detect this, and I am displaying misleading informations from the cache. Everything like :touch => true, or :counter_cache => true works partialy. It's get incremented if relations are updated or created. But if user removes relation nothing happens. :counter_cache is getting broken, :touch doesn't trigger.
The garbage solution is to call .touch in the controller, when the main model is saved. This kind of works, but it seems really non-professional. This should be in the model logic, not in the controllers.
I feel like I am missing something big, but cant get my head over this. Anyone could put some insight on this problem?
Monkey patching Active Record isn't necessary. When defining your association, set the :dependent option to :destroy.
class Book < ActiveRecord::Base
has_many :authorships, :dependent => :destroy
has_many :authors, :through => :authorships, :dependent => :destroy
end
Check the monkey-patch that Mark S. wrote to answer his own question: How to create a full Audit log in Rails for every table?
ActiveRecord::Associations::HasManyThroughAssociation.class_eval do
def delete_records(records)
klass = #reflection.through_reflection.klass
records.each do |associate|
klass.destroy_all(construct_join_attributes(associate))
end
end
end
It may be useful for your problem as well. Note that this was in Rails 2.. things may be different if you're already using Rails 3.

Rails using a join model attribute in a condition for a find

I'm using a :has_many, :through association to link two models, User and Place
It looks like this -
In User:
has_many :user_places
has_many :places, :through=>:user_places
In Place:
has_many :user_places
has_many :users, :through=>:user_places
In User_Place
belongs_to :user
belongs_to :place
belongs_to :place_status
On that last one note the place_status.
I want to write a find that returns all places associated to a user with a particular place_status_id.
Place_Status_id is on the join model, user_place.
So basically I want
User.places.where(:place_status_id=>1)
(in rails 3)
but i get an error with that because place_status_id isnt on the place model.
Any ideas? Thanks all.
I believe you can do your find this way
#user.places.joins(:user_places).where(:user_places => {:place_status_id => 1})
I've never used Rails 3, so I'm sorry if there's any errors.

ActiveScaffold: How to create a drop-down select for polymorphic association?

I'm trying to create a drop-down select box for a polymorphic association with ActiveScaffold.
I have:
class Award
belongs_to :sponsorship, :polymorphic => :true
end
class Organization
has_many :awards, :as => :sponsorship
end
class Individual
has_many :awards, :as => :sponsorship
end
While trying to create a select drop-down box in awards_controller
with:
config.columns[:sponsorship].form_ui = :select
I get the following error:
ActionView::TemplateError
(uninitialized constant
Award::Sponsorship)
I'm not sure if it's something I'm not doing right or what I'm trying
to accomplish not directly supported in AS.
Would really appreciate some advice.
I'm not familiar with ActiveScaffold... But, a quick pass in their documentation revealed a section about has_many :through which I am familiar with from ActiveRecords... so for what it's worth, is it possible that your polymorphic associations should be written like this?:
class Organization
has_many :awards, :through => :sponsorship
end
class Individual
has_many :awards, :through => :sponsorship
end
I'm not sure of what you're trying to do, but rails is indeed true when saying that there is no ":sponsorship'.
When polymorphism is used, rails automatically create two columns, in your case : *sponsorship_id* and *sponsorship_type*.
You may want to use one of those.
However, I'm not familiar with ActiveScaffold form_ui, so I cannot help you further.
I am getting this error, but only if I have an instance of Award with no sponsorship (my names are different...). So presumably the OP and follow up posters got past this, but for future readers, make sure you don't create an instance of the dependent model when using a polymorphic association with active_scaffold...

Resources