Rails 3 autocomplete gem with belongs_to association - ruby-on-rails

I am using the rails3-jquery-autocomplete gem and it works neat when using it for fields that exist in the model. However, I have been trying to use it for associations and I fail to see how to make it work. So let's explain what I have:
Models:
class Receipt < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_many :receipts
end
Controller
class Admin::ReceiptsController < AdminController
autocomplete :user, :name
def index
#receipts = Receipt.all
end
def show
#receipt = Receipt.find_by_id(params[:id])
end
def edit
#receipt = Receipt.find_by_id(params[:id])
#users = User.all
end
end
View (form):
<%= form_for(#receipt, :url => admin_receipt_path, :html => { :multipart => true }) do |f| %>
<div class="clearfix">
<%= f.label :value, "Value($)" %>
<div class="input"><%= f.text_field :value %></div>
</div>
<div class="clearfix">
<%= f.label :user_id, "User" %>
<div class="input">
<%= f.autocomplete_field :user_id, autocomplete_user_name_admin_receipts_path %>
</div>
</div>
.....
The thing is... I am able to fetch user names, but I want to actually store the user id in there. The same way I would like to show the name when the admin tries to edit an existing receipt with a user associated. Something that I am able to do with this drop down:
<div class="clearfix">
<%= f.label :user_id, "User" %>
<div class="input"><%= f.select :user_id, #users.collect {|p| [ p.name, p.id ] },{:prompt => 'Select a User'} %></div>
</div>
I am failing to see how would I do this with this gem....

Ryan Bates did a screencast on this. Clean and well explained
Screencast
If you don't feel like subscribing try torrent

Related

has_many :through and collection_select rails form

I have tried all of the solutions to similar problems and haven't gotten this one figured out.
I have a has_many :through relationship between 'Clinician', and 'Patient' with a joined model 'CareGroupAssignment'. None of the methods I have tried so far been able to save the clinician to patient association. I would like to have a patient be able to have multiple clinicians associated with it and clinicians will have multiple patients.
clinician.rb (simplified)
class Clinician < ActiveRecord::Base
belongs_to :care_group
has_many :patients ,:through=> :care_group_assignments
has_many :care_group_assignments, :dependent => :destroy
belongs_to :user
accepts_nested_attributes_for :user, :allow_destroy => true
end
patient.rb
class Patient < ActiveRecord::Base
belongs_to :care_group
has_many :clinicians ,:through=> :care_group_assignments
has_many :care_group_assignments
belongs_to :user
accepts_nested_attributes_for :user, :allow_destroy => true
end
care_group_assignments.rb
class CareGroupAssignment < ActiveRecord::Base
belongs_to :clinician
belongs_to :patient
end
I first tried to follow the example from Railscasts PRO #17- HABTM Checkboxes to at least start getting the data collected and to have the models set up correctly. Below is the form with the checkboxes for each clinician as described in the RailsCast, checkboxes show up and the data is sent but not stored (can't figure out why).
patient new.html.erb form
<%= form_for #patient do |form| %>
<%= form.fields_for :user do |builder| %>
<div class="form-group">
<%= builder.label "Email or Username" %>
<%= builder.text_field :email, class: "form-control" %>
</div>
<div class="form-group">
<%= builder.label :password %>
<%= builder.password_field :password, class: "form-control" %>
</div>
<% end %>
<div class="form-group">
<%= form.label :first_name %>
<%= form.text_field :first_name, class: "form-control", placeholder: "First name" %>
</div>
<div class="form-group">
<%= form.label :last_name %>
<%= form.text_field :last_name, class: "form-control", placeholder: "Last name" %>
</div>
<div class="form-group">
<% Clinician.where(care_group_id: #care_group.id).each do |clinician| %>
<%= check_box_tag "patient[clinician_ids][]", clinician.id, #patient.clinician_ids.include?(clinician.id), id: dom_id(clinician) %>
<%= label_tag dom_id(clinician), clinician.full_name %><br>
<% end %>
</div>
<%= form.button 'Create Patient', class: "btn btn-u btn-success" %>
<% end %>
Next, I tried the collection_select answer to this question. This creates a badly formatted list where only one clinician can be selected. The data seems to get sent but again doesn't save.
patient new.html.erb form
<div class="form-group">
<%= collection_select(:patient, :clinician_ids,
Clinician.where(care_group_id: #care_group.id).order("first_name asc"),
:id, :full_name, {:selected => #patient.clinician_ids, :include_blank => true}, {:multiple => true}) %>
</div>
Lastly, I copied what was done in this questions/solution. Also isn't formatted as a normal collection_select dropdown but instead a list with a boarder around it where only one clinician can be selected.
patient new.html.erb form
<div class="form-group">
<% Clinician.where(care_group_id: #care_group.id).each do |clinician| %>
<%= check_box_tag "patient[clinician_ids][]", clinician.id, #patient.clinician_ids.include?(clinician.id), id: dom_id(clinician) %>
<%= label_tag dom_id(clinician), clinician.full_name %><br>
<% end %>
</div>
None of these methods have so far been able to save the clinician to patient association.
patient_controller.rb
def new
#patient = Patient.new
#user = User.new
#patient.build_user
#care_group = current_clinician.care_group
end
def create
#patient = Patient.create(patient_params)
#patient.care_group = current_clinician.care_group
if #patient.save
redirect_to patient_path(#patient), notice: "New patient created!"
else
render "new"
end
end
def show
#patient = Patient.find_by(id: params["id"])
end
private
def patient_params
params.require(:patient).permit({:clinician_ids => [:id]},:first_name,:last_name,:user_id,:care_group_id, user_attributes: [ :email, :password, :patient_id, :clinician_id ])
end
I plan to display the clinicians associated with a patient on the patient show page:
patient show.html.erb
<strong>Shared with:</strong>
<% #patient.clinicians.each do |clinician| %>
<%= clinician.full_name %><
<% end %>
This works if I seed the database but since the data doesn't seem to be stored, nothing is showing up.
Rails 4.1.8, ruby 2.2.1p85, PostgreSQL
Thanks
Found the answer on another question I asked:
problem is this line in the controller:
params.require(:patient).permit({:clinician_ids => [:id]}...
It should be:
params.require(:patient).permit({:clinician_ids => []}...

Nested attributes on Rails: Can't mass-assign protected attributes

I've been stuck on getting nested attributes to work on Rails 3.2.14 for a while and having looked at many examples I still can't seem to get it to work. At the moment when I try to submit the form I get the following error:
ActiveModel::MassAssignmentSecurity::Error in Admin::CategoriesController#create
Can't mass-assign protected attributes: products, category_departments
Here's my code:
class Category < ActiveRecord::Base
extend FriendlyId
friendly_id :category_name, use: :slugged
attr_accessible :category_name, :products_attributes, :slug, :department_id, :category_departments_attributes
has_many :products
has_many :category_departments
has_many :departments, :through => :category_departments
validates_presence_of :category_name
accepts_nested_attributes_for :products
accepts_nested_attributes_for :category_departments
scope :department_category, lambda {|department| joins(:department, :products).where("departments.department_name" => department ) }
end
Controller:
class Admin::CategoriesController < ApplicationController
def new
#category = Category.new
#category.products.build
#category.category_departments.build
end
def create
#category = Category.new(params[:category])
if #category.save
redirect_to admin_products_path
else
flash.now[:error] = "Could not save the category"
render "new"
end
end
Form-view
So I finally solved this by removing the products fields_for and allowing the department to be selected from the products creation page.
Form:-
<h1> Create a Category </h1>
<%= form_for :category, :url => { :action => "create" }, :method => :post do |f| %>
<%= render :partial => 'form_category', :locals => {:f => f} %>
<% end %>
Partial:-
<div class="category-form-update">
<form class="form-horizontal">
<div class="control-group">
<label class="control-label">
<%= f.label :category_name %>
</label>
<div clas="controls">
<%= f.text_field :category_name %>
</div>
</div>
<div class="control-group">
<%= f.fields_for :category_departments do |builder| %>
<label class="control-label">
<%= builder.label :department, "Department" %>
</label>
<div class="controls">
<% department = Department.all.map { |dep| [dep.department_name.capitalize, dep.id] } %>
<%= builder.select(:department_id ,options_for_select(department)) %>
<% end %>
</div>
</div>
<div class="control-group">
<div class="controls">
<button class="btn">
<%= f.submit %>
</button>
</div>
</div>
</div>
What am I not doing correctly here?
I think this is as easy as adding :products and :category_departments to attr_accessible like so:
class Category < ActiveRecord::Base
extend FriendlyId
friendly_id :category_name, use: :slugged
attr_accessible :category_name, :products_attributes, :slug, :department_id, :category_departments_attributes, :products, :category_departments
...
Without checking the internals, I assume this is necessary because the nested_attributes magic uses the :products_attributes to populate :products.
EDIT:
This only revealed the actual issue which is the nested attribute naming magic didn't kick in and name the fields properly. My guess is the form_for doesn't have the category object as a parameter.

Issue while creating posts in database

I have a form from which a project is created. The form collects data for two tables; 'projects' and 'projects_users'. The last one
is a relational tabel which is used for storing which users that are members of the project (choosen in the form).
Creating a new project works fine, but when it comes to creating new posts in 'projects_users' it fails:
uninitialized constant ProjectsController::Projects_users
First of all, am I thinking in the right way (see the code below)?
What I do is that I extract the members array from params[:project], that's retrieved from the form. Then I'm creating the project in the db, and when that is done I iterate through the members array (which contains of user_id's) and creates the posts in the db for 'projects_users'.
What am I doing wrong? Is there a better way to achieve what I want?
projects controller:
class ProjectsController < ApplicationController
def new
#project = Project.new
#users = (current_user.blank? ? User.all : User.find(:all, :conditions => ["id != ?", current_user.id]))
end
def create
#members = params[:project].delete(:members)
#project = Project.new(params[:project].merge(:user_id => current_user.id))
if #project.save
#members.each do |member|
#project_members = Projects_users.new
#project_members.project_id = #project.project_id
#project_members.user_id = member.user_id
end
redirect_to #project
else
#users = (current_user.blank? ? User.all : User.find(:all, :conditions => ["id != ?", current_user.id]))
render :new
end
end
end
new.html.erb:
<%= form_for #project do |f| %>
<div class="alert alert-block">
<%= f.error_messages %>
</div>
<div class="text_field">
<%= f.label :title%>
<%= f.text_field :title%>
</div>
<div class="text_field">
<%= f.label :description%>
<%= f.text_field :description%>
</div>
<div class="dropdown">
<%= f.label :start_date%>
<%= f.date_select :start_date %>
</div>
<div class="dropdown">
<%= f.label :end_date%>
<%= f.date_select :end_date %>
</div><br/>
<span class="help-block">Välj användare som ska ingå ingå i projektet.</span>
<div class="checkbox">
<% #users.each do |user| %>
<%= check_box_tag "project[members][]", user.id, '1', :id => "user_#{user.id}" %>
<%= label_tag "user_#{user.id}", user.first_name + ' ' + user.last_name, :class => "checkbox" %>
<% end %>
</div>
</div>
<div class="submit">
<%= f.submit "Spara" %>
</div>
<% end %>
project model:
class Project < ActiveRecord::Base
has_and_belongs_to_many :users, :class_name => 'User'
belongs_to :user
has_many :tickets, :dependent => :destroy
// validation...
# Setup accessible (or protected) attributes for your model
attr_accessible :user_id, :title, :description, :start_date, :end_date
end
users model:
class User < ActiveRecord::Base
attr_accessible :first_name, :last_name, :email, :password
has_and_belongs_to_many :projects
has_many :tickets
... other code
end
projects_users table:
project_id
user_id
projects table:
user_id (the user that creates the project = admin)
title
description
start_date
end_date
In the controller you are using Projects_users.new that means the new method for Projects_users model and as you are using HABTM association the join model doesn't exist. If you want to use the join/associated model then you must use has_many :through association. But in case you just want to associate preexisting users to projects you can do it following way
#project.user_ids = #members
OR
#members.each do |member|
user = User.find(member)
#project.users << user
end
#member will be an array in your case not a hash. It will contain all the checked users' ids. So you don't need to have member.user_id as it is not a hash.

rails accept nested atributes for a polymorphic association

I have an error "Can't mass-assign protected attributes: Upload", but I have assigned it to be accessible.
This is a nested form with a polymorphic association.
Models
class Upload < ActiveRecord::Base
attr_accessible :link, :post_id
belongs_to :uploadable, polymorphic: true
end
class Post < ActiveRecord::Base
attr_accessible :description, :title, :uploads_attributes
has_many :uploads, as: :uploadable
accepts_nested_attributes_for :uploads, :reject_if => lambda { |a| a[:content].blank?
}, :allow_destroy => true
end
I tried too put accept_nested ... for :uploadable but tells me dont exist the association
The action new on the controller is this one
def new
#post = Post.new
#post.uploads.new
end
and here is the form for create
<%= form_for [:admin,#post], remote: true, :html => {:multipart => true} do |f| %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title%>
</div>
<div class="field">
<%= f.label :description%><br />
<%= f.text_area :description %>
</div>
<div>
<%= f.fields_for :upload do |builder| %>
<%= render 'upload_fields', f: builder %>
<% end %>
<%= link_to_add_fields "Add Upload", f, :uploads %>
</div>
<div class="actions">
<%= f.submit%>
</div>
<% end %>
The partial ...
<fieldset>
<%= f.label :file %><br />
<%= f.file_field :file %>
<%= f.hidden_field :_destroy %>
<%= link_to "remove", '#', class: "remove_fields" %>
</fieldset>
Dont think the javascript affects, so Im not going to put it here.
How I cna solve "Can't mass-assign protected attributes" on polymorphic asociations ?
Plz need help on this anyone. Cant belive I cant upload files, looks so simple on tutorials, and Its not working, or I get a Can't mass assign orthe upload its not saved ....
Try to use #post.uploads.build instead of #post.uploads.new
The associated model needs to know the identity of her parent to save the relationship.
I recommend you the following railscast: Polymorphic Association.
#uploads_controller.rb
before_filter :load_uploadable
def create
#upload = #uploadable.uploads.new(params[:upload])
....
end
private
def load_uploadable
resource, id = request.path.split('/')[1, 2] # /posts/1
#uploadable = resource.singularize.classify.constantize.find(id)
end
This line inside your view:
<%= f.fields_for :upload do |builder| %>
Should be this:
<%= f.fields_for :uploadable do |builder| %>
Because the association on the Post model is called "uploadable", not "upload".
For nested attributes to work, you will need to specify the model does accept nested attributes for this model, which can be done by putting this line underneath the belongs_to in your model:
accepts_nested_attributes_for :uploadable
And then you will need to make these attributes accessible, which you can do with this:
attr_accessible :uploadable_attributes

Creating forms for Multiple Nested Resources in Rails 3

I have been following Ryan Bates' tutorial on nested forms Railscast 196
The form for the new action shows the nested attributes for quizzes but does not show nested attributes for the key. I am guessing this is because quizzes have a has_many relationship where key has a has_one relationship... But I cannot figure out what I'm doing wrong?
Any help is much appreciated!
This is my model:
class Repository < ActiveRecord::Base
has_many :quizzes, :dependent => :destroy
has_one :key, :dependent => :destroy
accepts_nested_attributes_for :key, :quizzes
end
This is my controller:
def new
#repository = Repository.new
3.times { #repository.quizzes.build }
#repository.key = Key.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #repository }
end
end
This is my view:
<div class="field">
<%= f.label :wp_uid %><br />
<%= f.text_field :wp_uid %>
<% f.fields_for :quizzes do |quiz_fields| %>
<p>
<%= quiz_fields.label :name, "Name" %><br />
<%= quiz_fields.text_field :name %>
</p>
<% end %>
<% f.fields_for :key do |key_fields| %>
<div class="field">
<%= key_fields.label :value, "Value" %><br />
<%= key_fields.text_field :value %>
</div>
<div class="field">
<%= key_fields.label :expiry, "Expiry" %><br />
<%= key_fields.date_select :expiry %>
</div>
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
You should try modifying your fields_for blocks to use <%= %>
Try changing to:
<%= f.fields_for :key do |key_fields| %>
The railscast could have been made before the change in Rails 3 to use <%= %> instead of <%%>.
Ryan has a nested_form gem that you may find useful for this as well. I haven't tried using it yet, but plan to next time I start a new project.
https://github.com/ryanb/nested_form
Try building the key object as
#reposity.build_key
From the rails docmentation
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#label-Unsaved+objects+and+associations
If you wish to assign an object to a has_one association without saving it, use the build_association method. The object being replaced will still be saved to update its foreign key.

Resources