I am trying to allow a user to enter a project into a database. One of the fields allows them to enter multiple technologies for that project.
Here is my project controller, new and create action.
def new
#project = Project.new
#all_technols = Technol.all
#project_technol = #project.projecttechnols.build
respond_to do |format|
format.html # new.html.erb
format.json { render json: #project }
end
end
def create
#project = Project.new(params[:project])
params[:technols][:id].each do |technol|
if !technol.empty?
#project.projecttechnols.build(:technol_id => technol)
end
end
end
Here is my new project view for the multi select technology dropdown.
<%= fields_for(#project_technol) do |ab| %>
<div class="tech">
<%= ab.label "All Tech" %><br/>
<%= collection_select(:technols, :id, #all_technols, :id, :tech, {}, {:multiple => true} ) %>
</div>
<% end %>
project.rb
class Project < ActiveRecord::Base
attr_accessible :tech
has_many :projecttechnols
has_many :technols, :through => :projecttechnols
end
technol.rb
class Technol < ActiveRecord::Base
attr_accessible :tech
has_many :projecttechnols
has_many :projects, :through => :projecttechnols
end
projecttechnol.rb
class Projecttechnol < ActiveRecord::Base
attr_accessible :project_id, :technol_id
belongs_to :technol
belongs_to :project
end
At the moment, I have a page where the user can enter a new technology. But I want to move this option to the create new project page, where they can either select existing technologies, or enter a new one, or do both, and they would save with that project.
When I try to save a new project however, I am getting this error.
Showing /home/james/Desktop/webapp/app/views/projects/new.html.erb where line #233 raised:
undefined method `model_name' for NilClass:Class
Extracted source (around line #233):
233: <%= fields_for(#project_technol) do |ab| %>
234:
235: <div class="tech">
236: <%= ab.label "All Tech" %><br/>
I am new to rails and still learning so please remember when answering. Thanks in advance.
EDIT
after changing
#project.projecttechnols.build(:technol_id => technol)
to
#project_technol = #project.projecttechnols.build(:technol_id => technol)
I now get this error:
NoMethodError in Projects#create
undefined method `map' for nil:NilClass
Extracted source (around line #240):
237: <div class="tech">
238: <%= ab.label "All Tech" %><br/>
239:
240: <%= collection_select(:technols, :id, #all_technols, :id, :tech, {}, {:multiple => true} ) %>
241: </div>
242: <% end %>
EDIT 2
#all_technols = Technol.all in the create action
I now get this error.
NoMethodError in Projects#show
Showing /home/james/Desktop/webapp/app/views/projects/show.html.erb where line #181 raised:
undefined method `technol' for #<Project:0xb36823c>
Extracted source (around line #181):
178: <h3>Related books</h3>
179:
180: <ul>
181: <% #project.technol.each do |technol| %>
182: <li><%= technol.tech %> <%= link_to "Details", technol_path(technol) %></li>
183: <% end %>
184: </ul>
Your create action is rendering the new view again. However, #project_technol is not defined within the create action. The fields_for method calls model_name method on the argument passed in (#project_technol), but since #project_technol = nil, it's throwing that error. To fix this, within your create action, change
#project.projecttechnols.build(:technol_id => technol)
to
#project_technol = #project.projecttechnols.build(:technol_id => technol)
Related
I am trying to work in my first implementation using fields_for to manage creating has_many relationship in one form partial. This form partial itself is part of a nested resource
So far, I am able to render, save and edit the form successfully without the fields_for nested form.
When I include the fields_for in the form_for, white-list the params, and build the objects in #new, I get this error in the console as it failed to save and re renders the #new view:
(0.1ms) rollback transaction
What can I do to successfully save the form along with the nested_attributes?
routes.rb
....
resources :projects do
resources :step_ones
resources :step_threes
resources :step_twos
resources :step_fours
resources :step_fives
resources :timelines
end
step_four.rb
class StepFour < ApplicationRecord
belongs_to :project
has_many :ios_devices
accepts_nested_attributes_for :ios_devices
end
ios_device.rb
class IosDevice < ApplicationRecord
belongs_to :step_four
end
_form.html.erb
<div>
<%= form_for([#project, #step_four]) do |f| %>
....
<%= f.fields_for :ios_devices do |d| %>
<div class='form-group'>
<%= d.label :full_name, "Name:"%>
<%= d.text_field :full_name %>
<%= d.label :email, "Email:"%>
<%= d.text_field :email %>
<%= d.label :udid, "UDID:"%>
<%= d.text_field :udid %>
<% end %>
<%= hidden_field_tag :project_id, :value => #project.id %>
<div class='row'>
<span class='col-md-6'><%= button_to "Back", project_path(#project), method: :get, class:'btn btn-primary full-wide-button main-btn' %></span>
<span class='col-md-6'><%= f.submit 'Save Data', class: 'btn btn-primary full-wide-button'%></span>
</div>
<% end %>
</div>
step_fours_controller.rb
class StepFoursController < ApplicationController
def new
#project = Project.find(params[:project_id])
#step_four = StepFour.new
3.times { #step_four.ios_devices.build }
end
def create
#step_four = StepFour.new(step_four_params)
#project = Project.find(params[:project_id])
#step_four.ios_devices.each do |d|
puts d.full_name
puts d.email
puts d.udid
end
#step_four.project_id = params[:project_id]
if #step_four.save
flash[:success] = "Step Five Data Saved"
redirect_to #project
else
flash[:danger] = "Data Not Saved. Please Try Again"
render "new"
end
end
def show
#step_four = StepFour.where(project_id: (params[:project_id])).first
end
def update
#step_four = StepFour.where(project_id: (params[:project_id])).first
#project = Project.find(params[:project_id])
if #step_four.update_attributes(step_four_params)
flash[:success] = "Step Four Data Saved"
redirect_to #project
else
flash[:danger] = "Data Not Saved. Please Try Again"
render 'edit'
end
end
def edit
#step_four = StepFour.where(project_id: (params[:project_id])).first
#project = Project.find(params[:project_id])
end
def step_four_params
params.require(:step_four).permit(:iphone_name, :iphone_nickname, :android_name, ios_devices_attributes: [:id, :full_name, :email, :udid])
end
end
After realizing that the error was upon the save method, I tried to force the issue and raise an exception with a shebang ! . I received a Validation error that lead me to this question:
Error: Validation failed: Images imageable must exist , rails-5.0 , paperclip-5
I needed to add optional: true to the belongs_to: step_four in the ios_device model since, I believe that the object doesn't exist yet.
Now everything is working
I have a model called project and another called invite.
The associations are:
Project
has_many :invites
Invite
belongs_to :project
I want to allow users who create projects to send invites to other users to join them in working on the project.
I have a form to create invites as follows:
<%= simple_form_for(#invite, :url => invites_path) do |f| %>
<%= f.hidden_field :recipient_id, :value => get_recipient_id %>
<%#= f.hidden_field :project_id, :value => current_user.profile.project_id %>
<%= f.hidden_field :project_id, :value => #invite.project_id %>
<%= f.label :email %>
<%= f.email_field :email %>
<!-- This field should use :date_picker- but it isnt working -->
<%= f.input :expiry, :as => :date, :label => "When do you need a response to this invitation?" %>
<%#= f.input :expiry, :as => :date_picker, :label => "When do you need a response to this invitation?" %>
<%= f.submit 'Send', :class=>"formsubmit" %>
<% end %>
In the above form, I'm trying to set the project_id value.
In the invites controller, I have:
class InvitesController < ApplicationController
before_action :get_project
def index
#invites = #project.invites
end
def new
# #invite = Invite.new
#invite = #project.invites.build
end
def create
#invite = Invite.new(invite_params)
#invite.sender_id = current_user.profile.id
# #project = Project.find(params[:project_id])
if #invite.save
#send existing user email invitation to join project team
InviteMailer.existing_user_invite(#invite).deliver_later
format.html { redirect_to #project }
#invite.recipient.project.push(#invite.project)
else
#invite.recipient.project.push(#invite.project)
InviteMailer.new_user_invite(#invite, new_user_registration_path(:invite_token => #invite.token)).deliver
end
# oh no, creating an new invitation failed
end
private
# Use callbacks to share common setup or constraints between actions.
def set_invite
#invite = Invite.find(params[:id])
end
def get_project
#project = Project.find(params[:project_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def invite_params
params[:invite].permit(:email, :project_id, :recipient_id)
end
end
I thought the get_project before action would get the project. Instead, I get an error that says:
undefined method `project_id' for #<Profile:0x007fa179509b60>
Did you mean? project_ids
project_ids=
projects
object_id
The error message points to the hidden field in my form for project_id.
Can anyone see where I'm going wrong?
The problem is with the statement current_user.profile.project_id in one of the hidden form fields.
(The error message points to this code but I don't know why you have commented that line in the post)
The error clearly says that a profile does not have a project_id and a user can have many projects. If you want to access the project_id, you can do something like this.
<%= f.hidden_field :project_id, value: #project.id %>
#project is accessible from the controller through the get_project method.
Hey i´ve got another problem ;)
When i try to create a new Book in my app it always says
undefined method "model_name" for NilClass:Class
I found out that it must be an uninitialized param in the Form_for function... Here my code:
NoMethodError in Books#new
Showing /app/views/books/_form.html.erb where line #1 raised:
undefined method `model_name' for NilClass:Class
Extracted source (around line #1):
1: <%= form_for(#book) do |f| %>
2: <% if #book.errors.any? %>
3: <div id="error_explanation">
4: <h2><%= pluralize(#book.errors.count, "error") %> prohibited this book from being saved:</h2>
Controller:
#GET /books/new
#GET /books/new.json
def new
#users = User.find(:all)
#book = Book.new
1.times{ #book.chapters.build }
#book.users = [current_user]
respond_to do |format|
format.html #new.html.erb
format.json { render json: #book }
end
end
I don´t know why it should be uninitialized, it worked properly before I changed some relations between Books and Users but I there shoudn´t be the failure or?
EDIT:
app/views/books/new.html.erb :
<h1>New book</h1>
<%= render 'form' %>
<%= link_to 'Back', books_path %>
And the Model :
class Book < ActiveRecord::Base
attr_accessible :abstract, :status, :titel, :user_tokens, user_ids, :chapters_attributes
has_and_belongs_to_many :users
attr_reader :user_tokens
has_many :chapters, :dependent => :destroy, :autosave => true, :order => 'slot'
validates :title, :presence => true
accepts_nested_attributes_for :chapters, :allow_destroy => true
after_initialize :init
def init
self.status = false if self.status?
end
def user_tokens=(ids)
self.user_ids = ids.split(",")
end
end
end
Your partial will not know the instance variables you set up in the controller. You will have to pass them as locals when you render the partial
render :partial => "form", :locals => {:book => #book}
And in your partial, use book instead of #book
<%= form_for(book) do |f| %>
<% if book.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(book.errors.count, "error") %> prohibited this book from being saved:</h2>
i'm building a relations Company :has_many Notes.
i want to be able to add some new notes to a just created company in the Comany#show resource. so in the company scaffold's show.html.erb
i have follwed step by step the cocoon demostration app and from the github mardown, but the examples shows only the method to add nested attribute into _form.html.erb partial. I don't know if there is some particular things to do differently, but when i try to run the Company#show action it retrieves this error:
undefined method `new_record?' for nil:NilClass
this is my code:
show.html.erb:
...
<%= simple_form_for :notes, :html => { :class => 'form-horizontal' } do |note| %>
<%= render 'note_fields', :f => note %>
<% end %>
<%= link_to_add_association 'Aggiungi Nota', f, :notes, :render_options => {:wrapper => 'inline' } %>
...
_note_fields.html.erb:
...
<div class="nested-fields">
<%= f.input :body %>
<%= link_to_remove_association "Elimina Nota", f %>
</div>
...
Company.rb:
...
has_many :notes
accepts_nested_attributes_for :notes, :reject_if => :all_blank, :allow_destroy => true
...
Note.rb
class Note < ActiveRecord::Base
attr_accessible :body, :company_id
belongs_to :company
end
company_controller.rb
def show
#company = Company.includes(:category, :clients, :notes).find(params[:id])
#mapCompany = Company.find(params[:id]).to_gmaps4rails
respond_to do |format|
format.html # show.html.erb
format.json { render json: #company }
end
end
thanks!
Dave
In the following code, the f variable was never defined.
<%= link_to_add_association 'Aggiungi Nota', f, :notes, :render_options => {:wrapper => 'inline' } %>
Try using company instead of f.
Ok so i am tring to list my genres in a f.select form and I am getting an error. I have look everywhere and i am just not understanding what i am doing differently. when I enter rails c and type g = Genre.all it lists all genres then g.map out puts => #<Enumerator: ...>
Error:
undefined method `map' for nil:NilClass
View Page:
<%= f.fields_for :genres do |g| %>
<div class="field">
<%= g.label :genre %>
<%= g.select :genres, #genres.map {|g| g.name} %>
</div>
<% end %>
Controller:
def create
#song = Song.new(params[:song])
#genres = Genre.all
if #song.save
redirect_to player_path
else
render :new
end
end
You need to assign #genres variable in new action too:
def new
#genres = Genre.all
end