undefined method `name' for nil:NilClass on save - ruby-on-rails

I'm posting here because i can't find anyone with this error. I'm using Rails 4.0.2 and when i try to save my form (it uses a collection_check_box) it gives me this message:
NoMethodError (undefined method `name' for nil:NilClass):
app/controllers/projeto_controller.rb:34:in `block in create'
app/controllers/projeto_controller.rb:33:in `create'
I'm a little lost here because i don't have any attributes named name.
Here my controllers and models.
class Projeto < ActiveRecord::Base
belongs_to :usuario
has_many :projeto_temas
has_many :temas, through: :projeto_temas
accepts_nested_attributes_for :temas
validates_presence_of :titulo, :orgao_financiador, :periodo_inicio, :periodo_fim
end
class ProjetoController < ApplicationController
# GET /projeto/new
def new
#projeto = Projeto.new
render :layout => 'application_cadastro'
end
# POST /projeto
# POST /projeto.json
def create
#projeto = Projeto.new(projeto_params)
respond_to do |format|
if #projeto.save
format.html { redirect_to #projeto, notice: 'Projeto was successfully created.' }
format.json { render action: 'show', status: :created, location: #projeto }
else
format.html { render action: 'new' }
format.json { render json: #projeto.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /projeto/1
# PATCH/PUT /projeto/1.json
def update
respond_to do |format|
if #projeto.update(projeto_params)
format.html { redirect_to #projeto, notice: 'Projeto was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #projeto.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_projeto
#projeto = Projeto.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def projeto_params
params.require(:projeto).permit(:titulo, :usuario_id, :orgao_financiador, :periodo_inicio, :periodo_fim, :resumo, :temas_ids => [])
end
end
And the Temas model.
class Temas < ActiveRecord::Base
has_many :relacionamento_temas_pai, class_name: RelacaoTemas, foreign_key: :temas_pai_id
belongs_to :relacionamento_temas_filho, class_name: RelacaoTemas, foreign_key: :temas_filho_id
has_and_belongs_to_many :projeto
accepts_nested_attributes_for :relacionamento_temas_pai
validates :nome, presence: true
end
The part of the view with the ckeck_box
<div class="presquisadores-preview-action">
<div class="temas-projetos-checkbox">
<%= f.collection_check_boxes :temas_ids, Temas.all, :id, :nome %>
</div>
</div>
It has one attribute with the name nome which is portuguese for name, so it shouldn't affect anything.
Thanks in advance for the help, in really lost, and don't know what to do.
--EDIT
So... after a lot of research i didn't find the problem. Actually i was looking into some rails documentation and saw some issues with that version of the activerecord so i updated to rails 4.2.0 and the problem is now gone.
I still don't know what caused it, but now my form saves normally.
Thanks for all the help folks

This is an issue with Rails 4.0.2. I faced the same issue and when I updated to Rails 4.0.13 (the last in the 4.0.x series), the issue resolved itself.
From the github issues, I can only glean that this is because of some database bugs that Rails did not prepare for.

Related

Rails collection_check_boxes not returnig selected values

Im new on Rails and I feel a kind of stuck right now, I need to develop an app where you associate Congresses and Users, has_and_belong_to_many, the point is that I have this on my view:
<div class="field">
<%= f.label :administrators_id %>
<%= f.collection_check_boxes :administrators_id, #users,'id','user_id',{multiple: true, class: 'checkbox inline'} %>
this is on my controllers:
def new
#congress = Congress.new
#users = User.all
end
# GET /congresses/1/edit
def edit
#users = User.all
end
# POST /congresses
# POST /congresses.json
def create
#congress = Congress.new(congress_params)
respond_to do |format|
if #congress.save
format.html { redirect_to #congress, notice: 'Congress was successfully created.' }
format.json { render :show, status: :created, location: #congress }
else
format.html { render :new }
format.json { render json: #congress.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /congresses/1
# PATCH/PUT /congresses/1.json
def update
respond_to do |format|
if #congress.update(congress_params)
format.html { redirect_to #congress, notice: 'Congress was successfully updated.' }
format.json { render :show, status: :ok, location: #congress }
else
format.html { render :edit }
format.json { render json: #congress.errors, status: :unprocessable_entity }
end
end
end
But I dont get it to work, checked vales adoes not store at all.
Thanks for your help!
class User < ApplicationRecord
has_many :adminstrations
has_many :congresses, through: :adminstrations
end
class Congress < ApplicationRecord
has_many :adminstrations
has_many :adminstrators, through: :adminstrations,
source: :user
end
class Administration < ApplicationRecord
belongs_to :user
belongs_to :congress
end
See Why You Don’t Need Has_and_belongs_to_many Relationships. You can call the join model whatever you want. But in 99% of cases you'll want to have it sooner or later.
To assign associations from an array (created by a select or checkboxes) you need to use the _ids setter. Not _id. _id is singular and will only work if the relation is one to one.
<div class="field">
<%= f.label :administrators_ids %>
<%= f.collection_check_boxes :administrators_ids, #users, :id, :email, {multiple: true, class: 'checkbox inline'} %>
</div>
The two methods should be the value and the label method to be used on the user instance when generating the option tags. Use symbols here instead of strings for readability.
Make sure you are whitelisting the correct param as well:
def congress_params
params.require(:congress)
.permit(:foo, :bar, :administrators_ids)
end

Rails - how to reference namespaced table attributes in views

I am trying to learn how to use namespaces in my Rails 5 app.
I have an organisation model and I have also made a series of nested models under the folder name "stance". One of those models is called overview.
The associations are:
Organisation.rb
has_one :overview, class_name: Stance::Overview
accepts_nested_attributes_for :overview, reject_if: :all_blank, allow_destroy: true
Stance::Overview
class Stance::Overview < ApplicationRecord
belongs_to :organisation, inverse_of: :overview
My controllers for stance resources are nested under a folder called stance.
My routes are:
namespace :stance do
resources :overviews
end
In my stance view partial, I am trying to render the attributes from the overview table.
I have tried:
<p><%= #overview.internal_explanation %></p>
<p><%= #stance_overview.internal_explanation %></p>
<p><%= #stance.overview.internal_explanation %></p>
<p><%= #stance::overview.internal_explanation %></p>
I want to display this partial in my organisation show. I am trying to do that with:
<%= render 'stance/overviews/internal', overview: #overview %>
But I can't figure out how to access the overview table. Do I need to add a reference to 'stance' in the associations?
I can see that in the console I need to write:
o = Stance::Overview.create(internal_explanation: "test")
o = Stance::Overview.first
but I can't see how to use that in the code itself.
I can see in the console that there is a record for this attribute.
The name of the table in the schema is "stance_overview".
My organisation controller has:
class OrganisationsController < ApplicationController
before_action :set_organisation, only: [:show, :edit, :update, :destroy]
def index
#organisations = Organisation.all
end
def show
end
def new
#organisation = Organisation.new
#organisation.build_overview
end
def edit
#organisation.build_overview unless #organisation.overview
end
def create
#organisation = Organisation.new(organisation_params)
respond_to do |format|
if #organisation.save
format.html { redirect_to #organisation, notice: 'Organisation was successfully created.' }
format.json { render :show, status: :created, location: #organisation }
else
format.html { render :new }
format.json { render json: #organisation.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #organisation.update(organisation_params)
format.html { redirect_to #organisation, notice: 'Organisation was successfully updated.' }
format.json { render :show, status: :ok, location: #organisation }
else
format.html { render :edit }
format.json { render json: #organisation.errors, status: :unprocessable_entity }
end
end
end
def destroy
#organisation.destroy
respond_to do |format|
format.html { redirect_to organisations_url, notice: 'Organisation was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_organisation
#organisation = Organisation.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def organisation_params
params.fetch(:organisation, {}).permit(:title, :comment,
overview_attributes: [:internal_explanation, :external_explanation ]
)
end
end
I have also tried defining the strong params for organisation as:
stance_overview_attributes: [:internal_explanation, :external_explanation ]
I keep getting an error that says:
undefined method `internal_explanation' for nil:NilClass
Can anyone refer me to materials to help me learn how to use namespaces in my app. I am trying to understand the fundamentals of this so that I can bank some knowledge. I am finding things through trial and error but not understanding what's actually required (although in this case, none of my attempts are working out).
To access Overview model(table) when you working not in Stance namespace you have to use Stance::Overview. If working for example in a controller that in Stance namespace you can use just Overview for access.
To get access from the relation you don't need any additional notation just #organisation.overview.
If I understand correctly in you case you have to declare your partial as
<%= render 'stance/overviews/internal', overview: #organisation.overview %>
and in the partial you have to use overview without #.

How to properly associate a model with multiple models?

I've tried to implement many of the proposed solutions in the relevant questions, but haven't yet found an answer ideal for what I'm trying to achieve in my Rails 4 application.
Basically my app has three models. Users, Hooks (embeddable pop-up widgets) and Contacts. Users can create Hooks and Contacts within their interface. And any visitor can create a new contact by filling out the Contact create form placed within a Hook's view, and that contact is associated with the user who created that hook.
That works fine, however when a contact is created by filling out a Hook's form, there's no connection to the specific Hook they completed the form in.
The next set of features I would like to add to my app requires not only associating each contact with a user, but also with the specific Hook it was created from.
I've read a bit into polymorphic associations (model belongs to multiple models) and I understand that's probably the way to go. After a couple of failed attempts, I'm not sure how to implement it though.
How would I associate Contacts with Hooks, so users can know which hook a contact was created from?
Here is what I currently have in the Hooks controller and model...
def create
#hook = hook.new(hook_params)
#hook.user = current_user
#contact = Contact.new(contact_params)
respond_to do |format|
if #hook.save
format.html { redirect_to #hook, notice: 'Hook was successfully created.' }
format.json { render :show, status: :created, location: #hook }
format.js
else
format.html { render :new }
format.json { render json: #hook.errors, status: :unprocessable_entity }
format.js
end
end
end
class Hook < ActiveRecord::Base
belongs_to :user
has_attached_file :image, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "https://s3.amazonaws.com/app/assets/leadmagnet.png"
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
end
And here is the contacts controller and model...
def create
#contact = Contact.new(contact_params)
#contact.user = current_user
respond_to do |format|
if #contact.save
if user_signed_in?
format.html { redirect_to #contact, notice: 'Contact was successfully created.' }
else
format.html { redirect_to #contact, notice: 'Contact was successfully created.' }
end
format.json { render :show, status: :created, location: #contact }
else
format.html { render :new }
format.json { render json: #contact.errors, status: :unprocessable_entity }
end
end
end
class Contact < ActiveRecord::Base
belongs_to :owner, :class_name => 'User'
belongs_to :user
validates :email, :presence => {:message => 'Email cannot be blank'}
end
First off, you should never ever ever create 2 unrelated models on the same controller action. It breaks conventions and will only lead to problems.
You do not need to directly associate Contacts to Users. You should associate Contacts to Hooks and then associate Contacts through Hooks
class User < ActiveRecord::Base
has_many :hooks
has_many :contacts, through: :hooks
end
class Hook < ActiveRecord::Base
belongs_to :user
has_many :contacts
accepts_nested_attributes_for :contacts
end
class Contact < ActiveRecord::Base
belongs_to :hook
end
Now on the create action of the ContactsController, you can first get the Hook either by URL param or passed via post body. You can first find the Hook and create the Contact on it via:
hook = Hook.find(hook_id)
#contact = hook.contacts.new(contacts_param)
If you want to create contacts when creating a new Hook, you need to add :contacts_attributes on the strong_params, then pass an array of contact attributes via the POST. Adding accepts_nested_attributes_for to the Hook model allows you to easily create Contacts while creating Hooks by simply entering:
#hook = Hook.new(hook_params)
If I understand correctly, you want to create both a Hook and a Contact, and associate both to current_user. In your code you create both, but you only associate #hook with the current_user, and only save it, while ignoring the #contact. Simply associate it and save it as well:
def create
#hook = hook.new(hook_params)
#hook.user = current_user
#contact = Contact.new(contact_params)
#contact.user = current_user
respond_to do |format|
if #hook.save && #contact.save
format.html { redirect_to #hook, notice: 'Hook was successfully created.' }
format.json { render :show, status: :created, location: #hook }
format.js
else
format.html { render :new }
format.json { render json: #hook.errors + #contact.errors, status: :unprocessable_entity }
format.js
end
end
end

I am trying to duplicate an activerecord record, but receive NoMethodError - undefined method

Forgive my ignorance but I am quite new to RoR. I am working on a project where users are able to duplicate a post in order to edit this "cloned version" and to save it (with a new post id, of course).
First I tried to use the Amoeba gem described like here, but I failed.
Then I thought I found a better solution - Duplicating a record in Rails 3 - but when I am integrating the suggested code, I am receiving the following error:
NoMethodError in Posts#show
undefined method `clone_post_path' for #<#:0x0000010267b8c8>
Researching and tinkering for hours now, I would really appreciate any help!
I am using Rails 3.2.13.
In my posts_controller I have the following code:
def show
#post = Post.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #post }
end
end
def new
#post = current_user.posts.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #post }
end
end
def clone
#post = current_user.posts.find(params[:id]) # find original object
#post = current_user.posts.new(#post.attributes) # initialize duplicate (not saved)
render :new # render same view as "new", but with #post attributes already filled in
end
def create
#post = current_user.posts.new(params[:post])
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render json: #post, status: :created, location: #post }
else
format.html { render action: "new" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
This is the post.rb model:
class Post < ActiveRecord::Base
attr_accessible :content, :title, :videos, :link, :description
validates :title, presence: true
belongs_to :user
end
In the show view I call this:
<%= link_to 'Create a clone', clone_post_path(#post) %>
What am I doing wrong?
Thank you so much in advance for any help!
UPDATE:
Adding
resources :posts do
get 'clone', on: :member
end
to the routes file worked.
Here is the routes file:
Tt::Application.routes.draw do
devise_for :users
get 'about' => 'pages#about'
resources :posts
root :to => 'pages#home'
post 'attachments' => 'images#create'
resources :posts do
get 'clone', on: :member
end
end
Unfortunately afterwards a new error occurred:
ActiveModel::MassAssignmentSecurity::Error in PostsController#clone
Can't mass-assign protected attributes: id, created_at, updated_at, image_file_name, image_content_type, image_file_size, image_updated_at, file, user_id
Make sure that your routes file includes the following:
resources :posts do
get 'clone', on: :member
end
Since the clone action is not a standard action you must account for it in your routes file so it knows what to do.

Subform for parent object

So I've been holding off putting a question on here because I don't want to bother the community with stupid questions, but I'm going to ask for help now anyway.
I'm quite new to Ruby on Rails, and as you've probably read from the title, I'm having trouble with my subform. More specifically, with assigning the parent object to a client object. I'm building a system for my work in where employees can register repairs (mobile phones) and keep track of them. I'm building the client object with #repair = Repair.new, which works fine, but when I try to set the Client with #repair = Client.new, the :client_id on the repair stays null.
Here's my repair.rb: (some fields are in Dutch, please ignore that)
class Repair < ActiveRecord::Base
attr_accessible :imei, :klantnaam, :telefoon, :intake, :branch_id, :id, :client_id
attr_accessible :merk, :type, :batterij, :lader, :headset, :batterijklep, :carkit, :schade_toestel, :schade_scherm, :bon, :datum_bon, :klacht, :prijsindicatie
belongs_to :branch
belongs_to :client
accepts_nested_attributes_for :client
end
client.rb:
class Client < ActiveRecord::Base
attr_accessible :email, :firstname, :lastname, :number, :phone, :postalcode
has_many :repairs
end
repairs_controller.rb: (I've left the irrelevant methods out, I was getting tired of the 4 spaces :P)
class RepairsController < ApplicationController
# GET /repairs/new
# GET /repairs/new.json
def new
#repair = Repair.new
#repair.client = Client.new
if request.remote_ip == "xx.xx.xx.xx"
#repair.branch = Branch.where(:name => "Xxxxxxx").first
end
#repair.intake = Time.now
respond_to do |format|
format.html # new.html.erb
format.json { render json: #repair }
end
end
# POST /repairs
# POST /repairs.json
def create
#repair = Repair.new(params[:repair])
respond_to do |format|
if #repair.save
format.html { redirect_to #repair, notice: 'Repair was successfully created.' }
format.json { render json: #repair, status: :created, location: #repair }
else
format.html { render action: "new" }
format.json { render json: #repair.errors, status: :unprocessable_entity }
end
end
end
end
And this is the JSON I get from /repair/new.json:
{"batterij":null,"batterijklep":null,"bon":null,"branch_id":null,"carkit":null,"client_id":null,"created_at":null,"datum_bon":null,"headset":null,"id":null,"imei":null,"intake":"2013-02-01T23:29:10Z","klacht":null,"klantnaam":null,"lader":null,"merk":null,"pickup":null,"prijsindicatie":null,"schade_scherm":null,"schade_toestel":null,"telefoon":null,"updated_at":null}
By the way, the branch assignment works flawlessly... (It's null now because I'm not on the IP I specified in the new method)
Please help me out... :-(
Robin
Solved it!!
The code above all works flawlessly, the problem was a <% instead of <%= in my view, which made my subform not show up. Duhh.

Resources