I am trying to create recurring events using ice_cube and recurring_select gems.
Here is my _form.html.erb code:
<%= simple_form_for(#event) do |f| %>
<div class="form-inputs">
<%= f.select_recurring :day, [IceCube::Rule.daily] %>
<%= f.input :start_time %>
<%= f.input :end_time %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
In my controller I have (among other things):
def new
#event = Event.new
end
def create
#event = Event.new(event_params)
respond_to do |format|
if #event.save
format.html { redirect_to #event, notice: 'Event was successfully created.' }
format.json { render :show, status: :created, location: #event }
else
format.html { render :new }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
def event_params
params.require(:event).permit(:day, :start_time, :end_time, :reserved)
end
As you can see I want to create the same event for each day in a week, but actually my :day column remains empty if I submit this form.
Can you give some feedback? I don't know what can be wrong
Your escape_params seems to be wrong, it should be event_params as you have used in the update action:
private
def event_params
params.require(:event).permit(:day, :start_time, :end_time, :reserved)
end
Update:
After looking into recurring_select gem, the data that it is sending to the server is something like this:
event[:day]: {"interval":1,"until":null,"count":null,"validations":null,"rule_type":"IceCube::DailyRule"}
So it is not a simple single value parameter that you can store in a single field.
You have two choices here, either serialize this value and store it in a single field or create separate fields for each parameter in the database.
And since your data in day field is a hash, permit function simply won't work on it. You can see more information on Rails issue tracker.
Related
I am positive this is the dumbest question but I cannot wrap my head around it.
I have two models in a simple has_one/belongs_to relationship
registration_code.rb
class RegistrationCode < ActiveRecord::Base
has_one :billing_transaction
accepts_nested_attributes_for :billing_transaction
billing_transaction.rb
class BillingTransaction < ActiveRecord::Base
belongs_to :registration_code
In my form I am collecting information for BOTH models using fields_for.
_form.html.erb (truncated example)
<%= form_for #registration_code, :html => {:class => "form", role: "form"} do |f| %>
<%= f.label :registration_code, "Registration Code", :class => "control-label" %>
<%= f.text_field :registration_code %>
<%= f.fields_for #billing_transaction do |bt| %>
<%= bt.label :transaction_amount, "Transaction Amount", :class => "control-label" %>
<%= bt.number_field :transaction_amount %>
<% end %>
<% end %>
In my controller, I have the following.
registration_code_controller.rb
def new
#registration_code = RegistrationCode.new
#billing_transaction = BillingTransaction.new
#billing_transaction.registration_code = #registration_code
end
def create
#registration_code = RegistrationCode.new(registration_code_params)
#billing_transaction = BillingTransaction.new # DOES THIS HAVE TO TAKE PARAMS?
#billing_transaction.registration_code = #registration_code # DO I NEED THIS LINE?
##### THE TROUBLE IS ON THIS NEXT LINE #####
#billing_transaction.transaction_amount = params[:billing_transaction_attributes][:transaction_amount] # THIS NEVER GETS SET! NOT SURE HOW TO ACCESS THE PARAMS
respond_to do |format|
if #registration_code.save && #billing_transaction.save
format.html { redirect_to registration_codes_path, notice: 'Registration code was successfully created.' }
else
format.html { render :new }
format.json { render json: #customer.errors, status: :unprocessable_entity }
end
end
end
private
# Never trust parameters from the scary internet, only allow the white list through.
def registration_code_params
params.require(:registration_code).permit(:registration_code, :expires_at, billing_transaction_attributes: [:transaction_amount])
end
The params are submitted and I can access the params for the primary model (registration_code) just fine. But I cannot for the life of me figure out how to get the parameters of the "sub" model (billing_transaction) and use them in the controller.
{"utf8"=>"✓",
"authenticity_token"=>"ePpqwJkeTAGMzb5WRWeI6aYCx4xpqvq4rl2m405IbwLdbp9xE0RyPgTZ6NmX8SvCFu94GKrfMfV9PrOkKa1BLg==",
"registration_code"=>{"registration_code"=>"HFmkbQEN",
"expires_at"=>"2015-07-16",
"billing_transaction"=>{"transaction_amount"=>"958.40" }},
"commit"=>"Create Registration Code"}
To access the billing_transaction.transaction_amount, for example, I have tried many variations:
params[:billing_transaction_attributes][:transaction_amount]
params[:billing_transaction][:transaction_amount]
params[#billing_transaction][:transaction_amount]
params[:registration_code][:billing_transaction][:transaction_amount]
No matter what I enter I cannot seem to access that nested array of parameters.
Help. Feeling super dumb right now. Thanks.
A few important changes to your new and create methods as below would solve your problem.
def new
#registration_code = RegistrationCode.new
#billing_transaction = #registration_code.build_billing_transaction
end
def create
#registration_code = RegistrationCode.new(registration_code_params)
respond_to do |format|
if #registration_code.save
format.html { redirect_to registration_codes_path, notice: 'Registration code was successfully created.' }
else
format.html { render :new }
format.json { render json: #customer.errors, status: :unprocessable_entity }
end
end
end
This is how the nested_attributes gets saved in the DB.
To retrieve the hash of billing transactions:
registration_code_params[:billing_transaction_attributes]
To retrieve the first (and only) key/value pair in the hash:
key, value = registration_code_params[:billing_transaction_attributes].first
puts key #transaction_amount
puts value #958.40
I want to add some extra parameters (categories) when filling my standard form for Event model. They are not in my events table (I have table categories_events and hmbtm in both Events and Category models). Here is my code for _form :
<% #categories.each do |category| %>
<div class="field">
<%= check_box_tag(:category, category.id) %>
<%= label_tag( :category, "#{category.name}" ) %>
</div>
<div class="actions">
<%= f.submit %>
<% end %>
I'm passing categories in new action - it's simple Category.all
Here is my code in events controller
def new
#event = Event.new
#categories = Category.all
end
def create
#event = Event.new(event_params)
#category_id = Category.find(params[:category])
respond_to do |format|
if #event.save
format.html { redirect_to #event, notice: 'Event was successfully created.' }
format.json { render action: 'show', status: :created, location: #event }
else
format.html { render action: 'new' }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
Later I want to put category_id and event_id into categories_events but I have NoMethodError
undefined method `category_id' for #<Event:0x374c268>
and #event.safe is the problem
Parameters look like this
{"utf8"=>"✓",
"authenticity_token"=>"stL+sdIhxttrk3KjkLJsuCXubjaDpNBbrLYtpjv8clw=",
"event"=>{"name"=>"asdsa",
"place"=>"asdas",
"description"=>"dsadsa"},
"commit"=>"Create Event",
"category"=>"2"}
I think that the problem is in too many parameters in new(event_params) but looking at brackets in parameters tells me that it shouldn't be a problem to make it acceptable for rails.
Error stacktrace:
http://pastebin.com/kQK1fni6
Updated event_params
def event_params
params.require(:event).permit(:name, :place, :description, :category_ids)
end
Adjust your check_box_tag to the following:
<%= check_box_tag("event[category_ids][]", category.id, #event.categories.include?(category)) %>
<%= label_tag("event[category_ids][]", category.name) %>
One more thing, you'll have to add category_ids to your whitelisted attributes.
To resolve Couldn't find Category without an ID
Replace
#category_id = Category.find(params[:category_ids])
with
#category_id = Category.find(params[:event][:category_ids])
If you check the params hash you'll see that due to the update in checkbox code(as suggested by H-man), category_ids would be part of params[:event] keys value.
Trying to create a form field where a user can submit a url per: http://apidock.com/rails/v3.2.13/ActionView/Helpers/FormHelper/url_field
I'm getting an error: ActionView::Template::Error (undefined method `homepage' for #
here is the model:
class Idea < ActiveRecord::Base
has_many :comments
mount_uploader :picture, PictureUploader
attr_accessible :description, :name, :picture, :homepage
end
the view in form.html.erb
<%= form_for(#idea) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :link %><br />
<%= url_field("homepage") %><br />
</div>
<div class="actions">
<%= f.submit %>
the view in show.html.erb
<p><b>Name: </b><%= #idea.name %></p>
<p><b>Link:</b><%= #idea.homepage %></p>
ideas_controller
def create
#idea = Idea.new(params[:idea])
respond_to do |format|
if #idea.save
format.html { redirect_to #idea, notice: 'Idea was successfully created.' }
format.json { render json: #idea, status: :created, location: #idea }
else
format.html { render action: "new" }
format.json { render json: #idea.errors, status: :unprocessable_entity }
end
end
end
def show
#idea = Idea.find(params[:id])
#comment = #idea.comments.build
respond_to do |format|
format.html # show.html.erb
format.json { render json: #idea }
end
end
Basically, when you're yielding, and using, a variable to the block in form_for, it already sets the association of the form fields.
ie:
url_field('user', 'homepage')
is equivalent to
f.url_field('homepage')
Check out the url_field, and the form_for documentation
IMHO using url_field in the form builder is antiquated and prone to errors. Eventually I was able to find: rails auto link from tenderlove: https://github.com/tenderlove/rails_autolink coupled with tinymce-rails from spohlenz: https://github.com/spohlenz/tinymce-rails. With these 2 gems you can build a full-featured form field and display the output much more effectively. Hopefully this helps someone else.
I'm using rails 4.0.1
<%= form_for #event, :html => { :multipart => true} do |f| %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :content %><br>
<%= f.text_area :content %>
</div>
<div class="field">
<%= f.label :place_id %><br>
<%= f.collection_select(:place_id, #places, :id, :title) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And I want to check for current_user.id and Place.user_id (it stores creator id). In Events cotroller i'm trying to use:
def create
#places = Place.all
#event = Event.new(event_params)
#event.user_id = current_user.id
#curplace = Place.find_by(id: params[:place_id])
#event.content = #curplace.id
respond_to do |format|
if #event.save
format.html { redirect_to #event, notice: 'Event was successfully created.' }
format.json { render action: 'show', status: :created, location: #event }
else
format.html { render action: 'new' }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
But i got an error. I think i'm not getting this Place_id param right or anything else?
Further to the comment from Ankush Kataria, the form_for helper basically creates a form which combines all the params into a hash, as opposed to form_tag, which just makes the params independently
As you've discovered, this means your params will be accessed by:
#form_for
params[:variable][:param]
#form_tag
params[:param]
form_for
The reason why this is important is because if you're using the RESTful routes interface, you'll be able to create / edit / update a variety of records
form_for basically keeps consistency throughout this process, pre-populating your forms with the various values, and keeping your code DRY
To call a form_for helper, you have to define the #varaible the form will populate. This #variable needs to be an ActiveRecord object, and is why you have to build it in the new action before your form shows
form_tag
form_tag is much more independent of the form_for helper, doesn't require any #variable, and creates the params individually
You'd use a form_tag for the likes of a contact us form or similar
Your Code
Your form looks good, but your create action can be dried up:
def create
#places = Place.all
#event = Event.new(event_params)
respond_to do |format|
if #event.save
format.html { redirect_to #event, notice: 'Event was successfully created.' }
format.json { render action: 'show', status: :created, location: #event }
else
format.html { render action: 'new' }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
private
def event_params
params.require(:event).permit(:title, :content).merge(user_id: current_user.id, place_id: params[:event][:place_id])
end
You are right that params[:place_id] isn't returning the value you expect. It only returns nil. To get the :place_id that's submitted by the form, you have to do this:
#curplace = Place.find(params[:event][:place_id])
Just replace the old line with the code above. It's because your form submits the data in the fields inside an :event key in the params hash since you're using the form_for helper method provided by Rails. That is its default behavior unless you change the 'name' attribute's value in the input fields.
Hope that helps!
I'm trying to get the text from a text_area field in a form to save to a database in a different Model with the current Model's ID.
Currently, this works but only will save integers. If I put text into the 'Notes' field, then its saves it as a '0'. I suspect this is working correctly but I'm missing a piece to my puzzle. This is because I only want the 'Ticket' to save the note_id because I will have multiple 'Notes' per 'Ticket.
How can I get the Note to save in the Note Model, with an ID, and associate that note_id with this specific ticket?
Form - /app/views/tickets/_form.html.erb
<%= form_for(#ticket) do |f| %>
<% if #ticket.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#ticket.errors.count, "error") %> prohibited this ticket from being saved:</h2>
<ul>
<% #ticket.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.fields_for :notes do |u|%>
<%= u.label :note %>
<%= u.text_area :note, :size => "101x4", :placeholder => "Leave notes here." %>
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Tickets_controller.rb
class TicketsController < ApplicationController
# GET /tickets
# GET /tickets.json
def index
#tickets = Ticket.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #tickets }
end
end
# GET /tickets/1
# GET /tickets/1.json
def show
#ticket = Ticket.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #ticket }
end
end
# GET /tickets/new
# GET /tickets/new.json
def new
#ticket = Ticket.new
#ticket.notes.build
respond_to do |format|
format.html # new.html.erb
format.json { render json: #ticket }
end
end
# GET /tickets/1/edit
def edit
#ticket = Ticket.find(params[:id])
end
# POST /tickets
# POST /tickets.json
def create
#ticket = Ticket.new(params[:ticket])
respond_to do |format|
if #ticket.save
format.html { redirect_to #ticket, notice: 'Ticket was successfully created.' }
format.json { render json: #ticket, status: :created, location: #ticket }
else
format.html { render action: "new" }
format.json { render json: #ticket.errors, status: :unprocessable_entity }
end
end
end
# PUT /tickets/1
# PUT /tickets/1.json
def update
#ticket = Ticket.find(params[:id])
respond_to do |format|
if #ticket.update_attributes(params[:ticket])
format.html { redirect_to #ticket, notice: 'Ticket was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #ticket.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tickets/1
# DELETE /tickets/1.json
def destroy
#ticket = Ticket.find(params[:id])
#ticket.destroy
respond_to do |format|
format.html { redirect_to tickets_url }
format.json { head :no_content }
end
end
end
Note.rb
class Note < ActiveRecord::Base
belongs_to :ticket
attr_accessible :note, :ticket_id
end
Ticket.rb
class Ticket < ActiveRecord::Base
attr_accessible :notes_attributes
accepts_nested_attributes_for :notes
end
It is because note_id is an integer type.
Use nested models:
Refer this for Nested Models
Model:
class Ticket < ActiveRecord::Base
has_many :notes
attr_accessible :note_id, :notes_attributes
accepts_nested_attributes_for :notes
end
View:
<%= form_for(#ticket) do |f| %>
<%= f.fields_for :notes do |u|%>
<%= u.label :note %>
<%= u.text_area :note %>
<% end %>
<%= f.submit 'Submit' %>
<% end %>
What you have is a nested association, with Ticket as the "parent". The association is governed by the link from note_id in the Note model to the id (primary key) of the Ticket. What you're presently doing right now is manually manipulating that numeric association. Rails, knowing that the note_id column is supposed to be an integer, is taking the text you're trying to insert and turning it in to a number (zero in this case). You've probably got a bunch of orphaned rows right now because of this.
Ultimately, in order to accomplish what you're trying to do, your form will need to provide fields for that associated model. One way you can handle this is by using the accepts_nested_attributes_for in your Ticket model. Like so:
class Ticket < ActiveRecord::Base
has_many :notes
accepts_nested_attributes_for :notes
end
And in your form, you can easily create a nested form like so:
<%= form_for(#ticket) do |f| %>
<div class="field">
<%= f.fields_for :notes do |f_notes|%>
<%= f_notes.label :note %><br />
<%= f_notes.text_area :note, :size => "101x4", :placeholder => "Please leave notes here."%>
<% end %>
</div>
<% end %>
Edit Almost forgot: Check out this Railscast from Ryan Bates dealing with Nested Attributes
Edit 2 As codeit pointed out, you don't need the attr_accessible :note_id in Ticket. Since you've indicated that a Ticket has many Notes, and that Note belongs to Ticket, the foreign key column will appear in the Note model as ticket_id, which you already have. Having note_id in the ticket model is useless, and also nonsensical since has_many describes a plural relationship (which can't be expressed with a single column).