Rails , How to santize within the Model - ruby-on-rails

I have the following model
Diary.rb
class Diary < ApplicationRecord
belongs_to :student
belongs_to :user
belongs_to :grade
has_many :diary_entries
validates :diary_year, presence: true
def self.from_student(owner, student_obj)
new(
user_id: owner.id,
student_id: student_obj.id,
grade_id: student_obj.grade_id,
#How to add diary_year here.....
)
end
end
My diary only had three attributes, user_id, grade_id, student_id... I added an extra attribute diary_year, the diary_year is a integer and I am not sure what is the right syntax to add it to the self.from_student..
My guess, but that fails.
diary_year: subject_obj.diary_year
Here is my controller
def create
#diary = Diary.from_student(current_user, #student)
#diary.save
redirect_to #student, notice: "Diary was successfully created."
end

You can populate the field with Date.today.year in the method:
class Diary < ApplicationRecord
belongs_to :student
belongs_to :user
belongs_to :grade
has_many :diary_entries
validates :diary_year, presence: true
def self.from_student(owner, student_obj)
new(
user_id: owner.id,
student_id: student_obj.id,
grade_id: student_obj.grade_id,
diary_year: Date.today.year #this populates the field automatically
)
end
end

Related

how disable adding existing record in has_many through

I add unique index, but record dont save, validation error. I need update tags in my post,existing tags adding to tags with new id, but I need existing tags not to be added
class Tag < ApplicationRecord
has_many :tags_posts
has_many :tags, through: :tags_posts
accepts_nested_attributes_for :tags_posts, :allow_destroy => true, :update_only=>true
end
class TagsPost < ApplicationRecord
belongs_to :post
belongs_to :tag
accepts_nested_attributes_for :tag, :allow_destroy => true, :update_only=>true
end
controller code:
def update
#resource=resource_class.find(params[:id])
#resource.assign_attributes(resource_params)
if #resource.save
render json: #resource.as_json(as_json_resource)
else
render json: {errors:#resource.errors}, status: :unprocessable_entity
end
end
def resource_class
Post
end
def resource_params
params.require(:post).permit(:user_id,:title,:category_id, :content, :date_of_publication, tags_posts_attributes: [tag_attributes: [:name]] )
end
Add id to tag_attributes
params.require(:post).permit(:user_id,..., tags_posts_attributes: [tag_attributes: [:id, :name]] )
That will prevent it from adding again.

Rails 5: Nested attributes aren't updated for model

I can't get rails to update my nested attributes, though regular attributes work fine. This is my structure:
unit.rb:
class Unit < ApplicationRecord
has_many :unit_skill_lists
has_many :skill_lists, through: :unit_skill_lists, inverse_of: :units, autosave: true
accepts_nested_attributes_for :skill_lists, reject_if: :all_blank, allow_destroy: true
end
unit_skill_list.rb:
class UnitSkillList < ApplicationRecord
belongs_to :unit
belongs_to :skill_list
end
skill_list.rb:
class SkillList < ApplicationRecord
has_many :unit_skill_lists
has_many :units, through: :unit_skill_lists, inverse_of: :skill_lists
end
And this is (part of) the controller:
class UnitsController < ApplicationController
def update
#unit = Unit.find(params[:id])
if #unit.update(unit_params)
redirect_to edit_unit_path(#unit), notice: "Unit updated"
else
redirect_to edit_unit_path(#unit), alert: "Unit update failed"
end
end
private
def unit_params
unit_params = params.require(:unit).permit(
...
skill_list_attributes: [:id, :name, :_destroy]
)
unit_params
end
end
The relevant rows in the form (using formtastic and cocoon):
<%= label_tag :skill_lists %>
<%= f.input :skill_lists, :as => :check_boxes, collection: SkillList.where(skill_list_type: :base), class: "inline" %>
Any idea where I'm going wrong? I have tried following all guides I could find but updating does nothing for the nested attributes.
Edit after help from Vasilisa:
This is the error when I try to update a Unit:
ActiveRecord::RecordInvalid (Validation failed: Database must exist):
This is the full unit_skill_list.rb:
class UnitSkillList < ApplicationRecord
belongs_to :unit
belongs_to :skill_list
belongs_to :database
end
There is no input field for "database". It is supposed to be set from a session variable when the unit is updated.
If you look at the server log you'll see something like skill_list_ids: [] in params hash. You don't need accepts_nested_attributes_for :skill_lists, since you don't create new SkillList on Unit create/update. Change permitted params to:
def unit_params
params.require(:unit).permit(
...
skill_list_ids: []
)
end
UPDATE
I think the best options here is to set optional parameter - belongs_to :database, optional: true. And update it in the controller manually.
def update
#unit = Unit.find(params[:id])
if #unit.update(unit_params)
#unit.skill_lists.update_all(database: session[:database])
redirect_to edit_unit_path(#unit), notice: "Unit updated"
else
redirect_to edit_unit_path(#unit), alert: "Unit update failed"
end
end

Two different classes using accepts_nested_attributes of one class

I have a class Addresse where Organismereferent and Organisme have a has_many belongs_to relationship with. Also Organismereferent and Organisme can accepts_nested_attributes_for :addresses
My problem is when I only had the Organismereferent class everything was working fine and I was able to create a new Organismereferent with an addresse but as soon as I created and added the same relation to Organisme , they both stopped working without giving any error message I only get this in the console:
My model:
class Organismereferent < ApplicationRecord
has_many :addresses
has_many :referents
accepts_nested_attributes_for :addresses
end
class Organisme < ApplicationRecord
has_many :addresses
accepts_nested_attributes_for :addresses
end
class Address < ApplicationRecord
belongs_to :organismereferent
belongs_to :organisme
end
Controller for Organisme
def new
#organisme = Organisme.new
#organisme.addresses.build
end
def create
#organisme = Organisme.new(organisme_params)
#organisme.status = true
#organisme.save
redirect_to #organisme
end
private
def organisme_params
params.require(:organisme).permit(:nom, :telephone, :courriel, :fax, addresses_attributes: [:id, :no_civique, :rue, :ville, :province, :etat, :code_postal])
end
Controller for Organismereferent:
def new
#organisme = Organismereferent.new
#organisme.addresses.build
end
def create
#organisme = Organismereferent.new(organisme_params)
#organisme.active = true
#organisme.save
redirect_to #organisme
end
private
def organisme_params
params.require(:organismereferent).permit(:nom_organisation, :bureau, :telecopie, :courriel, :site_web, addresses_attributes: [:id, :no_civique, :rue, :ville, :province, :etat, :code_postal])
end
I'm not sure what else information might be important so I'll be glad to add anything.
Try to change address model like
class Address < ApplicationRecord
belongs_to :organismereferent, optional: true
belongs_to :organisme, optional: true
end

Rails Model doesn't save data with polymorphic

I have a model job and a model user, the both can choose contracts types (that's why i use polymorphic).
I created a model contract for each contracts and i create an attached_contract model too.
Job model
class Job < ApplicationRecord
has_many :contracts, through: :attached_contracts
has_many :attached_contracts, as: :contractable, dependent: :destroy
accepts_nested_attributes_for :attached_contracts, reject_if: :all_blank, allow_destroy: true
end
AttachedContract model
class AttachedContract < ApplicationRecord
belongs_to :contract
belongs_to :contractable, polymorphic: true
validates :contract, uniqueness: { scope: [:contractable_type,:contractable_id] }
end
Contract model
class Contract < ApplicationRecord
validates :name, presence: true, allow_blank: false
has_many :attached_contracts
end
Jobs_controller
def new
#job = Job.new
#job.attached_contracts.build
end
def create
#job = current_company.jobs.build(set_params)
if #job.save
redirect_to job_path(#job)
end
else
render :new
end
end
def set_params
params.require(:job).permit(:title, :description, :address, attached_contracts_attributes: [:id, :contract_id, :_destroy]
end
In my view :
<%= simple_form_for([:company, #job]) do |f| %>
<div class="nested-fields">
<%= f.association :contracts, as: :check_boxes %>
</div>
<% end %>
When I submit my form my model AttachedContract still empty, and the data are lost.
I try tu put a "raise" in my controller after #job = current_company.jobs.build(set_params)
and I have a empty array if I call #job.attached_contracts
I don't understand beause in the "Request parameters" (rails debug console) I have the values : "contract_ids"=>["", "1", "3"]
Any idea ? May be the problem is in the polymorphic implantation ?
Finally, I changed the requested parameters by "contract_ids: [ ]" and that's work perfectly !

How to create nested models from API request?

I've a Rails API and I've two models:
class Event < ActiveRecord::Base
belongs_to :category
has_many :event_categories
has_many :events, through: :event_categories
attr_accessible :title, :description, :event_categories_attributes
accepts_nested_attributes_for :event_categories
end
and
class EventCategory < ActiveRecord::Base
belongs_to :event
belongs_to :category
attr_accessible :category_id, :event_id, :principal
validates :event, :presence => true
validates :category, :presence => true
validates_uniqueness_of :event_id, :scope => :category_id
end
In a first moment, EventCategory didn't exist so I created Event resources sending params like event[title]='event1', event[description] = 'blablbla' thought POST REST request.
My API EventsController was like this (I haven't a new method because I don't need views):
def create
#event = Event.create(params[:event])
if #event
respond_with #event
else
respond_with nil, location: nil, status: 404
end
end
This way worked correctly for me. Now, with the new EventCategory model I don't know how I could create EventCategories models at the same time.
I've trying this... but it doesn't work:
def create
#event = Event.new(params[:event])
#event.event_categories.build
if #event.save
respond_with #event
else
respond_with nil, location: nil, status: 404
end
end
Rails told me:
{
"event_categories.event": [
"can't be blank"
],
"event_categories.category": [
"can't be blank"
]
}
I send the category_id like this:
event[event_categories_attributes][0][category_id] = 2
Any ideas?
In your create action, instead of this:
#event.event_categories.build
Try this:
#event.event_categories = EventCategory.new do |ec|
ec.event = #event
ec.category = the_cattegory_you_want_to_specify
# You need both of these as you are validating the presence of event AND category
end

Resources