I seem to be unable to delete items using the accepts_nested_attributes_for command but I have done this according to this tutorial and the associated git repo. My models are ...
class Job < ActiveRecord::Base
has_many :specialties, :inverse_of => :job
accepts_nested_attributes_for :specialties, allow_destroy: true, :reject_if => :all_blank
end
class Specialty < ActiveRecord::Base
belongs_to :job, :inverse_of => :specialties
end
In my Job form, I have...
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "Remove Specialty" %>
When I click the checkbox to delete the a couple of specialties, nothing happens. I checked the server output and received:
Started PATCH "/jobs/1" for 127.0.0.1 at 2013-07-16 16:15:16 -0400
Processing by JobsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"8VxYXujcKXpLEm8+7B43SLU6X3fH00kIOmFK+nvaBKs=", "job"=>{"name"=>"Cook", "description"=>"Makes the food.", "specialties_attributes"=>{"2"=>{"name"=>"", "description"=>"", "_destroy"=>"1", "id"=>"3"}, "3"=>{"name"=>"", "description"=>"", "_destroy"=>"1", "id"=>"4"}}}, "commit"=>"Update Job", "id"=>"1"}
Job Load (0.1ms) SELECT "jobs".* FROM "jobs" WHERE "jobs"."id" = ? LIMIT 1 [["id", "1"]]
Unpermitted parameters: _destroy
Unpermitted parameters: _destroy
Unpermitted parameters: _destroy
Unpermitted parameters: _destroy
What did I miss? I've gone through the tutorial and repo a bunch of times and I can't see where I've gone off.
That's because of strong_parameters. You now have to permit keys. In your action:
params.permit(:_destroy)
I like #Damien Roche's answer but its just for not confusion to any one. follow this
In job_controller.rb
private
def job_params
params.require(:job).permit(:id, :description, :specialty_fields_attributes => [:id, :job_id, :avatar, :_destroy])
end
Related
I am not sure if my title is properly using the vocabulary. I found a few SO posts where people had similar issues (I couldn't find a solution in those posts), so I used a similar title to those. I am trying to allow users to create clubs and automatically assign the user as a member of the club. However, it seems like I have something out of order when I tried to create the club.
I have three models:
###Models###
#user
has_many :club_memberships, :class_name => 'ClubMembership', :foreign_key => :member_id, :primary_key => :id
has_many :clubs, :through => :club_memberships
#club
attr_accessor :club_name, :club_type
has_many :club_memberships
has_many :members, :through => :club_memberships
#clubmembership
attr_accessor :club_id, :member_id, :membership_type
belongs_to :club
belongs_to :member, :class_name => "User", :foreign_key => :member_id, :primary_key => :id
Here are the relevant parts of the controllers
###Controllers###
#Clubs
def new
#club = Club.new
end
def create
#club = Club.new(club_params)
if #club.save
#club_membership = ClubMembership.create(
member_id: current_user.id,
club_id: #club.id,
membership_type: 'founder'
)
flash[:success] = "Club Created!"
redirect_to root_url
else
render #club.errors.full_messages
end
end
private
def club_params
params.require(:club).permit(:club_name, :club_type)
end
#ClubMemberships
def create
#club_membership = ClubMembership.new(club_membership_params)
if #club_membership.save
render #club_membership
else
render #club_membership.errors.full_messages
end
end
private
def club_membership_params
params.require(:club_membership).permit(:member_id, :club_id, :membership_type)
end
My form_for
###View###
#club#new
= form_for(#club) do |f|
.field.center-align
= f.label :club_name
= f.text_field :club_name, :class => "form-control fieldbox", autofocus: true
.field.center-align
= f.label :club_type
= f.text_field :club_type, :class => 'form-control fieldbox', autofocus: true
.actions.center-align
= f.submit "Create Club!", :class => "btn hoverable padtop"
And finally, here is what the log shows on post
#log
Started POST "/clubs" for at 2015-09-03 22:32:41 +0000
Cannot render console from ! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by ClubsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Ar2dv41/Tqk9EVjwfLLeD8bnpLoVWQIdDxG3Ju1GO3stLLvPd/FFgoFF9YuHobWbgb2byqkgAMiWRJAg5YcGKQ==", "club"=>{"club_name"=>"Test Club", "club_type"=>"Test Type"}, "commit"=>"Create Club!"}
(0.2ms) BEGIN
Club Exists (0.4ms) SELECT 1 AS one FROM `clubs` WHERE `clubs`.`club_name` = BINARY 'Test Club' LIMIT 1
SQL (0.3ms) INSERT INTO `clubs` (`created_at`, `updated_at`) VALUES ('2015-09-03 22:32:41', '2015-09-03 22:32:41')
(3.4ms) COMMIT
User Load (0.1ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 56 LIMIT 1
(0.1ms) BEGIN
ClubMembership Exists (0.3ms) SELECT 1 AS one FROM `club_memberships` WHERE (`club_memberships`.`member_id` = BINARY 56 AND `club_memberships`.`club_id` IS NULL) LIMIT 1
SQL (1.6ms) INSERT INTO `club_memberships` (`created_at`, `updated_at`) VALUES ('2015-09-03 22:32:41', '2015-09-03 22:32:41')
(3.1ms) COMMIT
Redirected to c9
Completed 302 Found in 71ms (ActiveRecord: 11.1ms)
I'll be honest. I have no clue what is happening in that POST or where to tackle this from next. It seems like the parameters I want are going through, but then they aren't. Any help would be appreciated.
I figured it out. I tried two things at once and it worked, so I can't say for sure what helped, but I am pretty sure the second thing was most important.
First, I removed the attr_accessor from both model's (Club and ClubMembership). Why did I put it in there in the first place? No idea. I probably saw it somewhere and thought it was cool.
Second, also in the models, I had validators that I didn't post because I didn't think they were important. I had:
validates :club_name, :club_type, :presence => true
validates :club_name, :uniqueness => true
I changed this to:
validates :club_name, presence: true
validates :club_type, presence: true
Turns out that was important and everything is working fine now.
I have 2 models Post and Photo:
class Post < ActiveRecord::Base
has_many :photos
end
and :
class Photo < ActiveRecord::Base
belongs_to :post
has_attached_file :photo,styles:{medium:"300x300>", small:"100x100>"}
validates_attachment_content_type :photo, :content_type => /\Aimage\/.*\Z/
validates :photo, presence: true
end
I made a single change to photos_controller so photos could be uploaded, I added :photo:
def photo_params
params.require(:photo).permit(:post_id, :photo)
end
But when I want to add a new photo I get this warning in log:
Unpermitted parameters: post
And here is the parameters:
Processing by PhotosController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"gSiLdGHe3VM8Ka6gjTKk7xjcK0omPdvqfQ0DRRXdOKo=",
"photo"=>{"post"=>"1"}, "commit"=>"Update Photo", "id"=>"1"}
Note: I have a photo attribute in my Photo model but I think thats not going to make any problems and I'm using paperclip gem for uploading images.
From what I see in the parameters sent to the server, post (not post_id) is set to 1.
Rails tells you that you're trying to assign post, an unpermitted parameter, to 1 (while you only permitted post_id in your photo_params method).
I have following models
class User < ActiveRecord::Base
has_many :project_users, dependent: :destroy
has_many :projects, through: :project_users
end
class ProjectUser < ActiveRecord::Base
belongs_to :user
belongs_to :project
has_many :participants
has_many :tasks, through: :participants
end
class Task < ActiveRecord::Base
belongs_to :project
has_many :participants
has_many :project_users, through: :participants
accepts_nested_attributes_for :participants
end
class Participant < ActiveRecord::Base
belongs_to :project_user
belongs_to :task
end
So the flow should go like this:
1. User creates the project
2. User adds users to project via the join model ProjectUser
3. User creates a task for the project and selects those users from ProjectUsers, who will participate in the task. So I put an accepts_nested_attributes_for method and tried to build the nested form.
In my controller:
def new
#task = Task.new
#task.participants.build
end
def task_params
params.require(:task).permit(:project_id, :project_phase_id, :priority_id, :title, :due_date, :estimation, :responsible_id, :description, :participant_ids => [])#, :participants_attributes => [:project_user_id, :task_id])
end
participants_attributes is commented
In my view:
= f.association :participants, as: :select
Actual HTML generated:
<input name="task[participant_ids][]" type="hidden" value="">
<select class="select optional form-control" id="task_participant_ids" multiple="multiple" name="task[participant_ids][]">
<option value="57">AlexandeR MazeiN</option>
<option value="59">Firenze</option>
<option value="58">Vasily Strekotkin</option>
</select>
I add options via ajax, value = ProjectUser.id
I Have to do it like so, because I dont know which ProjectUsers there will be unless a concrete project for a task is selected.
Error I am getting:
Started POST "/tasks" for 127.0.0.1 at 2014-04-11 13:18:24 +0300
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = 6 ORDER BY "users"."id" ASC LIMIT 1
Processing by TasksController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"aXuk9ZuDvFZce+sbIQLRhWZlVjitMvySaJ7CwWfdmaQ=", "task"=>{"project_id"=>"20", "priority_id"=>"4", "project_phase_id"=>"40", "title"=>"Skepta", "due_date"=>"", "estimation"=>"8", "responsible_id"=>"6", "participant_ids"=>["", "57", "58"], "description"=>""}, "commit"=>"Create Task"}
Team Load (0.4ms) SELECT "teams".* FROM "teams" WHERE "teams"."id" = $1 LIMIT 1 [["id", 3]]
Participant Load (0.5ms) SELECT "participants".* FROM "participants" WHERE "participants"."id" IN (57, 58)
Completed 404 Not Found in 7ms
ActiveRecord::RecordNotFound - Couldn't find all Participants with IDs (57, 58) (found 0 results, but was looking for 2):
Your param hash has the IDs from ProjectUser as participant_ids, so when it queries the database it is looking for Participant models with these IDs. You need to set these as project_user_id inside of a list of participants, something like this:
participants: [ { project_user_id: 57 }, { project_user_id: 58 } ]
I'm not super familiar with build, but something along these lines should allow AR to properly construct the associations.
My Create controller passes in the for the child of a nested resource as null instead of passing the values i've just inputed into the form.
Here is my code
Routes:
resources :trips do
resources :pilgrims
end
Models:
Trip:
class Trip < ActiveRecord::Base
has_many :pilgrims
accepts_nested_attributes_for :pilgrims, :allow_destroy => true
attr_accessible :end_date, :leader_id, :name, :start_date, :pilgrim_attributes
end
Pilgrim:
class Pilgrim < ActiveRecord::Base
belongs_to :trip
attr_accessible :pilgrim_id, :surname, :name, :middle, :aka, :prefix, :address, :city, :state, :zip, :email, :telephone, :nationality, :date_of_birth, :passport_number, :expiration, :jordan, :room, :price, :status, :trip_id
end
My Pilgrim controller:
def new
#trip = Trip.find(params[:trip_id])
#pilgrim = Pilgrim.new
end
def create
#trip = Trip.find(params[:trip_id])
#pilgrim = #trip.pilgrims.build(params[:pilgrim])
if #pilgrim.save
flash[:notice] = "The <b>#{ #pilgrim.name }</b> has been created successfully."
redirect_to(trip_pilgrims_path, :notice => "The <b>#{ #pilgrim.name }</b> ship has been saved successfully.")
else
render(:new, :error => #pilgrim.errors)
end
end
Link to a gist with my form code Form
The routes seem to be correct, when i click on new_trip_pilgrim_path(#trip) it does point to trips/:trip_id/pilgrims/new and loads the new pilgrim form.
However when i click save on the form it redirects me to the route trips/3/pilgrims but shows the new pilgrim form saying all required fields were left blank.
This is what displays in the log.
Started POST "/trips/3/pilgrims" for 127.0.0.1 at 2013-01-19 22:12:06 -0800
Processing by PilgrimsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"kOE06m3DNax43BOLYZ6t1lS7/T4wOWb2xM8m/mlQzvA=", "commit"=>"Create Pilgrim", "trip_id"=>"3"}
Trip Load (0.3ms) SELECT `trips`.* FROM `trips` WHERE `trips`.`id` = 3 LIMIT 1
(0.2ms) BEGIN
(0.2ms) ROLLBACK
Pilgrim Load (0.4ms) SELECT `pilgrims`.* FROM `pilgrims` WHERE `pilgrims`.`trip_id` = 3
Rendered pilgrims/_form.html.erb (36.4ms)
Rendered pilgrims/new.html.erb within layouts/application (37.2ms)
User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
Trip Load (0.3ms) SELECT `trips`.* FROM `trips`
Completed 200 OK in 244ms (Views: 102.5ms | ActiveRecord: 11.2ms)
What is going on with the Pilgrim create controller?
You are trying to create a new pilgrim object by calling
#pilgrim = #trip.pilgrims.build(params[:pilgrim])
in the PilgrimsController. But Parameters: {"utf8"=>"✓", "authenticity_token"=>"kOE06m3DNax43BOLYZ6t1lS7/T4wOWb2xM8m/mlQzvA=", "commit"=>"Create Pilgrim", "trip_id"=>"3"} Doesn't contain any pilgrim paramters. So the problem is with the form used for creating a new pilgrim
My models:
class NewsItem < ActiveRecord::Base
has_many :file_uploads, :as => :uploadable
accepts_nested_attributes_for :file_uploads, :allow_destroy => true
end
class FileUpload < ActiveRecord::Base
belongs_to :uploadable, :polymorphic => true
has_attached_file :upload, :styles => {:thumb => '100x100>'}
end
Form Code (nested within NewsItem)
...
<%= f.fields_for :file_uploads do |upload| %>
<div class="file_upload">
<%= upload.file_field :upload %>
</div>
...
<% end %>
...
On submit I get the following error: "unknown attribute: upload". Here are the params:
{"utf8"=>"✓",
"authenticity_token"=>"MBfxJ4XTizCXv3Mpu971VHCm60bS3Y84Kdxfe+VJD2w=",
"news_item"=>{"title"=>"",
"body"=>"",
"published_date"=>"",
"file_uploads_attributes"=>{"0"=>{"upload"=>#<ActionDispatch::Http::UploadedFile:0x000001070112a8 #original_filename="rails-dd352fc2630e5f9aa5685ef1d7fe5997.png",
#content_type="image/png",
#headers="Content-Disposition: form-data; name=\"news_item[file_uploads_attributes][0][upload]\"; filename=\"rails-dd352fc2630e5f9aa5685ef1d7fe5997.png\"\r\nContent-Type: image/png\r\n",
#tempfile=#<File:/var/folders/hb/2bkct63171lck8d3sg0xfq0c0000gn/T/RackMultipart20111204-3216-71in7a>>,
"name"=>"",
"caption"=>""}}},
"commit"=>"Create News item"}
I'm using Rails 3.1.3 and paperclip "~> 2.4".
I'd avoid generic terms like "uploadable" because the resultant term "upload" has the potential for collision.
youavmatchulsky's suggestions are good too - if you have attr_accessible anywhere you'll need to make file_uploads_attributes accessible as well.
Also, the params don't look like the form is multipart, so I'd force it with :multipart => true in the call to form_for
EDIT: Even though it's supposed to happen automagically, you may have to explicitly accept_nested_attributes_for the join, and then on the join model accept_nested_attributes_for :uploadable -- I've found anaf to be pretty weird with things like polymorphic joins sometimes
Restarting the rails app fixed the problem. I'm guessing I installed the gem but did not restart, leading to the error above. Lesson learned: always restart after installing a gem.