My Rails 5 application includes two models, Activity and Timeslot.
activity.rb
class Activity < ApplicationRecord
belongs_to :club
has_many :timeslots, :dependent => :destroy
accepts_nested_attributes_for :timeslots
validates :club_id, presence: true
validates :name, presence: true, length: { maximum: 50 }
end
timeslot.rb
class Timeslot < ApplicationRecord
belongs_to :activity
validates :time_start, presence: true
validates :time_end, presence: true
validates :day, presence: true
#validates :activity_id, presence: true (I realised this was causing one of the errors I had)
default_scope -> { order(day: :asc) }
end
When I create my activity, I'd also like to create it's first timeslot on the same page, same form.
new.html.erb
<%= form_for(#activity) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.label :name, "Class name" %>*
<%= f.text_field :name, class: 'form-control' %>
<%= f.fields_for :timeslots do |timeslots_form| %>
<%= timeslots_form.label :time_start, "Start time" %>
<%= timeslots_form.time_select :time_start %>
<%= timeslots_form.label :time_end, "End time" %>
<%= timeslots_form.time_select :time_end %>
<%= timeslots_form.label :day %>
<%= timeslots_form.select :day, (0..6).map {|d| [Date::DAYNAMES[d], d]} %>
<% end %>
</div>
<%= f.submit "Create class", class: "btn btn-primary" %>
<% end %>
My edit/update version of this seems to be working fine.
activities_controller.rb
class ActivitiesController < ApplicationController
...
def new
#activity = Activity.new
#activity.timeslots.build
end
def create
#activity = current_club.activities.build(activity_params)
##activity.timeslots.first.activity_id = #activity.id (I thought this might solve the problem, but didn't)
if #activity.save
flash[:success] = "New class created!"
redirect_to activities_path
else
render 'new'
end
end
def edit
#activity = current_club.activities.find_by(id: params[:id])
#activity.timeslots.build
end
def update
#activity = current_club.activities.find_by(id: params[:id])
if #activity.update_attributes(activity_params)
flash[:sucess] = "Class updated!"
redirect_to edit_activity_path(#activity)
else
render 'edit'
end
end
...
private
def activity_params
params.require(:activity).permit(:name, :active, #active is set to default: true
:timeslots_attributes => [:id,
:time_start,
:time_end,
:day,
:active])
end
end
But whenever I try to create a new activity I get the error message "Timeslots activities must exist".
I feel it's trying to assign the activity_id for timeslot before the activity is created, but I'm not sure. I've tried many things (some of which I've included in my example in comment form) but am unable to work out why I'm getting this error.
Update: Add error log
Started POST "/activities" for 127.0.0.1 at 2016-09-25 18:04:51 +0700
Processing by ActivitiesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"xp+dBcWC4cjI6FLpIqhU0RzM4ldZ4JpkFLSyAXcmifL73QqWz6R65EHm/Tj7QxlXnWiBA0axjVXvMZHQ+XKA9A==", "activity"=>{"name"=>"Newest class", "timeslots_attributes"=>{"0"=>{"time_start(1i)"=>"2016", "time_start(2i)"=>"9", "time_start(3i)"=>"25", "time_start(4i)"=>"12", "time_start(5i)"=>"00", "time_end(1i)"=>"2016", "time_end(2i)"=>"9", "time_end(3i)"=>"25", "time_end(4i)"=>"13", "time_end(5i)"=>"30", "day"=>"4"}}}, "commit"=>"Create class"}
Club Load (0.2ms) SELECT "clubs".* FROM "clubs" WHERE "clubs"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
(0.1ms) begin transaction
(0.1ms) rollback transaction
Rendering activities/new.html.erb within layouts/application
Rendered shared/_error_messages.html.erb (1.5ms)
Rendered activities/new.html.erb within layouts/application (16.9ms)
Rendered layouts/_rails_default.html.erb (58.5ms)
Rendered layouts/_shim.html.erb (0.5ms)
Rendered layouts/_header.html.erb (1.7ms)
Rendered layouts/_footer.html.erb (0.8ms)
Completed 200 OK in 111ms (Views: 93.9ms | ActiveRecord: 0.3ms)
You're getting this error because Rails 5 makes belongs_to attribute required by default. Also, the saving mechanism kind of follows:
validate your parent model
validate your child model # validation fails here because parent doesn't have an id yet, because it hasn't been saved
save parent model
save child model
A way to resolve this is to:
class Activity < AR
has_many :timeslots, dependent: :destroy, inverse_of: :activity
accepts_nested_attributes_for :timeslots
end
class Timeslot < AR
belongs_to :activity, inverse_of: :timeslot
end
You could learn more of this here and here
Related
I have three models related using has_many :through as seen below. The user should be able to select concerns (in addition to insurance, patient gender, preferred gender, and writing a note) and create a referral request. When I try to submit the referral request form I get a wrong number of arguments error as seen in this screenshot.
Screenshot of Error
I know this must have something to do with how I am whitelisting my params and have tried a lot of different variations but can't seem to get the syntax (or something else) right. Any help would be greatly appreciated.
From Referral Requests Controller:
def create
#referral_request = current_user.referral_requests.build(referral_request_params)
if #referral_request.save
flash[:success] = "Referral Request Created!"
render 'referral_requests/index'
else
#feed_items = []
render 'static_pages/home'
end
end
def destroy
end
private
def referral_request_params
params.require(:referral_request).permit(:content, :patient_gender_id,
:preferred_gender_id, :insurance_id, :concern_ids [])
end
end
my referral request form
<%= form_for(#referral_request) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<% Concern.all.each do |concern| %>
<%= check_box_tag "referral_request[concern_ids][]", concern.id %>
<%= concern.name %><br>
<% end %>
<%= f.text_area :content, placeholder: "Compose new referral request..." %>
<%= collection_select( :referral_request, :patient_gender_id, Gender.all, :id, :name, prompt: true) %>
<%= collection_select( :referral_request, :preferred_gender_id, Gender.all, :id, :name, prompt: true) %>
<%= collection_select( :referral_request, :insurance_id, Insurance.all, :id, :name, prompt: true) %>
</div>
<%= f.submit "Post", class: "btn btn-primary" %>
<% end %>
Referral Request Model
class ReferralRequest < ApplicationRecord
belongs_to :user
has_many :referral_request_concerns
has_many :concerns, through: :referral_request_concerns
default_scope -> { order(created_at: :desc) }
validates :user_id, presence: true
validates :content, presence: true, length: { minimum: 20 }
validates :patient_gender_id, presence: true
validates :preferred_gender_id, presence: true
validates :insurance_id, presence: true
end
Concern Model
class Concern < ApplicationRecord
has_many :referral_request_concerns
has_many :referral_requests, through: :referral_request_concerns
end
ReferralRequestConcern Model
class ReferralRequestConcern < ApplicationRecord
belongs_to :referral_request
belongs_to :concern
validates :referral_request_id, presence: true
validates :concern_id, presence: true
end
Here is the output of the create action and associated error log after changing :concern_ids [] to concern_ids: []
Started POST "/referral_requests" for ::1 at 2017-06-27 15:01:54 -0400
Processing by ReferralRequestsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"9gd2J+PB6R1jRkpwIlJ8KNlFBdxoFuZ5W2c1NAL1aiBv7mhrKT7ITBtxZPd9jpJ49UAGpc4/4jOpAbrlenG91A==", "referral_request"=>{"concern_ids"=>["1", "2", "3", "4"], "content"=>"dsdfsdsdsfggfdsgfdfgdsgfdfgsdgfsdgfdsgfdgfd", "patient_gender_id"=>"2", "preferred_gender_id"=>"2", "insurance_id"=>"16"}, "commit"=>"Post"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
Concern Load (0.2ms) SELECT "concerns".* FROM "concerns" WHERE "concerns"."id" IN (1, 2, 3, 4)
(0.1ms) begin transaction
(0.1ms) rollback transaction
Rendering static_pages/home.html.erb within layouts/application
Rendered static_pages/home.html.erb within layouts/application (1.7ms)
Rendered layouts/_shim.html.erb (0.7ms)
Rendered layouts/_header.html.erb (1.6ms)
Rendered layouts/_footer.html.erb (1.1ms)
#<ActiveModel::Errors:0x007f8c2a399d70 #base=#<ReferralRequest id: nil, content: "dsdfsdsdsfggfdsgfdfgdsgfdfgsdgfsdgfdsgfdgfd", insurance: nil, user_id: 1, created_at: nil, updated_at: nil, insurance_id: 16, patient_gender_id: 2, preferred_gender_id: 2>, #messages={:referral_request_concerns=>["is invalid"]}, #details={:referral_request_concerns=>[{:error=>:invalid}, {:error=>:invalid}, {:error=>:invalid}, {:error=>:invalid}]}>
Completed 200 OK in 131ms (Views: 79.9ms | ActiveRecord: 1.0ms)
def referral_request_params
params.require(:referral_request).permit(:content, :patient_gender_id,
:preferred_gender_id, :insurance_id, concern_ids: [])
end
(concern_ids: [] instead of :concern_ids [])
EDIT 3: Just to clarify, the goal and problem is to create 2 new records from the same form of which one is the parent and one is the child. The child needs the parent ID, but the parent is created from the same form that the child is.
EDIT 2: I think I'm getting closer. See log file at end, the deal is successfully saved and it looks like the client entry is starting to commit but then not saving. Code is updated below for changes.
I followed the Railscast #196 for nested forms and I am successfully able to edit, add and delete from nested forms as long as the record is already created. Now I am trying to use nested forms to create new records. I think I'm 99% of the way there, but I'm missing something I can't see anymore. I just need to figure out how to pass the id of the parent to the child.
In addition to the Railscast I used this answer to set inverse_of relationships and call the save order (using create instead of save though). I'm pretty sure the problem is in the form or the controller (but models are listed below too)
Nested Form (I tried to simplify to make it easier to read)
EDIT 2: remove hidden field
<%= form_for(#deal) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="deal-<%= #deal.id %>" >
<div class="form-group">
<%= f.label :headline %>
<%= f.text_field :headline, required: true, placeholder: "Headline" %>
</div>
<div class="form-group" id="clients">
<%= f.fields_for :clients do |client_form| %>
<div class="field">
<%= client_form.label :client %><br />
<%= client_form.text_field :name, placeholder: "Client name" %>
</div>
<% end %>
<%= link_to_add_fields "Add client", f, :clients %>
</div>
<div class="form-group">
<%= f.label :matter %>
<%= f.text_field :matter, placeholder: "Matter", rows: "4" %>
</div>
<div class="form-group">
<%= f.label :summary %>
<%= f.text_area :summary, placeholder: "Deal summary", rows: "4" %>
</div>
<div class="form-group">
<div class="action-area">
<%= f.submit "Add deal" %>
</div>
</div>
</div>
<% end %>
Controller
EDIT 2: include deal_id param & change save calls
class DealsController < ApplicationController
before_action :require_login
def new
#deal = Deal.new
#client = #deal.clients
end
def create
#deal = current_user.deals.create(deal_params)
if #deal.save
flash[:success] = "Your deal was created!"
redirect_to root_url
else
render 'deals/new'
end
end
private
def deal_params
params.require(:deal).permit(:headline, :matter, :summary, clients_attributes: [:id, :deal_id, :name, :_destroy])
end
end
EDIT 2: No longer yields errors in browser and success flash message is triggered
EDIT 2: Here is the console output on submit (the record is saved and can be viewed it just doesn't have a client)
Started POST "/deals" for ::1 at 2017-04-26 00:13:08 +0200
Processing by DealsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"hbvpS6KsZOorR3u4LgNoG5WHgerok6j3yYzO+dFUHs9thsxRi+rbUkm88nb7A5WvlmWZEcvaDvCKywufP3340w==", "deal"=>{"headline"=>"headline", "client"=>{"name"=>"aaa"}, "matter"=>"", "summary"=>""}, "commit"=>"Add deal"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 1], ["LIMIT", 1]]
Unpermitted parameter: client
(0.1ms) begin transaction
SQL (0.5ms) INSERT INTO "deals" ("headline", "matter", "summary", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?) [["headline", "headline"], ["matter", ""], ["summary", ""], ["user_id", 1], ["created_at", 2017-04-25 22:13:08 UTC], ["updated_at", 2017-04-25 22:13:08 UTC]]
(3.8ms) commit transaction
(0.1ms) begin transaction
(0.1ms) commit transaction
Redirected to http://localhost:3000/
Completed 302 Found in 16ms (ActiveRecord: 4.6ms)
Models for reference
Users
class User < ApplicationRecord
has_many :deals
end
Deals
class Deal < ApplicationRecord
belongs_to :user
has_many :clients, inverse_of: :deal
validates :headline, presence: true
accepts_nested_attributes_for :clients, allow_destroy: true
end
Clients
class Client < ApplicationRecord
belongs_to :deal, inverse_of: :clients
validates :name, presence: true
validates :deal_id, presence: true
end
You are missing the deal_id on the params
def deal_params
params.require(:deal).permit(:headline, :matter, :summary, clients_attributes: [:id, :deal_id, :name, :_destroy])
end
and on the create of deal, you can make something like this
def create
#deal = Deal.new(deal_params)
if #deal.save
...
and just add a hidden field on the form for the user_id parameter.
The problem is the validations in the client model. Removing the validations will allow the records to be correctly saved from the nested form.
In the Client model remove the name and deal_id validators
class Client < ApplicationRecord
belongs_to :deal, inverse_of: :clients
end
In the controller add build to the new action so it's nicer for the users:
def new
#deal = Deal.new
#client = #deal.clients.build
end
.build is not strictly necessary since the helper method that was created from the Rails Cast will create new client entries on demand, but with it the user is presented with the placeholder first entry which is ignored if blank.
To keep empty client records from saving I added a reject_if: proc to the deal model
class Deal < ApplicationRecord
belongs_to :user
has_many :clients, inverse_of: :deal
validates :headline, presence: true
accepts_nested_attributes_for :clients, allow_destroy: true, reject_if: proc { |attributes| attributes['name'].blank? }
end
I'll leave this open/unanswered in case someone can explain better why my solution worked and if there's a better way to do it.
I am newbie on RoR. I try to create answer through word controller by using accepts_nested_attributes_for but when I click submit button, I get nothing and button got disable.
Here is my code.
word.rb
class Word < ApplicationRecord
belongs_to :category
belongs_to :exam
has_many :answers, dependent: :destroy
accepts_nested_attributes_for :answers
has_many :exam_words, dependent: :destroy
scope :alphabet, ->{order :content}
end
answer.rb
class Answer < ApplicationRecord
belongs_to :wordscope :alphabel, ->{order "content"}
validates :content, presence: true
end
new.html.erb
<% provide(:title, "Create word" )%>
<h1></h1>
<%= form_for #word do |f| %>
<%= f.label :word_content %>
<%= f.text_field :content, class: "form-control" %>
<%= f.fields_for :answers do |answer| %>
<%= answer.label :answer_content %>
<%= answer.text_area :content, class: "form-control" %>
<%= answer.label :is_correct %>
<%= answer.check_box :is_correct %>
<%end%>
<%= f.submit "create", class: "btn btn-primary"%>
<%end%>
words_controller.rb
class WordsController < ApplicationController
before_action :load_category, except: [:show, :new]
def index
#words = #category.words.includes(:answers).paginate(page: params[:page])
end
def new
#word = Word.new
#word.answers.new
end
def show
#word = Word.find_by_id(params[:id])
session[:w_id] = #word.id
end
def create
#word = #category.words.new(word_params)
#word.category_id = session[:cat_id]
#word.exam_id = 1
if #word.save
redirect_to category_path(session[:cat_id])
end
end
def destroy
#word = Word.find(params[:id])
if #word.present?
#word.destroy
end
redirect_to :back
end
def edit
#word = Word.find(params[:id])
end
def update
#word = Word.find(params[:id])
if #word.update_attributes(word_params)
flash[:success] = "Updated"
redirect_to category_path(session[:cat_id])
else
render 'edit'
end
end
private
def word_params
params.require(:word).permit :content,
answers_attributes: [:id, :content, :is_correct]
end
def load_category
#category = Category.find_by id: session[:cat_id]
unless #category
flash[:danger] = t "category_not_found"
redirect_to categories_path
end
end
end
This is what i get in server in terminal
Started POST "/words" for 127.0.0.1 at 2016-11-29 14:52:26 +0000
Processing by WordsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"qr4qCFAh6omymmgJK7aOjZO0HFtkyT3uwB0KGl6EL60MOipdCFgS0l+XwEi7adhPt1uF1TL2RdRGwsK79FX3iw==", "word"=>{"content"=>"new", "answers_attributes"=>{"0"=>{"content"=>"moi", "is_correct"=>"1"}}}, "commit"=>"create"}
Category Load (0.9ms) SELECT "categories".* FROM "categories" WHERE "categories"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
(0.2ms) begin transaction
Exam Load (0.3ms) SELECT "exams".* FROM "exams" WHERE "exams"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
(0.4ms) rollback transaction
No template found for WordsController#create, rendering head :no_content
Completed 204 No Content in 48ms (ActiveRecord: 2.7ms)
This is what show in my local web
==============SOLVED========================
I just find out how to solve, I forgot optional: true in answer.rd.
class Answer < ApplicationRecord
belongs_to :word, optional: true
scope :alphabel, ->{order "content"}
validates :content, presence: true
end
I'm relatively new to Ruby on Rails, and have been developing a slide-sharing application with some complex functionality.
I talk about four models: Spark, Question, Answer, and AnswerImage.
Spark has_many Questions, Question has_many Answers, and Answer has_many AnswerImages. And of course AnswerImages belongs_to Answer and so on.
I use a nested form to update a Question and add a new Answer simultaneously. An instance of Answer may or may not contain an AnswerImage (I use Carrierwave to upload the attachments to S3). When I try and upload an image to the Answer, I get the following error: undefined method '[]' for #<ActionDispatch::Http::UploadedFile: ... >. If I don't try to attach an image, the Question is updated and an answer is created smoothly.
Here is my code:
QuestionsController's update action and question_params
class QuestionsController < ApplicationController
def update
#spark = Spark.find(params[:spark_id])
#question = #spark.questions.find(params[:id])
if #question.update(question_params) # This is where the extracted source of the error is!
flash[:success] = "The question was successfully updated!"
redirect_to #spark
else
render 'edit'
end
end
private
def question_params
params.require(:question).permit(:id, :name, :email, :body, :slide_number, :authorized, :tag_list,
:answers_attributes => [:id, :content, :crop_x, :crop_y, :crop_w, :crop_h, :imgNo, :path,
:answer_images_attributes => [:loc, :id] ]
)
end
end
The Question update form
<%= form_for :question, :method => :patch, :url => "/sparks/#{#spark.id}/questions/#{#question.id}" do |f| %>
<p>
Question Fields
</p>
<%= f.fields_for :answers_attributes do |answer_builder| %>
<div class="form-group">
<%= answer_builder.hidden_field :id %>
<%= answer_builder.label "Answer (If you want to include an image in the answer, navigate to the page you want, and double click anywhere on the page)"%><br>
<%= answer_builder.text_area :content, class: 'form-control', style: 'width: 100%;' %>
<p>
<%= answer_builder.fields_for :answer_images_attributes, html: {multipart: true} do |image| %>
<%= image.file_field :loc %>
<% end %>
</p>
</div>
<% end %>
<p>
<%= f.submit "Save Question", class: 'btn btn-primary' %>
</p>
<% end %>
Logs
Started PATCH "/sparks/13/questions/13" for ::1 at 2016-07-12 11:16:34 -0400
Processing by QuestionsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"mCGLm1Aw2TQo05eVNxFMy/5DxpeRCtpc58tRCX/pt0AEQ1yyMSH7qUxXH3VYXDgDt9T6KTz0Zx9v9mMprroAXw==", "question"=>{"email"=>"rohit.k.gupte#gmail.com", "tag_list"=>"all, ", "slide_number"=>"1", "body"=>"sadf", "answers_attributes"=>{"id"=>"", "content"=>"Answer", "answer_images_attributes"=>{"loc"=>#<ActionDispatch::Http::UploadedFile:0x007fe215f6efb0 #tempfile=#<Tempfile:/var/folders/8z/tjjy3sd507j1m3w4mrsbtjk00000gn/T/RackMultipart20160712-769-3q9ssg.jpg>, #original_filename="GSWImage584.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"question[answers_attributes][answer_images_attributes][loc]\"; filename=\"GSWImage584.jpg\"\r\nContent-Type: image/jpeg\r\n">}, "authorized"=>"1"}, "answer_image"=>"on", "commit"=>"Save Question", "spark_id"=>"13", "id"=>"13"}
Spark Load (0.5ms) SELECT "sparks".* FROM "sparks" WHERE "sparks"."id" = ? LIMIT 1 [["id", 13]]
Question Load (0.1ms) SELECT "questions".* FROM "questions" WHERE "questions"."spark_id" = ? AND "questions"."id" = ? LIMIT 1 [["spark_id", 13], ["id", 13]]
(0.2ms) rollback transaction
Completed 500 Internal Server Error in 26ms (ActiveRecord: 3.3ms)
NoMethodError (undefined method `[]' for #<ActionDispatch::Http::UploadedFile:0x007fe215f6efb0>):
app/controllers/questions_controller.rb:53:in `update'
Question model
class Question < ActiveRecord::Base
belongs_to :spark
has_many :answers, dependent: :destroy
acts_as_taggable_on :tags
accepts_nested_attributes_for :answers, :allow_destroy => true, reject_if: proc { |attributes| attributes['content'].blank? }
end
Answer model
class Answer < ActiveRecord::Base
belongs_to :question
has_many :answer_images, dependent: :destroy
accepts_nested_attributes_for :answer_images, :allow_destroy => true
end
AnswerImage model
class AnswerImage < ActiveRecord::Base
belongs_to :answer
mount_uploader :loc, AnswerPngStore, dependent: :destroy
end
I can provide code for the Uploader if needed although I don't think the problem lies there.
I have taken a look at this post and a few others that describe different undefined method errors for ActionDispatch::Http::UploadedFile, but none of them had a conclusive solution.
I appreciate your help! :)
I have a form that includes two models, one of which is nested in another. When on the development server I submit the form, the submission generates the flash error message:
The form contains 1 error:
* Members organization can't be blank
Each Member belongs to 1 Organization. Might the error have to do with that the organization isn't saved yet when it's trying to save the Member (for a new organization, it's supposed to simulateneously save the organization and member)? Should I add code that sets organization_id for the member (but I would expect #organization.members.build to take care of that)? What am I doing wrong here?
The server log:
Processing by OrganizationsController#create as HTML
Parameters: {"utf8"=>"✓", "organization"=>{"org_name"=>"sadfsdaf", "phone"=>"sdfds", "members_attributes"=>{"0"=>{"username"=>"fsfdsfsad", "email"=>"sfdsdf#sfsdf.com", "fullname"=>"sdfds", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}}}, "admin"=>"true", "commit"=>"Sign up"}
(0.5ms) begin transaction
Member Exists (0.4ms) SELECT 1 AS one FROM "members" WHERE LOWER("members"."email") = LOWER('sfdsdf#sfsdf.com') LIMIT 1
Member Exists (0.2ms) SELECT 1 AS one FROM "members" WHERE LOWER("members"."username") = LOWER('fsfdsfsad') LIMIT 1
Organization Exists (0.3ms) SELECT 1 AS one FROM "organizations" WHERE LOWER("organizations"."org_name") = LOWER('sadfsdaf') LIMIT 1
Organization Exists (0.2ms) SELECT 1 AS one FROM "organizations" WHERE LOWER("organizations"."phone") = LOWER('sdfds') LIMIT 1
(0.2ms) rollback transaction
Rendered shared/_error_messages.html.erb (1.9ms)
Organization model:
has_many :members, dependent: :destroy
accepts_nested_attributes_for :members, :reject_if => :all_blank, :allow_destroy => true
Member model:
belongs_to :organization
validates :organization_id, presence: true # There are other validations as well, but I don't think they matter for this question.
def send_activation_email
MemberMailer.account_activation(self).deliver_now
end
Organization controller:
def new
#organization = Organization.new
#member = #organization.members.build
end
def create
#organization = Organization.new(organizationnew_params)
if #organization.save
#member.send_activation_email # Method in Member model file.
flash[:success] = "Please check your email to activate your account."
redirect_to root_url
else
render 'new'
end
end
private
def organizationnew_params
params.require(:organization).permit(:org_name,
:phone,
member_attributes: [:email,
:username,
:admin,
:password,
:password_confirmation
])
end
New view:
<%= form_for(#organization) do |f| %>
<%= f.text_field :org_name, %>
<%= f.text_field :phone %>
<%= f.fields_for :members do |p| %>
<%= p.text_field :username %>
<%= p.email_field :email %>
<%= p.password_field :password %>
<%= p.password_field :password_confirmation %>
<%= hidden_field_tag :admin, true %>
<% end %>
<%= f.submit "Sign up", class: "formbutton btn btn-default" %>
<% end %>
On the permitted params, try changing member_attributes to members_attributes. Also on the create action You are referring to #member but its not defined yet.
To debug further more replace your create action with:
def create
return render text: organizationnew_params
end
This way, when you send the form you will get all the permitted params and check if it's what you expected.
To Send the emails replace
#member.send_activation_email
With
#organization.members.each do |single_member|
single_member.send_activation_email
end
3rd Edit
Just use this
def create
#organization = Organization.new(organizationnew_params)
if #organization.save
#organization.members.each do |single_member|
single_member.send_activation_email
end
flash[:success] = "Please check your email to activate your account."
redirect_to root_url
else
render 'new'
end
end
private
def organizationnew_params
params.require(:organization).permit(:org_name,
:phone,
members_attributes: [:id,:email,
:username,
:admin,
:password,
:password_confirmation
])
end
4th Edit
The validation:
When creating members with oraganization ( in the OraganizationsController ), you do not need to validate organization_id because it will be created at the same time of the organization. Unfortunately you will need the validation of the organization_id when adding a new member to the organization. So what we can do is add a condition to the validation:
#member.rb
attr_accessor :require_organization_id
belongs_to :organization
validates :organization_id, presence: true, if: :require_organization_id
How to use it:
member = Member.new(name: "Some Name")
member.valid? #true
member.require_organization_id = true
member.valid? #false
member.organization = Organization.first
member.valid? #true
If you set validation in member model i.e.
validates :organization_id, presence: true
then it looks in member params for organization_id which doesn't present in params of memeber
"members_attributes"=>{"0"=>{"email"=>"sfsa#sfsd.com", "username"=>"fsfdsfsad", "fullname"=>"sdfds", "password"=>"foobar", "password_confirmation"=>"foobar"}}
thats why its showing validation error so remove this line
validates :organization_id, presence: true
from your member model
Also for #member issue you need to do like this
#organization.memebers.each do |member|
member.send_activation_email
end