undefined method `title' for nil:NilClass in mailer - ruby-on-rails

I am pretty new to ror, and I run into some issue with my application:
I have a ticket model and a comment model,
class Ticket < ActiveRecord::Base
attr_accessible :content, :title, :user, :priority, :category, :status
validates_presence_of :content, :title, :category
has_many :comments, dependent: :destroy
accepts_nested_attributes_for :comments
end
class Comment < ActiveRecord::Base
attr_accessible :content, :ticket_id, :user
belongs_to :ticket
end
Now I want to send a mail when a comment is created:
In comment controller:
def create
#comment = Comment.new(params[:comment])
respond_to do |format|
if #comment.save
TicketMailer.ticket_commented(#comment).deliver
format.html { redirect_to #comment, notice: 'Comment was successfull created.' }
format.json { render json: #comment, status: :created, location: #comment }
else
format.html { render action: "new" }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
Then in mailer:
class TicketMailer < ActionMailer::Base
default from: "helpdesk#testing.com"
def ticket_commented(comment)
#comment = comment
#ticket = Ticket.find_by_id(#comment.id)
mail(:to => #comment.user, :subject => 'New comment')
end
end
But when I try to call
<%= #ticket.title %>
In view, I got this error: undefined methodtitle' for nil:NilClass`
Did I do something wrong? Or how can I pass #ticket into the mailer correctly?

In your mailer you're trying to find a ticket by providing the id of a comment, change the line #ticket = Ticket.find_by_id(#comment.id) to #ticket = #comment.ticket

Related

ActiveModel::MissingAttributeError - rails

I have some problem with my code:
Models:
class UsefulPhrase < ActiveRecord::Base
has_many :useful_phrase_contents
accepts_nested_attributes_for :useful_phrase_contents
validates_presence_of :key
end
class UsefulPhraseContent < ActiveRecord::Base
belongs_to :useful_phrase
attr_accessor :useful_phrase_id
validates_presence_of :language, :content
end
Controller:
def new
#useful_phrase = UsefulPhrase.new
#available_languages = available_languages
#useful_phrase.useful_phrase_contents.build
end
def create
#useful_phrase = UsefulPhrase.new(useful_phrase_params)
#useful_phrase.useful_phrase_contents.build(upc_params)
respond_to do |format|
if #useful_phrase.save
format.html { redirect_to #useful_phrase, notice: 'bla-bla' }
format.json { render :show, status: :created, location: #useful_phrase }
else
format.html { render :new }
format.json { render json: #useful_phrase.errors, status: :unprocessable_entity }
end
end
end
def useful_phrase_params
params.require(:useful_phrase).permit(:key)
end
def upc_params
params.require(:useful_phrase).require(:useful_phrase_content).permit(:language, :content)
end
When i'm trying save any record I get:
ActiveModel::MissingAttributeError at /useful_phrases
can't write unknown attribute useful_phrase_id
I don't know how to repair it.
try edit your parameter in your upc_params
params.require(:useful_phrase)
.permit(:language, content, :useful_phrase_content => [puttheattributefor use_ful_phrase_content])

Rails 5 Nested attributes "Unpermitted parameter" - Whitelisted

Error: Unpermitted parameter: properties
I'm whitelisting the properties{} in the request_controller.rb
This usually works but not this time.
I'm not been able to save some of the data entered in a form. The 3 fields that are not saving are coming from a dynamic form "request_type". I followed Rails Cast episode 403 for this solution, which I have working well in another project but not in this one.
Source: http://railscasts.com/episodes/403-dynamic-forms
Sorry if this is a duplicate question, but I've looked at several other questions and I can't pin-point what I'm doing wrong here
I've researched several questions here, but I'm still not able to get it to work:
Rails 4 Nested Attributes Unpermitted Parameters
Nested attributes - Unpermitted parameters Rails 4
I'm omitting some stuff to make it easier to read the code. Please ask me if you need to see more.
Here's the log:
Processing by RequestsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"8EASewOIxY58b+SU+dxd2YAfpjt38IdwNSju69RPwl/OKfx3AfmvLav79igj8CqPbDwi0eJAwojRbtm+C9F6wg==", "request"=>{"name"=>"asdasddaa", "due_date(1i)"=>"2016", "due_date(2i)"=>"9", "due_date(3i)"=>"15", "user_id"=>"1", "project_id"=>"1", "request_type_id"=>"2", "properties"=>{"Name and last name"=>"asdasd", "Mobile"=>"asdada", "Office tel."=>"asdadas"}}, "commit"=>"Create Request"}
Unpermitted parameter: properties
Update
If I change the request_params to this:
def request_params
params.require(:request).permit(:name, :due_date, :group_id, :user_id, :project_id, :request_type_id, properties:{} ).tap do |whitelisted|
whitelisted[:properties] = params[:request][:properties]
end
end
See:
properties:{}
I get this Error:
Unpermitted parameters: Name and last name, Mobile, Office tel.
request_controller.rb
def new
#request = Request.new
#request_type = RequestType.find(params[:request_type_id])
#project = #request_type.project.id
end
def create
#request = Request.new(request_params)
respond_to do |format|
if #request.save
format.html { redirect_to #request, notice: 'Request was successfully created.' }
format.json { render :show, status: :created, location: #request }
else
format.html { render :new }
format.json { render json: #request.errors, status: :unprocessable_entity }
end
end
end
def request_params
params.require(:request).permit(:name, :due_date, :group_id, :user_id, :project_id, :request_type_id, :properties).tap do |whitelisted|
whitelisted[:properties] = params[:request][:properties]
end
end
request_types_controller.rb
def new
#request_type = RequestType.new
#project = Project.find(params[:project])
end
def create
#request_type = RequestType.new(request_type_params)
respond_to do |format|
if #request_type.save
format.html { redirect_to #request_type, notice: 'Request type was successfully created.' }
format.json { render :show, status: :created, location: #request_type }
else
format.html { render :new }
format.json { render json: #request_type.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #request_type.update(request_type_params)
format.html { redirect_to #request_type, notice: 'Request type was successfully updated.' }
format.json { render :show, status: :ok, location: #request_type }
else
format.html { render :edit }
format.json { render json: #request_type.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_request_type
#request_type = RequestType.find(params[:id])
end
def request_type_params
params.require(:request_type).permit(:name, :project_id, properties:{}, fields_attributes: [:name, :field_type, :required, :id, :_destroy])
# params.require(:product_type).permit(:name, :product_type_id)
end
models/request.rb
class Request < ApplicationRecord
belongs_to :group
belongs_to :user
belongs_to :project
belongs_to :request_type
serialize :properties, Hash
end
models/request_type.rb
class RequestType < ApplicationRecord
belongs_to :project
has_many :fields, class_name: "RequestField"
accepts_nested_attributes_for :fields, allow_destroy: true
has_many :requests
end
models/request_field.rb
class RequestField < ApplicationRecord
belongs_to :request_type
end
views/requests/new.html.erb
<%= form_for #request do |f| %>
<%= f.fields_for :properties, OpenStruct.new(#request.properties) do |builder| %>
<% #request_type.fields.each do |field| %>
<%= render "requests/fields/#{field.field_type}", field: field, f: builder %>
<% end %>
<% end %>
<div class="actions">
<%= f.submit class:"btn btn-primary" %>
</div>
<% end %>
Try removing :properties from your request_params in your request_controller like this:
def request_params
params.require(:request).permit(:name, :due_date, :group_id, :user_id, :project_id, :request_type_id).tap do |whitelisted|
whitelisted[:properties] = params[:request][:properties]
end
EDIT
def request_params
params.require(:request).permit(:id, :name, :due_date, :group_id, :user_id, :project_id, :request_type_id)
params.require(:properties).permit!
end!

Rails 4- Complex model validation (has_many, through)

I am trying to validate the "name" attribute in my Ingredient model. However, when I add validates :name, :uniqueness => true in my Ingredient model, it does not validate the name (can insert ingredient with same name). The ingredient model has a complex relationship with other model. Please see the code below.
My ultimate goal is to allows user to create ingredient if the ingredient does not exist in the Ingredient table. If the ingredient already existed, used the ingredient id for quantity. If anyone has any idea how to achieve that, please provide the solution to it. Thanks in advance.
ingredient.rb
class Ingredient < ActiveRecord::Base
has_many :quantities
has_many :recipes, through: :quantities
validates :name, :presence => true, :uniqueness => true
end
quantity.rb
class Quantity < ActiveRecord::Base
belongs_to :ingredient
belongs_to :recipe
accepts_nested_attributes_for :ingredient,
:reject_if => :all_blank
validates :ingredient, :uniqueness => true
end
recipe.rb
class Recipe < ActiveRecord::Base
has_many :quantities,
dependent: :destroy
has_many :ingredients,
:through => :quantities
accepts_nested_attributes_for :quantities,
reject_if: :all_blank,
allow_destroy: true
accepts_nested_attributes_for :ingredients
end
view section for creating Ingredient:
%strong Ingredients:
%fieldset#recipe-ingredients
%br
= f.fields_for :quantities do |builder|
= render 'recipe/quantity_fields', f: builder
.links
= link_to_add_association 'add ingredient', f, :quantities, 'data-association-insertion-node' => '#recipe-ingredients', 'data-assoication-insertion-moethod' => "append", :wrap_object => Proc.new{|quantity| quantity.ingredient.build ; quantity}
%br
Ingredient controller:
class IngredientController < ApplicationController
before_action :set_ingredient, only: [:show, :edit, :update, :destroy]
# GET /ingredients
# GET /ingredients.json
def index
#ingredients = Ingredient.all
end
# GET /ingredients/1
# GET /ingredients/1.json
def show
end
# GET /ingredients/new
def new
#ingredient = Ingredient.new
end
# GET /ingredients/1/edit
def edit
end
def create
#ingredient = Ingredient.new(ingredient_params)
respond_to do |format|
if #ingredient.save
format.html { redirect_to #ingredient, notice: 'Ingredient was successfully created.' }
format.json { render :show, status: :created, location: #ingredient }
else
format.html { render :new }
format.json { render json: #ingredient.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /ingredients/1
# PATCH/PUT /ingredients/1.json
def update
respond_to do |format|
if #ingredient.update(ingredient_params)
format.html { redirect_to #ingredient, notice: 'Ingredient was successfully updated.' }
format.json { render :show, status: :ok, location: #ingredient }
else
format.html { render :edit }
format.json { render json: #ingredient.errors, status: :unprocessable_entity }
end
end
end
# DELETE /ingredients/1
# DELETE /ingredients/1.json
def destroy
#ingredient.destroy
respond_to do |format|
format.html { redirect_to ingredients_url, notice: 'Ingredient was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_ingredient
#ingredient = Ingredient.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def ingredient_params
params.require(:ingredient).permit(:name)
end
end
It seems like a known issue probably a bug. Check this: https://github.com/rails/rails/issues/20676

Matching up collection_select output with strong parameters

In rails console & using the models below, I connected grades K, 1, and 2 to the school whose Edit form has this select field:
As you can see, that association correctly selects the 3 items in the field, but if I click to select/deselect grades, those changes aren't getting saved.
Here are the models:
# app/models/school.rb
class School < ActiveRecord::Base
has_many :grades_schools, inverse_of: :school
has_many :grades, through: :grades_schools
accepts_nested_attributes_for :grades_schools, allow_destroy: true
end
# app/models/grades_school.rb
class GradesSchool < ActiveRecord::Base
belongs_to :school
belongs_to :grade
end
# app/models/grade.rb
class Grade < ActiveRecord::Base
has_many :grades_schools, inverse_of: :grade
has_many :schools, through: :grades_schools
end
The form looks like this:
# app/views/schools/_form.html.haml
= form_for(#school) do |f|
/ <snip> other fields
= collection_select(:school, :grade_ids, #all_grades, :id, :name, {:selected => #school.grade_ids, include_hidden: false}, {:multiple => true})
/ <snip> other fields + submit button
And the controller looks like this:
# app/controllers/schools_controller.rb
class SchoolsController < ApplicationController
before_action :set_school, only: [:show, :edit, :update]
def index
#schools = School.all
end
def show
end
def new
#school = School.new
#all_grades = Grade.all
#grades_schools = #school.grades_schools.build
end
def edit
#all_grades = Grade.all
#grades_schools = #school.grades_schools.build
end
def create
#school = School.new(school_params)
respond_to do |format|
if #school.save
format.html { redirect_to #school, notice: 'School was successfully created.' }
format.json { render :show, status: :created, location: #school }
else
format.html { render :new }
format.json { render json: #school.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #school.update(school_params)
format.html { redirect_to #school, notice: 'School was successfully updated.' }
format.json { render :show, status: :ok, location: #school }
else
format.html { render :edit }
format.json { render json: #school.errors, status: :unprocessable_entity }
end
end
end
private
def set_school
#school = School.find(params[:id])
end
def school_params
params.require(:school).permit(:name, :date, :school_id, grades_attributes: [:id])
end
end
I have a feeling that the crux of my problem has to do with a mismatch between the params generated by collection_select and the strong parameters. One or both of these is probably incorrect, but I can't for the life of me find example code online that shows me what I'm doing wrong.
After trying a load of failed variations, I'm at my wits end! Thanks in advance for your help!
Crap. I could have sworn I tried this before, but it must have been when using fields_for in the form instead of collection_select. The solution:
def school_params
params.require(:school).permit(:name, :date, :school_id, grades_attributes: [:id])
end
becomes
def school_params
params.require(:school).permit(:name, :date, :school_id, grade_ids: [])
end
I'm still curious how it would work when using fields_for #grades_schools, but will have to save that investigation for another day....

Polymorphic Associations not saving values

My models:
class LineItem < ActiveRecord::Base
attr_accessible :itemable
belongs_to :itemable, polymorphic: true
belongs_to :lead
belongs_to :cart
end
class House < ActiveRecord::Base
has_many :line_items, :as => :itemable
end
class Appartment < ActiveRecord::Base
has_many :line_items, :as => :itemable
end
line_item_controller:
def create
#line_item = #cart.line_items.build item: #object
respond_to do |format|
if #line_item.save
format.html { redirect_to #line_item.cart,
notice: 'Vakantiehuis toegevoegd in lijst.' }
format.json { render action: 'show',
status: :created, location: #line_item }
else
format.html { render action: 'new' }
format.json { render json: #line_item.errors,
status: :unprocessable_entity }
end
end
end
private
def create_object
id = params[:house_id] || params[:appartment_id]
model = "House" if params[:house_id]
model = "Apartment" if params[:apartment_id]
model = model.constantize
#object = model.find(id)
end
When a new item list is created the values in de table line_items (itemable_id, itemable_type) are not saved. What am i doing wrong here? thanks..remco
try replace:
#cart.line_items.build item: #object
to:
#cart.line_items.build itemable: #object

Resources