Rails How to pass params from controller to after_save inside model - html

I have a Rfq contoller i am creating new or updating existing Rfqs, when i create or update the object is saved, what i want is as i have number of quotes params i want to update the line_items table with the quotes in params[:quotes] in quote_price column after saving the Rfqs
i know its confusing, but who are ror-ish should have got some hint wat i want to ask.

If you're trying to use the params hash in your model, you are violating principles of MVC. The model should stand alone with arguments. If you are trying to do the following:
# controller
Model.foo
# model
def foo
params[:bar].reverse!
end
You should do the following instead:
# controller
Model.foo(params[:bar])
# model
def foo(foobar)
foobar.reverse!
end

Honestly if it deals with params, it's probably a good idea to put that type of logic in the controller, lest you muddle the responsibilities of the model and controller.
That is, in the controller:
if #foo.save
# Update line_items using params[:quotes]
end

I think you want to be able to have 1 form that saves both the main object and all of the child objects. If not, disregard.
In rails, this is named "nested_attributes"
you'll add this to your model:
accepts_nested_attributes_for :quotes
# assuming you have
has_many :quotes
and then in your form view:
<% form.fields_for :quotes do |child_form| %>
<%= child_form.text_field :name %>
<% end %>
Check this out at Ryan's Blog: Nested Attributes

Related

param is missing or the value is empty error with patch link_to

Is my approach of using a link_to wrong in updating the value of an attribute or is there simply something wrong with my syntax? Any ideas on how I can fix this?
I have an error when I try to update a single attribute using link_to. I have the following code in my views:
<%=link_to "Pay", event_attendee_path(event_attendee, :paid => true), :method => :patch%>
I am using the link_to inside a loop :<% #event_attendees.each do |event_attendee| %><%end%>
I get the error: "param is missing or the value is empty: event_attendee" when I try to run my code.
I have the following in my controller:
def event_attendee_params
params.require(:event_attendee).permit(:attendee_id, :event_id, :paid)
end
Rake routes:
event_attendee GET /event_attendees/:id(.:format) event_attendees#show
PATCH /event_attendees/:id(.:format) event_attendees#update
PUT /event_attendees/:id(.:format) event_attendees#update
DELETE /event_attendees/:id(.:format) event_attendees#destroy
The issue is that when you pass a model to a route as you've done the only thing that is sent to the server is the id of the model. In the server it's params[:id].
In your controller you're requiring that params have a key called :event_atendee but actually the only thing you're sending is the id.
On a patch route you usually need the id to get the object you're going to update, so so far all is. However you probably want to update other values too? So I'd look at documentation on how to send form data in a link_to with a patch method.
One way is to include the keys in the route but there might be a better way.
it should be
params.require(:id).permit(:attendee_id, :event_id, :paid)
You require :event_attendee but routes parse it and sets it as :id
You can use
#event_attendee.update(paid: params[:paid])
in your controller, or use
form_for(#event_attendee)
on view, if you want use permit_params

Passing parameters from form to controller using RoR

I am new to RoR development and am a little confused about how parameters are passed from a HTML view to the controller. I have seen a few examples online which use a private method like this:
private
def message_params
params.require(:message).permit(:content)
end
I have been looking for some clarification online as to what this method does and how it works, but I only encounter posts/articles which use the method rather than explain what it does.
I was hoping someone could explain how the method takes(/filters?) values passed via the form via a POST request, what the require and permit keywords mean and how would i change this method to fit my own use.
For example if i needed to get data about a new book would i do this:
private
def book_params
params.require(:book_name).require(:ISBN).require(:Author).permit(:Illustrator)
end
Would the above be valid given that my book object has those fields?
Any clarification would be appreciated.
Thank you.
here is some info (I'm using your sample model Book and BookController), that probably can help you more understand
when you submit form, rails automatically called create method, inside create method you will see Book.new(book_params), book_params will call private method and will check which field allowed, if there is another field that submitted but not listed inside your permit block then it will be not passed along to save command
class BooksController < ApplicationController
def create
#book = Book.new(book_params)
if #book.save
flash[:success] = 'Data save successfully'
redirect_to books_path
else
render :new
end
end
private
def book_params
params.require(:book).permit(
:book_name,
:isbn,
:author,
:illustrator)
end
end
This kind of function is used to whitelist params - ie say you have a message model, and through the controller actions you should only be able to change the content. Maybe there is also an author field - but even if someone were to pass that through the form, you would not want to update it.
params.require(:message)
Will return to you params[:message]. permit means you are allowing only the content field through.
See: http://edgeguides.rubyonrails.org/action_controller_overview.html#strong-parameters
I would need to see your model setup, but I would assume given a book model you'd want something more akin to:
params.require(:book).permit(:illustrator, :author, :isbn)

Add column in database from controller

I want to add a column in a mysql table from a controller. The user completes a form, and when he sends it, it creates a new column (not row) with the information in the form. How can I do this?
it create new column
Don't.
Your database is sacrosanct, dynamically altering it is like dynamically changing a car based on some user's request. A car has four wheels, engine and seats. You can change the colour, tyres, etc... but not the fundamentals.
It's the same with web apps - you should not be changing the fundamental structure of your system. Sure, you'll be able to change various aspects of it (User Avatar etc), but the underlying basis of the system (the db schema) should be kept above any changes.
What you should be doing is maintaining your database fidelity through a tight set of Models, allowing you to create a dynamic experience around the data you've been provided.
For example...
The user complete a form and when he send it, it create new column
A better way to explain this will be to use a user story.
I'll surmise the following in your case:
A user wants to add a new project to his portfolio. He fills out the form to explain what the project will be and adds a number of extra fields specific for that project.
I think you're asking about the "extra fields" part...
You have to remember Rails is built on top of a relational database:
This means that you have the flexibility provided by your models to grant your users the capacity to add and manipulate as many pieces of associated data as they need.
The data they add to the system can have any name & any structure, so long as you provide that functionality within the system itself...
#app/models/user.rb
class User < ActiveRecord::Base
has_many :projects
has_many :specialized_fields, through: :projects
end
#app/models/project.rb
class Project < ActiveRecord::Base
belongs_to :user
belongs_to :specialized_field
accepts_nested_attributes_for :specialized_field
end
#app/models/specialized_field.rb
class SpecializedField < ActiveRecord::Base
has_many :projects
has_many :users, through: :projects
end
According to my example above,
User can make a Project
Project can have specialized fields (above the standard fields)
User can add specialized fields to the model
Thus you can do the following:
#app/controllers/projects_controller.rb
class ProjectsController < ApplicationController
def new
#project = current_user.projects.new #-> assuming you're using Devise
#specialized_field = #project.build_specialized_field
end
def create
#project = Project.save project_params
#project.save
end
private
def project_params
params.require(:project).permit(:name, :start_time, :end_time, specialized_field_attributes: [:name, :value])
end
end
The form could be as follows:
#app/views/projects/new.html.erb
<%= form_for #project do |f| %>
<%= f.text_field :name %>
<%= f.fields_for :specialized_field do |s| %>
<%= s.text_field :name %>
<%= s.text_field :value %>
<% end %>
<%= f.submit %>
<% end %>
Why would you like to add new columns to the database via the controller? This shouldn't be the case - and in general I couldnt' think of a single reason why this should ever be required. It sounds unconventional and against design principles.
If you add more information of what is required and what you are tyring to do I am pretty sure we can work out an alternative solution. (I bet what you are trying to do can be achieved with a many-to-many relationship, or similar, somehow). Post more information and see what we can do.
But as answer and solution I'd say it shouldn't be required.
Why do you want to do this? Database design is part of the application development, so you are the one deciding the rows. When the user inputs data, there are a gazillion things that can go wrong (hacks, invalid values...), which can affect your entire database. It's not worth risking that.
If you want a flexible schema, you can store hashes in a specific field.
For example you have a extra_data field which is a hash. Then in your form you can have to inputs, input_name and input_value which will go to the hash. This way you will have more flexible values for the same column and you don't need to change your database schema.

How to perform user input in rails

I've been struggling for a while on this (been reading a lot of the ruby on rail guides to try and understand this), but I'm not sure how user inputs work.
I am trying to search for a restaurant in my database with a list of fields the user specifies (cuisine, zipcode, review score). I have created a html.erb page that has the options for all of these.
Here is my controller.
class WelcomeController < ApplicationController
def home
#my_search = Restaurant.joins(:inspection).where(cuisine: c, zipcode: z, totalscore: 1..h)
end
My models for restaurant and inspection also have relations between them (the foreign keys).
How would you go about letting the user give inputs for c (cuisine), z (zipcode) and 1..h (score range)?
I know that people have answered this question in the past, but I think I need a concrete example to actually understand how to do this. As in, what would you put in the html.erb code so that when an option is selected, that value is passed to the method?
Thank you
First you need to create a form in the view. The simplest way to do this is with form_tag:
<%= form_tag(home_path) do %>
<%= text_field_tag 'cuisine' %>
...other inputs
<% end %>
Next, make sure you have a route defined for your controller action in config/routes.rb
post 'home' => 'welcome#home'
Most likely your routes will look different but this is the bare minimum you need.
And in your controller you can access the submitted data using the params object
class WelcomeController < ApplicationController
def home
#restaurants = Restaurant.joins(:inspection).where(
cuisine: params[:cuisine],
# ...other params
)
end
end

what could cause a rails scope to throw a NoMethodError

What could cause a rails app to have a no method error when using a scope?
I have a basic user class that has cats and dogs. I will need to combine the queries and sort them by created date. Eventually the individual queries will be more complex.
class User < ActiveRecord::Base
has_many :dogs
has_many :cats
scope :pets, joins(:dogs).joins(:cats).order("created_at desc")
In view
<%= render #user.pets%>
Is causing an no method error
undefined method `pets' for #<User:0x00000106370cb0>
Scopes only define class methods on the ActiveRecord model. The proper way to call this would be on the User model directly. User.pets as opposed to an instance of User #user.pets.
What you could do is create a method to be called on a User instance.
def pets
User.joins(:dogs).joins(:cats).order("created_at desc")
end
And thus, #user.pets is allowed.