I am building a simple sample tracker for a small analytical lab and I'm bashing my head against a problem. Structurally, the database consists of users, batches, samples, instruments, and assays. Please excuse messy or poor code, I'm new to Rails and programming. Generally I know where I'm being sloppy and how to fix it, it's just a matter of me breaking a problem down. Here's some explicit abridged code:
class Batch
belongs_to :user
has_many :samples
has_many :submissions
has_many :assays, :through => :submissions
accepts_nested_attributes_for :samples
accepts_nested_attributes_for :submissions
end
class Assay
belongs_to :instrument
has_many :submissions
has_many :batches, :through => :submissions
end
class Submission
belongs_to :batches
belongs_to :assays
end
I have created a batch submission form that accepts batch information, sample names as a nested attribute, and I'm trying to accept submissions as a nested attribute as well. My form currently looks like this (Please note comment line):
= semantic_form_for @batch do |f|
- @instruments.each do |instrument|
%ol
%li
= instrument.instrument_name
%ol
- instrument.assays.each do |assay|
%li
= assay.assay_name
# Some magic check boxes that fix my problem.
= f.inputs :name => "Batch Info" do
= f.input :sampling_date, :required => false
= f.input :experiment_name, :required => false
= f.input :notes, :as => :text
= f.semantic_fields_for :samples do |sample_form|
= sample_form.input :sample_name
= f.buttons do
= f.commit_button :label => "Submit batch"
What I would like to have is a check box for each assay that passes the assay_ids to the submissions table as a nested batch attribute, magically making sure that each batch is associated with the chosen assays.
My problem is deciding when and how to build the submissions in the controller/model and how to populate them. It seems like I should make some sort of paramater that holds the assay_ids, and use some sort of model callback (befor开发者_JS百科e_create or before_save) that builds a params[assay_ids].length
number of dummy submissions that I can fill with the assay_id params. Unfortunately all my attempts at building a method that does this have been futile.
I've watched all pertinent Railscasts I could find, read API entries, and I have been grinding on this for far too many hours. I can feel the answer on the very tip of my brain, and I am in desperate need of an Aha! moment. Thanks for any help you can provide!
Notice: This method is very brittle! I worked out a solution to make batches a true nested attribute and I will write it up ASAP.
So after a day of thinking the answer popped into my head (I swear I use Stack Overflow to officially start a 12 hour timer on when I'll epiphanically figure out what I got wrong). Here's how I did it:
Essentially I was trying to only make as many submissions as I needed so I didn't end up crapping my database up with empty ones, but I also wanted them built on the fly in-form. Because I didn't want to shove a bunch of extra logic into my view, I set up my magic check box as check_box_tag "assay_ids[]", assay.id
to make a nice param separate from the batches param. Then, in my batches controller under create
I built a little helper method:
def build_submissions(params) @submitted_assays = params[:assay_ids] for submitted_assay in @submitted_assays do @batch.submissions.build(:assay_id => submitted_assay) end end
That builds up just as many submissions as I need. This fix works wonderfully, but I would welcome any suggestions as to how to solve the problem differently.
精彩评论