Got ForbiddenAttributesError when inserting an object with association - ruby-on-rails

I ask you a little help as I'm starting with Ruby on Rails with a problem that is still bothering me after searching docs and forums.
The problem raises when trying to insert an object of a class that has an association of type "belongs to" with another class.
In this situation, after submitting in the "new" form, Rails gives me a ForbiddenAttributesError in this line of Enterprise controller :
#enterprise = #country.enterprises.build(params[:enterprise])
I don't know how it gives me that error since I'm sending all parameters from the view , and specified all parameters as white-listed in Enterprise class:
controller/enterprises_controller.rb
def new
#country = Country.find(params[:country_id])
#enterprise = #country.enterprises.build
end
def create
#country = Country.find(params[:country_id])
#enterprise = #country.enterprises.build(params[:enterprise])
if #enterprise.save
redirect_to country_enterprise_url(#country,#enterprise)
else
render :action => 'new'
end
end
private
def enterprise_params
params.require(:enterprise).permit(:param1,:param2,:param3)
end
Thanks in advance.

You are creating a 'permission' private action for permitting params, but not using it when creating instance..
instead of :
#enterprise = #country.enterprises.build(params[:enterprise])
write :
#enterprise = #country.enterprises.build(enterprise_params)
meaning: the name of the action
EDIT: Hence - it's not going through the params.require.permit validation

Please change the line to:
#enterprise = #country.enterprises.build(enterprise_params)

Related

Issues with nested scaffold's setters

I have 3 scaffolds that resources are nested as following: mangas > chapters > scans. I'm trying to create a website that allows visitors to read mangas chapters, but I'm getting some difficulties to set up the scan_controller's setter.
I have some constraints to follow: the manga scaffold uses FriendlyId, and both chapters and scans are shown to the URL via their chapter/scan number (an integer)
So, for the manga controller, i did the following:
private
def set_manga
#manga = Manga.friendly.find(params[:id])
end
I simply followed the manuel, no problem whatsoever.
For the chapter_controller, I did this
private
def set_chapter
#manga = Manga.find_by(slug: params[:manga_id])
#chapter = #manga.chapters.find_by(chapter_number: params[:id])
end
This allows me to get all chapters that are linked to the manga I want, and only them. Plus, I get to pass the chapter_number as an id into the link.
And, lastly, I tried this for the scan_controller:
private
def set_scan
#manga = Manga.find_by(slug: params[:manga_id])
#chapter = #manga.chapters.find_by(chapter_number: params[:id])
#scan = #manga.chapters.scans.find(params[:id])
end
However, at this point, I can't get a satisfying result. With this configuration, I get undefined method 'pejis' for #<Chapter::ActiveRecord_Associations_CollectionProxy:0x0000000713d1a0>. I tried to also set as follow:
private
def set_scan
#chapter = Chapter.find_by(chapter_number: params[:id])
#scan = #chapter.scans.find_by(scan_number: params[:id])
end
But i get undefined method 'pejis' for nil:NilClass, which is weird because it doesn't return any error with predefined ids in the rails console.
As anyone an idea ?
Thank you in advance
So, after re-reading again and again my code, I simply needed to do the following:
def set_peji
#chapter = Chapter.find_by(chapter_number: params[:chapter_id])
#peji = #chapter.pejis.find_by(scan_number: params[:id])
end
So I had to remove #manga since it's not concerned anymore, then to set the scan's chapter_id as being the chapter's number.

Active Record Query - Rails

Currently I have a method called Visit and it basically adds on the the visit counter on Subscriber. This method gets triggered when a Subscriber enters their phone_number in a form. I simply want to make a active record query that will look something like this Susbcriber.find_by(params[id]).last.visit(this doesn't work BTW). Hopefully you get what I'm trying to do there, basically call the person that checked in last with their phone number. I'll show my code for clarity.
CONTROLLER METHOD:
def search
#subscriber = Subscriber.new
end
def visit
#subscriber = Subscriber.find_by(params[:phone_number])
if #subscriber
#subscriber.visit ||= 0
#subscriber.visit += 1
#subscriber.save
flash[:notice] = flash[:notice] = "Thank You #{#subscriber.first_name}. You have #{#subscriber.days_till_expired} until renewal"
redirect_to subscribers_search_path(:subscriber)
else
render "search"
end
end
There you can see the method that gets triggered when a Subscriber inputs their phone number. I simply want to call that person in the console.
CONTROLLER METHOD THAT IS NOT WORKING CURRENTLY:
def create
#subscriber = Subscriber.find(params[:subscriber_id])
#comment = #subscriber.comments.build(comments_params)
if #comment.save
flash[:notice] = "Thank you!"
redirect_to subscribers_search_path(:comments)
else
render "new"
end
end
This is the method that needs the new query to find the Subscriber that just entered their phone number.
Let me know if you need more info? Thank You!
I'm editing my answer to be more inclusive based on the comments. It seems like you've got a number of issues going on here and maybe you need to step back and rebuild this step by step. Consider test driving it and/or at least verify that you're getting what you expect using a debugging tool as you go along (byebug, pry, or even just judicious use of 'puts' and 'inspect').
The find_by method requires that you specify the attribute that you're trying to use to find the row by, as well as the value of the attribute
#subscriber = Subscriber.find_by(phone_number: params[:phone_number])
If you are using the model's primary key, just use find:
#subscriber = Subscriber.find(params[:id])
If you're calling a controller action, params should always be present. Try inspecting the params before moving on with any of the rest of the code. Make sure that you're getting what you expect. If not, evaluate your view code.

Automating setting instance variables in single purpose controllers that are used by different models

Say I have two models, Email and Message, with a boolean read attribute, and to mark them read I add a concern with mark_read and mark_unread patch members that route to ReadablesController.
I'd like to make it so that set_readable is automatic, not requiring me to manually query the params, and instead just work for all models with a read attribute. Is there a simple way to accomplish that?
class ReadablesController < ApplicationController
before_action :set_readable
...
def mark_read
#readable.read = true
#readable.save
flash[:notice] = "#{#readable.class.to_s} marked read."
redirect_to :back
end
def mark_unread
#readable.read = false
#readable.save
flash[:notice] = "#{#readable.class.to_s} marked unread."
redirect_to :back
end
private
def set_readable
throw "error" if params[:email_id].present? && params[:message_id].present?
#readable = Email.find(params[:email_id]) if params[:email_id].present?
#readable = Message.find(params[:message_id]) if params[:message_id].present?
end
end
You can check if a model has read attribute with has_attribute?(:read). From there it is trivial to call your mark_read and mark_unread methods.
#model.mark_read if #model.has_attribute?(:read)
This probably goes to your controller's set_readable method where it still will have to check a relevant param, say, params[:read] to invoke the logic.

How do you 'save' data to your database in a rails controller?

I am receiving ajax data in a rails controller.
my :updatedFunds comes in within the params, and I set the users' dollars column value equal to it's value-- but it isnt persisting!
def update_dollars
#user = User.find(params[:user_id])
new_dollars = params[:updatedFunds]
#user.dollars = new_dollars.to_i
#store to database?
end
Whats the last step here?
def update_dollars
#user = User.find(params[:user_id])
new_dollars = params[:updatedFunds]
#user.dollars = new_dollars.to_i
#user.save #store to database!
end
There are two methods that will work.
#user.update(dollars: new_dollars.to_i)
will change the attribute and record the change in the database.
You can also change it using the ruby setter method and then save to the database such as in the solution from #agripp. Both use ActiveRecord, an object-relational-mapper that Ruby on Rails just loves. The docs on it are awesome if you want to take a look.
you can use #user.save or if you use #user.save! then an exception will be raised it the save failed (eg. if validation failed)

Rails 3: where query issue

I am learning about 'where' in Rails 3 and I am wondering why my code is giving me a NoMethod Error.
def create
#get form values from 'new' page
#post = Post.new(params[:post])
#search for the inventory item with the sku code the user typed in the form
#item = Inventory.where(:sku_code => #post.sku_code)
#set post variable to a variable from the row with the sku code
#post.detail = #item.detail
#post.save
end
By searching the SKU, I want to retrieve the other variables in the same id and set them to my #post variable. Anyone able to give me a hand?
Assuming that SKU code is unique, you got to do it like this
#post = Post.new(params[:post])
#post.detail = Inventory.where(:sku_code => #post.sku_code).first.try(:detail)
first will fetch the first (and possibly only) record from the database. try will try to fetch detail if the returned Inventory was not nil.
Check this blog post to learn more about try method.

Resources