get and post method in controller. Ruby on Rails - ruby-on-rails

I trying rewrite some data in model. Change_settings is GET-method, update_settings is POST. After click SUBMIT happens nothing. Data not change. Help me, please( what's wrong?
controller
def change_settings
#vacation_days = current_company.vacation_days
#illnes_days = current_company.illnes_days
end
def update_settings
current_company.update_attribute(:vacation_days, :illnes_days)
current_company.save
redirect_to account_company_path, notice: t('company.settings_changed')
end
change_settings view
.company_settings
= form_tag update_settings_company_path do
= field_set_tag do
= label_tag 'vacation_days'
= text_field_tag :vacation_days
= label_tag 'illnes_days'
= text_field_tag :illnes_days
%br
= submit_tag t('common.save'), class: 'btn'
= link_to t('common.back'), account_company_path, class: 'btn'
routes
resource :company, only: :all do
get :account
get :change_settings
post :update_settings
end

replace:
current_company.update_attribute(:vacation_days, :illnes_days)
current_company.save
with:
current_company.update_attributes(vacation_days: params[:vacation_days], illnes_days: params[:illnes_days] )
Basically you were not taken data sent from client into account

Related

Undefined method _path when controllers combined

I have a PokemonBattles controller in which I have methods create, new and update. Everything works fine with new but not with update. The error I get when I try to access the edit view.
undefined method `pokemon_battle_path' for
#<#<Class:0x007f692e7251c0>:0x007f692e7202d8>
Did you mean? pokemon_battles_path
controller/pokemon_battles_controller.rb
def create
pokemon_a = Pokemon.find(params[:pokemon_battle][:pokemon_a_id])
#pokemon_battle = PokemonBattle.create(pokemon_a_id: pokemon_a.id,
match_status: :upcoming,
pokemon_a_hp: pokemon_a.base_experience,
user_a_id: current_user.id)
redirect_to arena_index_path
end
def new
user = User.find(current_user.id)
#pokemons = user.pokemons
#pokemon_battle = PokemonBattle.new
end
def edit
#pokemon_battle = PokemonBattle.find(params[:id])
end
config/routes.rb
resources :pokemon_battles, only: [:new, :create, :edit]
views/pokemon_battles/edit.html.slim
section
= form_for #pokemon_battle do |f|
- #pokemons.each do |pokemon|
= f.radio_button :pokemon_b_id, pokemon.id
= f.label "pokemon_b_id_#{pokemon.id}", pokemon.name
= f.submit 'Choose', class: 'btn btn-primary'

NoMethodError undefined method `id' for nil:NilClass:

I know this kind of question is already answered multiple times but i seriously unable to figure it out what is causing a problem here, I am having trouble solving this problem. I keep getting the same error when i'm trying to create new registration ( http://localhost:3000/registrations/new?course_id=1 ) :
NoMethodError at /registrations
undefined method `id' for nil:NilClass
Here is my RegistrationsController:
class RegistrationsController < ApplicationController
before_action :set_registration, only: [:show, :edit, :update, :destroy]
def index
#registrations = Registration.all
end
def show
end
def new
#registration = Registration.new
#course = Course.new
#course = Course.find_by id: params["course_id"]
end
def create
#registration = Registration.new registration_params.merge(email: stripe_params["stripeEmail"], card_token: stripe_params["stripeToken"])
raise "Please Check Registration Errors" unless #registration.valid?
#registration.process_payment
#registration.save
redirect_to #registration, notice: 'Registration was successfully created.'
rescue Exception => e
flash[:error] = e.message
render :new
end
protect_from_forgery except: :webhook
def webhook
event = Stripe::Event.retrieve(params["id"])
case event.type
when "invoice.payment_succeeded" #renew subscription
Registration.find_by_customer_id(event.data.object.customer).renew
end
render status: :ok, json: "success"
end
private
def stripe_params
params.permit :stripeEmail, :stripeToken
end
def set_registration
#registration = Registration.find(params[:id])
end
def registration_params
params.require(:registration).permit(:course_id, :full_name, :company, :telephone, :email, :card_token)
end
end
My Registration Model:
class Registration < ActiveRecord::Base
belongs_to :course
def process_payment
customer_data = {email: email, card: card_token}.merge((course.plan.blank?)? {}: {plan: course.plan})
customer = Stripe::Customer.create customer_data
Stripe::Charge.create customer: customer.id,
amount: course.price * 100,
description: course.name,
currency: 'usd'
#Annotate Customer Id when Registration is Created
cusotmer_id = customer.id
end
def renew
update_attibute :end_date, Date.today + 1.month
end
end
Registration New.html.haml File :
%section#course-content
%section#ruby
%section.detailed-syllabus
.wrapper-inside
= form_for #registration, html: { class: "basic-grey" } do |f|
- if #registration.errors.any?
#error_explanation
%h2
= pluralize(#registration.errors.count, "error")
prohibited this registration from being saved:
%ul
- #registration.errors.full_messages.each do |message|
%li= message
.field
= f.hidden_field :course_id, value: #course.id
.field
= f.label :full_name
= f.text_field :full_name
.field
= f.label :company
= f.text_field :company
.field
= f.label :email
= f.text_field :email
.field
= f.label :telephone
= f.text_field :telephone
//‘Stripe.js’ will recognize the card data because we have marked the inputs with ‘data-stripe’ attribute as: number, cvv, exp-month and exp-year.
= javascript_include_tag "https://js.stripe.com/v2/"
:javascript
Stripe.setPublishableKey('#{Rails.application.secrets.stripe_publishable_key}');
= label_tag "Card Number", nil, required: true
.control-group
.controls
= text_field_tag :card_number, nil, class: "input-block-level", "data-stripe" => "number"
= label_tag "Card Verification", nil, required: true
.control-group
.controls
= text_field_tag :card_verification, nil, class: "input-block-level", "data-stripe" => "cvv"
= label_tag "Card Expires", nil, required: true
= select_tag :exp_month, options_for_select(Date::MONTHNAMES.compact.each_with_index.map { |name,i| ["#{i+1} - #{name}", i+1] }), include_blank: false, "data-stripe" => "exp-month", class: "span2"
= select_tag :exp_year, options_for_select((Date.today.year..(Date.today.year+10)).to_a), include_blank: false, "data-stripe" => "exp-year", class: "span1"
.actions
= f.submit "Registration Payment", class: "btn", style: "color: white;background: rgb(242, 118, 73);"
Does anyone know how to assist me in this? Greatly appreciate all the help.
Additional Can anyone please guide me through how to pass id between 2 models like this guy did between 2 models as he's creating a scaffold for one model but passing ID lets him create values for another model too without creating actions for another controller https://github.com/gotealeaf/stripe-basics.git
Edited:
GitHub Repository For This Code
https://github.com/ChiragArya/Stripe_CheckOut_Demo
From your comments, it appears the error is caused by :
#course.id being nil
The way to fix this is to ensure #course is defined properly. You need to do the following:
def new
#registration = Registration.new
#course = Course.find_by id: params["course_id"]
end
The other issue you have here is that your routes should be able to handle courses without having to append them with ?course_id=1:
#config/routes.rb
resources :registrations do
get :course_id, to: "registrations#new" #-> yoururl.com/registrations/:course_id
end
This will still give you the course_id param in the new action; just makes it more Rails.
--
Controller
You also need some structure in your code (you're aiming for fat model, thin controller). It looks like you're coming to Rails as a Ruby dev; you need to appreciate that Rails handles most of the exceptions etc for you.
Specifically, you need to look at how to remove code out of your actions:
def create
#registration = Registration.new registration_params
#registration.process_payment
if #registration.save
redirect_to #registration, notice: 'Registration was successfully created.'
else
# handle error here
end
end
private
def registration_params
params.require(:registration).permit(:course_id, :full_name, :company, :telephone, :email, :card_token).merge(email: stripe_params["stripeEmail"], card_token: stripe_params["stripeToken"])
end
-
`id' for nil:NilClass
Finally, you have to remember this error basically means the variable you're trying to invoke an action for is nil.
Ruby populates nil variables with a NilClass object, thus it's difficult to determine what the error actually is. All it means is that the variable you're trying to call a method on doesn't have the aforementioned method, as Ruby has populated it with the NilClass object.
Try changing Registration#new action to
def new
#course = Course.find(params[:course_id])
#registration = #course.registrations.new
end
add this in your def create
def create
#course = Course.find_by id: params["registration"]["course_id"]
#registration = Registration.new registration_params.merge(email: stripe_params["stripeEmail"], card_token: stripe_params["stripeToken"])
raise "Please Check Registration Errors" unless #registration.valid?
#registration.process_payment
#registration.save
redirect_to #registration, notice: 'Registration was successfully created.'
rescue Exception => e
flash[:error] = e.message
#course = Course.find_by id: params["registration"]["course_id"]
render :new
end

Values of a book saved from amazon have {:value=>""} around it

I'm making an application where the user can search Amazon (with Vacuum) through my application for books, then be able to record the data of the book to their library.
When you search for a book, it goes through every result and puts each in a thumbnail. In every thumbnail there is a button that opens a modal with a form with hidden tags. When the user clicks the submit button, the book's title is saved into a new book. The only problem is that the title is saved like {:value=>"the title of the book that was saved"}
Here is the part of new.html.erb which has the search box:
<%= form_tag({controller: "books", action: "new"}, method: "get", id: "search-form") do %>
<%= text_field_tag :keywords, params[:keywords], placeholder: "Search for a book", class: "form-control" %>
<% end %>
Here is the part of new.html.erb which has the hidden form:
<% #results.each do |result| %>
…
<%= form_for #book do |f|%>
<%= hidden_field_tag :title, class: 'form-control', value: result.name %>
<%= f.submit "Add book", class: "btn btn-default green-hover" %>
<% end %>
…
<% end %>
Here are the new and create actions in my controller:
def new
#book = current_user.books.build if logged_in?
# Search actions
if params[:keywords]
request = Vacuum.new
request.configure(
aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
associate_tag: 'my associate tag is here'
)
keywords = params[:keywords]
params = {
'SearchIndex' => 'Books',
'Keywords'=> keywords,
'ResponseGroup' => "ItemAttributes,Images"
}
raw_results = request.item_search(query: params)
hashed_results = raw_results.to_h
#results = []
hashed_results['ItemSearchResponse']['Items']['Item'].each do |item|
result = OpenStruct.new
result.title = item['ItemAttributes']['Title']
result.url = item['DetailPageURL']
result.image_url = item['MediumImage']['URL']
result.author = item['ItemAttributes']['Author']
result.pages = item['ItemAttributes']['NumberOfPages']
#results << result
end
end
end
def create
#book = #list.books.build(book_params)
if #book.save
flash[:success] = #book.title + "was added to your log."
redirect_to list_path(#book.list_id)
else
render 'books/new'
end
end
I tried to use gsub within book.rb to fix it, but that only changed the text within the flash message and it still saved as {:value=>"the title of the book that was saved"}.
after_create :init
private
def init
puts "Init was called!"
self.title.gsub!('{:value=>"', " ")
self.title.gsub!('"}', " ")
end
How can I change it so that it doesn't save the title with the {:value=>} around it?
I don't think the hidden field tag is right.
<%= hidden_field_tag :title, class: 'form-control', value: result.name %>
Try
<%= hidden_field_tag :title, result.name %>
Your title is being saved as a hash not a string. Use hash accessing methods:
t = title[:value]
puts t #=> "the tile of the book that was saved"

Rails 4 Cannot access hash in nested form (undefined method `[]' for nil:NilClass)

I've build quite complex form which creates one prescription with many realtions. I am using this syntax in view:
- provide(:title, 'Create prescription')
%h1 Add medicines to prescription
.row
.span6.offset3
= form_for #prescription do |f|
= render 'shared/error_prescription_messages'
%p
= f.hidden_field :patient_id, :value => params[:patient_id]
= f.hidden_field :user_id, :value => current_user.id
= f.fields_for :relations do |builder|
= render 'child_form', :f => builder
%p= f.submit "Submit"
chlid_form is quite simple :
- it=f.options[:child_index].to_i
- n= it.to_s
%h2
= "Medicine ##{it+1}"
= f.hidden_field :medicine_id, :id => "my_medicine_id#{it}"
- if params[:prescription].nil? || params[:prescription][:relations_attributes][n.to_sym][:medicine_name].nil?
= f.autocomplete_field :medicine_name, autocomplete_medicine_name_relations_path, :id_element => "#my_medicine_id#{it}"
- else
= f.autocomplete_field :medicine_name, autocomplete_medicine_name_relations_path, :id_element => "#my_medicine_id#{it}", :value => params[:prescription][:relations_attributes][n.to_sym][:medicine_name]
= f.label :amount, "Amount of medicine boxes"
= f.number_field :amount, :value => 1
= f.label :daily
= f.number_field :daily, :value => 1
= f.label :period_in_days, "Duration of treatment (in days)"
= f.number_field :period_in_days, :value => 1
So as you can see I'm using f.options[:child_index] to get index of child (0,1,2...) cause I generate multiple items with this particular form. I then put it to variable it and sucessfully use it in :id_element => "#my_medicine_id#{it}" which works PERFECTLY fine (creates my_medicine_id0, my_medicine_id1 ....) Although it doesn't work in this line:
:value => params[:prescription][:relations_attributes][n.to_sym][:medicine_name]
where n is just n=it.to_s.
I though somethings wrong in controller but if I change this line to whatever
:value => params[:prescription][:relations_attributes]**[:'0']**[:medicine_name] or any other integer from 0 to 4 everything works great, but I NEED dynamic change in this one. So I got proof that it DOES work because it generates integer fine here "#my_medicine_id#{it}" but won't work in hash! And when I print the whole hash from params I get this:
{"patient_id"=>"7", "user_id"=>"1", "relations_attributes"=>{"0"=>{"medicine_id"=>"13490", "medicine_name"=>"Locacid 500 mcg/g (0,05%) (1 tuba 30 g)", "amount"=>"0", "daily"=>"1", "period_in_days"=>"1"}, "1"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}, "2"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}, "3"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}, "4"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}}}
so to get the values I need it's pretty obvious that
params[:prescription][:relations_attributes][SOME_KIND_OF_INETEGER][:medicine_name] should work, but doesn't.
Controller code:
class PrescriptionsController < ApplicationController
before_action :signed_in_user
before_action :doctor_user, only: [:new, :create]
before_action :pharmacist_user, only: [:update]
def new
#prescription =Prescription.new
5.times { #prescription.relations.build }
end
def create
#prescription = Prescription.new(new_prescription_params)
if #prescription.save
flash[:success] = "Prescription created."
redirect_to #prescription
else
5.times { #prescription.relations.build }
render 'new', :prescription => params[:prescription]
end
end
def show
#prescription = Prescription.find(params[:id])
#medicines = #prescription.medicines.paginate(page: params[:page], :per_page => 10)
end
def update
#prescription = Prescription.find(params[:id])
#patient = Patient.find(params[:patient_id])
if !prescription_expired?(#prescription)
#prescription.realized = 1
if #prescription.save
flash[:success] = "Prescription realized."
redirect_to #patient
else
redirect_to root_url
end
else
flash[:notice] = "Can't realize, prescription expired."
redirect_to #patient
end
end
private
def new_prescription_params
params.require(:prescription).
permit(:patient_id, :user_id, relations_attributes: [:medicine_id, :medicine_name, :amount, :daily, :period_in_days])
end
def doctor_user
redirect_to(root_url) unless current_user.function == "doctor"
end
def pharmacist_user
redirect_to(root_url) unless current_user.function == "pharmacist"
end
def prescription_expired?(presc)
presc.created_at < 1.month.ago
end
def signed_in_user
unless signed_in?
store_location
flash[:notice] = "Please log in."
redirect_to login_url
end
end
end
I run out of ideas so I ask you guys if anyone can help. Thanks.
There is no point in using params in your view since you already assigned those to your models. Also when you rendering your new action, those params doesn't exist as nothing has been send to the server yet. Just get rid of all the values from inputs.
Your partial should look like:
- it=f.options[:child_index].to_i
- n= it.to_s
%h2
= "Medicine ##{it+1}"
= f.hidden_field :medicine_id, :id => "my_medicine_id#{it}"
= f.autocomplete_field :medicine_name, autocomplete_medicine_name_relations_path
= f.label :amount, "Amount of medicine boxes"
= f.number_field :amount
= f.label :daily
= f.number_field :daily
= f.label :period_in_days, "Duration of treatment (in days)"
= f.number_field :period_in_days
If you want your fields to have default value, set default value inside your database.

Rails form params changing in controller

I have a form:
<%= form_for(:report_main, :url => {:action => 'exporttoxiccreate'}) do |f| %>
<%= collection_select(:waste, :code, Waste.find_all_by_istoxic(false), :id, :code, :include_blank => '') %>
<%= f.check_box(:q_pripadnost) %>
<%= f.text_field(:amount) %>
<% end %>
and this code in controller:
def exporttoxiccreate
#report = ReportMain.new
#reportexport = ReportExport.new
#reportparam = params[:report_main]
#report.waste_id = #reportparam.waste.code
#report.amount = #reportparam.amount
if #report.save
#reportexport.report_main_id = #report.id
else
redirect_to(:action => 'exporttoxicnew')
end
#reportexport.q_pripadnost = #reportparam.q_pripadnost
if #reportexport.save
redirect_to(:action => 'show', :id => #reportexport.id)
else
redirect_to(:action => 'exporttoxicnew')
end
end
I want to save in two tables, in two objects data from this form, and I need to separate params to manipulate with. I tried with this:
#reportexport.q_pripadnost = #reportparam.q_pripadnost
I want to set q_pripadnost field in #reportexport with some value from param.
Where I make mistake?
When you get params from a form in Rails, it comes in the form of a hash. For example:
params[:report_main][:waste]
params[:report_main][:amount]
So when you call #reportparam = params[:report_main], you are setting #reportparam to a hash, but then you are trying to use it later like an object. For example, instead of #reportparam.q_pripadnost, use #reportparam[:q_pripadnost].
You can take a closer look at your variable by temporarily changing your action to show a text version of the variable, for example:
def exporttoxiccreate
#reportparam = params[:report_main]
render :text => #reportparam.to_yaml
end

Resources