Each "User" has one "Move".
Each "Move" has many "Neighborhood Preferences".
I want to create a form on the "/user/(:id)/edit" page that lets a person edit their "move", and "neighborhood_preferences".
Currently, the form displays correctly. But when I submit the form, I get this error Move(#2168853040) expected, got ActionController::Parameters(#2158484920).
How can I save both a new move, and the neighborhood_preferences?
View for Users#edit
<%= form_for(#user) do |f| %>
<%= hidden_field_tag "user[move][neighborhood_ids][]", nil %>
<% #neighborhoods.each do |n| %>
<%= check_box_tag "user[move][neighborhood_ids][]",
n.id, # the value to submit
#user.move.neighborhood_ids.include?(n.id), # Check the box on load
id: dom_id(n) # add a unique category based on the object
%>
<%= label_tag dom_id(n), n.name %>
<br/>
<% end %>
<%= f.submit "Save Changes" %>
<% end %>
Controller for Users#edit
def edit
#user = User.find(params[:id])
#neighborhoods = Neighborhood.all
end
private
def user_params
params.require(:user).permit(
:email,
:age,
:gender,
:university,
:grad_year,
:occupation,
:company,
# Allow form to submit neighborhood_ids for a user's move.
move: [neighborhood_ids: []]
)
end
Models
class User < ActiveRecord::Base
# attr_accessible :provider, :uid, :name, :email
validates_presence_of :name
has_one :move
accepts_nested_attributes_for :move, allow_destroy: true
class Move < ActiveRecord::Base
belongs_to :user
has_many :neighborhood_preferences
has_many :neighborhoods, through: :neighborhood_preferences
accepts_nested_attributes_for :neighborhood_preferences, allow_destroy: true
end
class NeighbhoodPreference < ActiveRecord::Base
belongs_to :neighborhood
belongs_to :move
end
Related
I'm working on a project where Users can see dog Parks and make individual Playdates for each park. The issue I'm having is that the PlaydatesController create action is not persisting the user_id and park_id that each new playdate is associated with. I've tried adding optional: true to my Playdate model, which does save each playdate. However, doing this makes a null column entry for the user_id and park_id.
All I need is the user_id and park_id to create a playdate and keep the association between playdates and parks... Did I mess up my associations? Any help is GREATLY appreciated.
Here's my code:
Playdate MODEL:
class Playdate < ApplicationRecord
belongs_to :park
belongs_to :user
validates :date, presence: true
validates :time, presence: true
end
Park MODEL:
class Park < ApplicationRecord
has_many :playdates
has_many :comments
has_many :users, through: :comments
end
User MODEL:
class User < ApplicationRecord
has_many :parks
has_many :playdates
has_many :comments, through: :parks
end
Playdates CONTROLLER:
def create
#playdate = Playdate.new(playdate_params)
if #playdate.save!
redirect_to park_path(#park)
else
render :new
end
end
private
def playdate_params
params.require(:playdate).permit(:time, :date, :user_id, :park_id)
end
Playdates NEW VIEW:
<%= form_for #playdate do |f| %>
<%= f.label :date %>
<%= f.date_field :date %><br><br>
<%= f.label :time %>
<%= f.time_field :time %><br><br>
<%= hidden_field_tag :user_id, current_user.id %>
<%= hidden_field_tag :park_id, #park%>
<%= f.submit "Add Playdate!" %>
<% end %>
You should use:
f.hidden_field :user_id, value: current_user.id
f.hidden_field :park_id, value: #park.id
The rendered HTML is not the same between "hidden_field_tag" and "hidden_field". Try by yourself to see the difference.
I'm creating an application where a "submission" can be made using a form which creates client details and allows "referrals" to be created depending on the branch(es) that can provide the required service
class Submission < ActiveRecord::Base
has_many :referrals, :inverse_of => :submission, dependent: :delete_all
accepts_nested_attributes_for :referrals, :allow_destroy => true
end
class Referral < ActiveRecord::Base
belongs_to :submission
end
class Branch < ActiveRecord::Base
has_many :referrals
end
Submissions controller:
def new
#submission = Submission.new
#submission.build_client
#submission.client.build_address
#submission.referrals.build
end
def submission_params
params.require(:submission).permit(:consent, :user_id, client_attributes:
[:client_id, :first_name,
address_attributes:
[:first_line, :second_line,]
],
referrals_attributes:
[:branch_id]
)
end
The Submission form:
<%= form_for(#submission) do |f| %>
<%= f.fields_for :referrals do |referral| %>
<%= render 'referral_fields', f: referral %>
<% end %>
<% end %>
_referral_fields.html.erb:
<% Branch.all.where(referrable: true).each do |branch| %>
<label>
<%= check_box_tag 'branch_ids[]', branch.id %>
<%= branch.name %>
</label>
<% end %>
What I want is to have checkboxes for each referrable branch. When a branch is ticked and the submission is created, a referral will be created for that branch. However, when I submit the form, I get a validation error of "Referrals can't be blank". Any idea why this is not working?
Any help is most appreciated
Use collection_check_boxes.
<% # _referral_fields.html.erb %>
<%= f.collection_check_boxes(:branch_ids, Branch.where(referrable: true), :id, :name) do |b|
b.label { b.check_box } # wraps check box in label
end %>
You would need to whitelist submission[referrals_attributes][branch_ids] - not branch_id.
def submission_params
params.require(:submission)
.permit(
:consent,
:user_id,
client_attributes: [
:client_id,
:first_name,
address_attributes: [
:first_line, :second_line,
]
],
referrals_attributes: [:branch_ids]
)
end
Edited.
However for this to work you need to setup a relation between Referral and Branch. In this case you could use either a has_and_belongs_to_many (HABTM) or has_many though: (HMT) relationship.
See Choosing Between has_many :through and has_and_belongs_to_many.
class Referral < ActiveRecord::Base
belongs_to :submission
has_and_belongs_to_many :branches
end
class Branch < ActiveRecord::Base
has_and_belongs_to_many :referrals
end
You need to create a join table as well:
rails g migration CreateBranchReferralJoinTable branch referral
Simple one-to-many relationship going on and getting a Unpermitted parameter in the server log.
Cup 1----*> Contacts
The params looks like
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Ay/wRwJTr4u5Vgu5oOrk7z4RC/OfeLJdN9WXuoyU7iQ=", "cup"=>{"name"=>"cupname", "location"=>"Somewhe", "type_ids"=>"1", "contact"=>{"first_name"=>"Greg", "last_name"=>"Ander", "email"=>"email#me.com", "telephone"=>"444906398"}}, "commit"=>"Create new cup"}
In cups_controller.rb
class CupsController < ApplicationController
def create
#cup = Cup.new(cup_params)
render nothing: true
end
private
def cup_params
params.require(:cup).permit(:name,:location,:type_ids,
:contacts_attributes => [:first_name, :last_name, :email, :telephone ])
end
In cup/new.html.erb - f is the main form for cup
<%= f.fields_for :contacts do |contact_info| %>
<%= contact_info.label :first_name %><%= contact_info.text_field :first_name %>
<%= contact_info.label :last_name %><%= contact_info.text_field :last_name %>
<%= contact_info.label :email %><%= contact_info.email_field :email %>
<%= contact_info.label :telephone %><%= contact_info.telephone_field :telephone %>
<% end %>
Keep getting Unpermitted parameter contact.
The Cup model has accepts_nested_attributes_for :contacts
Model files
class Cup < ActiveRecord::Base
has_many :contacts
has_and_belongs_to_many :types
accepts_nested_attributes_for :contacts
end
class Contact < ActiveRecord::Base
belongs_to :cup
end
Edit
Added updated cup_params and controller class. Also models.
You need to reference the contacts_attributes, not contact itself.
def cup_params
params.require(:cup).permit(:name,:location,:type_ids,
contacts_attributes: [:first_name, :last_name, :email, :telephone ])
end
A users can have many favorites top_songs,top_movies through songs and movies table.
A user registered user(current_user) want to post his favorites movies and songs.
Perhaps all Model association are right, i am stuck in controller and view (form).
When i submit from, i gets errors-
Can't mass-assign protected attributes: songs
How can i achieve this please?
all codes are below.
User Model
class User < ActiveRecord::Base
attr_accessible :id, :name_special_char, :screenname, :fullname, :username, :prefix, :firstname, :lastname,:middlename, :suffix, :age, :sex, :email,
:top_movies_attributes,:top_songs_attributes
has_many :top_movies
has_many :movies, through: :top_movies
has_many :top_songs
has_many :songs, through: :top_songs
accepts_nested_attributes_for :top_songs, :allow_destroy => true
accepts_nested_attributes_for :top_movies, :allow_destroy => true
end
Movie Model
class Movie < ActiveRecord::Base
attr_accessible :name
has_many :top_movies
has_many :users, through: :top_movies
end
TopMovie Model
class TopMovie < ActiveRecord::Base
belongs_to :user
belongs_to :movie
# attr_accessible :title, :body
end
Song Model
class Song < ActiveRecord::Base
attr_accessible :name
has_many :top_songs
has_many :users, through: :top_songs
end
TopSong Model
class TopSong < ActiveRecord::Base
belongs_to :user
belongs_to :song
# attr_accessible :title, :body
end
Controller
class MyTopFivesController < ApplicationController
def new
#favorites = current_user
#favorites=#favorites.movies.build()
#favorites=#favorites.songs.build()
respond_to do |format|
format.html # new.html.erb
format.json { render json: #useraccounts_my_top_fife }
end
end
def create
#favorites = current_user(params[:user])
#favorites.save!
# Here i have stuck. i am not sure how to save.
end
view form
<%=nested_form_for #favorites ,:url=>favorites_path(#favorites),:method=>'post' do |f| %>
<label >Songs</label>
<%= f.fields_for :songs do |songs| %>
<div id="Topsongs" >
<div class="input-control text span5 place-left ">
<%= songs.text_field :name,:placeholder=>"songs name.." %>
</div>
<div class="span1 place-left">
<%= songs.link_to_remove "", :class=>"icon-minus" %>
</div>
</div>
<% end %>
<span >
<%= f.link_to_add "", :songs, :class=>"icon-plus", :data => { :target => "#Topsongs" } %>
</span>
<label >movies</label>
<%= f.fields_for :movies do |movies| %>
<div id="Topmovies">
<div class="input-control text span5 place-left ">
<%= movies.text_field :name,:placeholder=>"movies name.." %>
</div>
<div class="span1 place-left">
<%= movies.link_to_remove "", :class=>"icon-minus" %>
</div>
</div>
<% end %>
<span>
<%= f.link_to_add "", :movies, :class=>"icon-plus",:style=>"font-size: 14px;", :data => { :target => "#Topmovies" } %>
</span>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
There are two options for setting up the associations here. One you have used by creating two join models for top songs and top movies. And other, to use polymorphic association.
Lets use polymorphic association. We are going to use User, Movie, Song and Favourite models for this stuff. The Favourite model will contain the polymorphic fields.
User.rb
class User < ActiveRecord::Base
attr_accessible :id, :name_special_char, :screenname, :fullname, :username, :prefix, :firstname, :lastname,:middlename, :suffix, :age, :sex, :email
has_many :favourites
has_many :movies, through: :favourites, source: :favouritable, source_type: 'Movie'
has_many :songs, through: :favourites, source: :favouritable, source_type: 'Song'
end
Movie.rb
class Movie < ActiveRecord::Base
attr_accessible :name
has_many :favourites, as: :favouritable
has_many :users, through: :favourites
end
Song.rb
class Song < ActiveRecord::Base
attr_accessible :name
has_many :favourites, as: :favouritable
has_many :users, through: :favourites
end
Favourite.rb
class Favourite < ActiveRecord::Base
belongs_to :users
belongs_to :favouritable, polymorphic: true
end
We also need to create the migration for new model "Favourite". As of now, we just need 3 columns ie. user_id, favouritable_id, favouritable_type. Here favouritable_type and favouritable_id are the polymorphic fields. favouritable_type is a string and favouritable_id is reference type.
Migration File
class CreateFavourites < ActiveRecord::Migration
def change
create_table :favourites do |t|
t.integer :user_id
t.references :favouritable, polymorphic: true
t.timestamps
end
end
end
Now, as we are going to mark some movies and songs to be favourite for a user, then we can place the code for building the data in UsersController instead of creating another controller or we can also create a controller for Favourites. I am going to use UsersController here. I am using update action to update the favourites as we don't need any extra functionality here. You can add a new action if you want.
In UsersController.rb
def edit_favourites #or some generic name
#user = current_user.includes(:movies, :songs)
#movies = Movie.all
#songs = Song.all
end
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
redirect_to users_path #user index page
else
if params[:user][:movie_ids].present? or params[:user][:song_ids].present?
render :edit_favourites
else
render :edit
end
end
end
edit_favourites.html.erb
<%= form_for(#user) do |f| %>
<div class="fields">
<%= f.label :movie_ids, "Favourite Movies: " %>
<%= f.collection_select :movie_ids, #movies, :id, :name, {}, multiple: true %>
</div>
<div class="fields">
<%= f.label :song_ids, "Favourite Songs: " %>
<%= f.collection_select :song_ids, #songs, :id, :name, {}, multiple: true %>
</div>
<% end %>
Also, Add the new action to routes.
I'm developing an app for college where a user can log on & upload details of a hiking trail.
So far everything is working & I have also implemented a nested form for photos in each hiking trail. A user can log-on & create a hike.
I would like to display all the hikes which the user created in there show/profile page but when I've set up the relationships in my database & the has_many & belongs_to options in my model. I've also tried to do this with nested accepts_nested_attributes_for :hikingtrails it does none of this works.
I've checked my database when a hikingtrail is created by a user it is not updating the user_id field in the table.
I'm not sure if I'm approaching this entirely the wrong way, should I be looking at polymorphic associations?
class User < ActiveRecord::Base
attr_accessible :user_name, :email, :password, :password_confirmation, :photos_attributes, :hikingtrails_attributes
has_many :hikingtrails
accepts_nested_attributes_for :hikingtrails, :allow_destroy => :true, :reject_if => :all_blank
class Hikingtrail < ActiveRecord::Base
attr_accessible :description, :name, :looped, :photos_attributes,:directions_attributes, :user_id
has_many :photos
has_many :trails
has_many :directions
belongs_to :user
users/show.html.erb
<div class="page-header">
<h1>Your Profile</h1>
</div>
<p>
<b>username:</b>
<%= #user.user_name %>
</p>
<p>
<b>email:</b>
<%= #user.email %>
</p>
<h4>Small Photos</h4>
<% #user.photos.each do |photo| %>
<%= image_tag photo.image_url(:thumb).to_s %>
<% end %>
<h4>Hiking Trails</h4>
<% #user.hikingtrails.each do |hk| %>
<%= hk.name %>
<% end %>
<%= link_to "Edit your Profile", edit_user_path(current_user), :class => 'btn btn-mini' %>
You didn't add :user_id to your accessible attributes in the Hikingtrail model. Try the following:
attr_accessible :description,
:duration_hours,
:duration_mins,
:name,
:looped,
:addr_1,
:addr_2,
:addr_3,
:country,
:latitude,
:longitude,
:photos_attributes,
:trails_attributes,
:directions_attributes,
:user_id
UPDATE:
After seeing the form code, I think it's probably not necessary to do the above and could potentially also be unsafe. Instead, don't set the user_id through mass assignment, but handle user assignment in your controller like so:
class HikingtrailsController < ApplicationController
# ...
def create
#hikingtrail = Hikingtrail.new(params[:hikingtrail])
#hikingtrail.user = current_user
if #hikingtrail.save
# ...
else
# ...
end
end
end
Hope this helps :)