I want to insert tags in new Place. giving that tags is in different model.
####### models ##########
class Tag < ActiveRecord::Base
belongs_to :place
attr_accessible :tag
end
class Place < ActiveRecord::Base
has_many :tags
end
how can I handle this in the new Place create form? and the create action in the places_controller? so that I can insert new place and mant tags then assign the product id to each tag.
####### place controller ##########
def create
#place = Place.new(params[:place])
#tag = Tag.new(params[:?????]) #this should be more than once
respond_to do |format|
if #place.save
format.html { redirect_to #place, notice: 'Place was successfully created.' }
format.json { render json: #place, status: :created, location: #place }
else
format.html { render action: "new" }
format.json { render json: #place.errors, status: :unprocessable_entity }
end
end
end
####### place new form ##########
<%= form_for #place do |f| %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :description %><br />
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :rank %><br />
<%= f.text_field :rank %>
</div>
<div class="field">
<%= f.label :lat %><br />
<%= f.text_field :lat %>
</div><div class="field">
<%= f.label :lng %><br />
<%= f.text_field :lng %>
</div>
<div class="field">
<%= f.label :address %><br />
<%= f.text_area :address %>
</div>
<div class="field">
<%= f.label :website %><br />
<%= f.text_field :website %>
</div>
<div class="field">
<%= f.label :phone %><br />
<%= f.text_field :phone %>
</div>
<div class="field">
<%= label_tag "tags" %>
<%= f.text_field :tag %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
If you want to do it on your own, you should look into accepts_nested_attributes_for, where there's a great 2 part tutorial by Ryan Bates at railscasts.com
If you don't want to do it on your own, there are several tag gems available, for instance:
ActsAsTaggableOn.
Add this in your form:
<%= f.fields_for :tags do |t| %>
<%= t.label :name %>
<%= t.text_field :name %>
<% end %>
And in your Place model:
accepts_nested_attributes_for :tags
And in your controller, you wouldn't even have to worry about creating tags.
You should still try to read about fields_for and accepts_nested_attributes_for, they're often useful, since your problem is very common.
Related
I get a 500 Internal Server Error when I submit the nested form which has two models - Member and ChildrenInformation.
Error:
500 Internal Server Error
If you are the administrator of this website, then please read this web application's log file and/or the web server's log file to find out what went wrong.
I checked the log file, and this is what I found out:
TypeError (expected Hash (got Array) for param `child_info_attrib'):
Here are the other parts of my rails project
View (new.html.erb>
<%= form_for(#member) do |f| %>
<div class="field">
<%= f.label :gender, "Gender" %><br />
<%= f.select :gender, options_for_select(["Male", "Female"]) %>
</div>
<div class="field">
<%= f.label :fname, "First Name" %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :age, "Age" %><br />
<%= f.text_field :age %>
</div>
<div class="field">
<%= f.label :membership_id, "Membership ID" %>
<%= f.text_field :membership_id %>
</div>
<div class="field">
<%= f.label "Branch" %>
<%= f.collection_select(:branch_id, Branch.all, :id, :name) %>
</div>
<% for children_information in #member.children_informations %>
<%= fields_for "member[child_info_attrib][]", children_information do |children_info_form| %>
<div class="field">
<%= children_info_form.label :name, "Name" %><br />
<%= children_info_form.text_field :name %>
</div>
<div class="field">
<%= children_info_form.label :gender, "Gender" %><br />
<%= children_info_form.select :gender, options_for_select(["Male", "Female"]) %>
</div>
<div class="field">
<%= children_info_form.label :birthdate, "Birthdate" %><br />
nn <%= children_info_form.datetime_select :birthdate, :discard_hour => true,
:order => [:month, :day, :year], :start_year => 1900 %>
</div>
</div>
<% end %>
<% end %>`
Model (Member)
class Member < ActiveRecord::Base
has_many :children_informations
def child_info_attrib=(attribs)
attribs.each do |attrib|
children_informations.build(attrib)
end
end
end
Model (ChildrenInformation)
class ChildrenInformation < ActiveRecord::Base
belongs_to :member
end
Controller (MembersController)
class MembersController < ApplicationController
def new
#member = Member.new
#member.children_informations.build
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #member }
end
end
def create
#member = Member.new(params[:member])
respond_to do |format|
if #member.save
format.html { redirect_to(#member, :notice => 'Member was successfully created.') }
format.xml { render :xml => #member, :status => :created, :location => #member }
else
format.html { render :action => "new" }
format.xml { render :xml => #member.errors, :status => :unprocessable_entity }
end
end
end
Development Log: http://pastebin.com/n9E2nyFv (members table has a lot of fields)
What I tried so far is to omit the nested form, and it did work. Additionally, I based this way of using nested form through RailsCasts (http://railscasts.com/episodes/73-complex-forms-part-1).
How can I submit it successfully with the nested form?
Thank you in advance! :)
I think you're building your nested form incorrectly:
#app/views/members/new.html.erb
<% for children_information in #member.children_informations %>
<%= fields_for "member[child_info_attrib][]", children_information do |children_info_form| %>
<div class="field">
<%= children_info_form.label :name, "Name" %><br />
<%= children_info_form.text_field :name %>
</div>
<div class="field">
<%= children_info_form.label :gender, "Gender" %><br />
<%= children_info_form.select :gender, options_for_select(["Male", "Female"]) %>
</div>
<div class="field">
<%= children_info_form.label :birthdate, "Birthdate" %><br />
nn <%= children_info_form.datetime_select :birthdate, :discard_hour => true,
:order => [:month, :day, :year], :start_year => 1900 %>
</div>
</div>
<% end %>
<% end %>
You'd need to do this:
View
<%= f.fields_for :children_informations do |children_info_form| %>
<div class="field">
<%= children_info_form.label :name, "Name" %><br />
<%= children_info_form.text_field :name %>
</div>
<div class="field">
<%= children_info_form.label :gender, "Gender" %><br />
<%= children_info_form.select :gender, options_for_select(["Male", "Female"]) %>
</div>
<div class="field">
<%= children_info_form.label :birthdate, "Birthdate" %><br />
nn <%= children_info_form.datetime_select :birthdate, :discard_hour => true,
:order => [:month, :day, :year], :start_year => 1900 %>
</div>
</div>
<% end %>
This will create the form elements with the correct data, but I also think your handling of the data can be improved. As you're on Rails 3, I'll wait for a comment to see if you'd like me to write some code for it!
the railscast episode you are following is dated 2007.
I don't think this approach is the best in doing nested forms.
this
def child_info_attrib=(attribs)
attribs.each do |attrib|
children_informations.build(attrib)
end
end
could be simplified to this (if you are using rails 3.x >)
attr_accessible :childs_attributes
accepts_nested_attributes_for :childs
If you want references or some tutorials to follow I would recommend
http://railscasts.com/episodes/196-nested-model-form-revised
http://railscasts.com/episodes/197-nested-model-form-part-2
or if you don't those, you could look at this gem
https://github.com/nathanvda/cocoon
which simplifies what you are trying to achieve.
It was a mistake that I defaced the note of RailsCasts episode about nested forms (http://railscasts.com/episodes/73-complex-forms-part-1) that it is outdated, and I should instead follow the latest episode of the said topic (http://railscasts.com/episodes/196-nested-model-form-part-1). It worked now :)
First things first
Using:
rails4
oracle enhanced adapter rails4 branch
I have a many to many relationship mapped on an existing database.
My models look as such:
class EventMap < ActiveRecord::Base
self.table_name="TAKE_PART"
self.primary_key="id"
belongs_to :event, foreign_key: "lottery_event_id"
belongs_to :entrant, foreign_key: "address_id"
end
class Event < ActiveRecord::Base
self.table_name="THE_EVENT"
self.primary_key="id"
has_many :event_maps, :foreign_key => "lottery_event_id"
has_many :entrants, :through => :event_maps
accepts_nested_attributes_for :entrants, :reject_if => :all_blank
end
class Entrant < ActiveRecord::Base
self.table_name="ADDRESSES"
self.primary_key="id"
self.set_date_columns :date_of_birth
has_many :events, :through => :event_maps
has_many :event_maps, :foreign_key => "address_id"
end
static page controller for my voting page
...
def vote
#event=Event.find_by(id: 4227)
#entrants=#event.entrants
#entrant=#event.entrants.build
end
...
vote view:
<%= form_for(#event) do |f| %>
<%= f.fields_for :entrant do |builder| %>
<%= render "/entrants/fields", :f => builder %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
entrant/fields partial:
<% if #entrant.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#entrant.errors.count, "error") %> prohibited this entrant from being saved:</h2>
<ul>
<% #entrant.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.hidden_field :id %>
<div class="field">
<%= f.label :lastname %><br>
<%= f.text_field :lastname %>
</div>
<div class="field">
<%= f.label :firstname %><br>
<%= f.text_field :firstname %>
</div>
<div class="field">
<%= f.label :street %><br>
<%= f.text_field :street %>
</div>
<div class="field">
<%= f.label :country_id %><br>
<%= f.number_field :country_id %>
</div>
<div class="field">
<%= f.label :city %><br>
<%= f.text_field :city %>
</div>
<div class="field">
<%= f.label :telephone %><br>
<%= f.text_field :telephone %>
</div>
<div class="field">
<%= f.label :email %><br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :date_of_birth %><br>
<%= f.date_select :date_of_birth %>
</div>
<div class="field">
<%= f.label :lang_id %><br>
<%= f.text_field :lang_id %>
</div>
<div class="field">
<%= f.label :added %><br>
<%= f.date_select :added %>
</div>
<div class="field">
<%= f.label :salut %><br>
<%= f.text_field :salut %>
</div>
<div class="field">
<%= f.label :zip %><br>
<%= f.text_field :zip %>
</div>
<div class="field">
<%= f.label :newsletter %><br>
<%= f.check_box :newsletter %>
</div>
<div class="field">
<%= f.label :company %><br>
<%= f.text_field :company %>
</div>
The form now submits to event controller PATCH
class EventsController < ApplicationController
before_action :set_event, only: [:show, :edit, :update, :destroy]
...
# PATCH/PUT /events/1
# --> HOW DO I SAVE THE SUBMITTED ENTRANT HERE??? <--
def update
respond_to do |format|
if #event.update(event_params)
format.html { redirect_to #event, notice: 'Event was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
...
private
# Use callbacks to share common setup or constraints between actions.
def set_event
#event = Event.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def event_params
params.require(:event).permit(:id, :lottery_id, :events_dates_id, :event_date, :event_location, :tickets_for_winner, :prize, :tickets_internally,
:entrants_attributes => [:id, :lastname, :firstname, :street, :country_id, :city, :telephone, :email, :date_of_birth, :lang_id, :added, :salut, :zip, :newsletter, :company])
end
end
How do I register an Entrant with an Event, adding data only to the intermediate model EventMap since the Event will always exist?
Do I need to include accepts_nested_attributes_for in my models to propagate changes accross tables (I could not quite figure out what this does from the documentation)? Do I need to send additional params via the Entrant form to update the EventMap?
Main GOAL: I want a form where Entrants can register to an existing event!
Hard to judge about Your forms, as we don't see any ;)
But You are right to be able to create nested attributes, from nested attributes from, You need to set accepts_nested_attributes_for :some_model, :some_other_model
If You find docs confusing, consult Railscasts:
http://railscasts.com/episodes/196-nested-model-form-part-1
http://railscasts.com/episodes/197-nested-model-form-part-2
You are requiring custom logic and that custom logic must be defined, Rails will not automatically update everything, it must be defined in the update controller as you suggest.
I might do something along the lines of this:
def update
entrant = Entrant.find(params[:entrant_id])
event = Event.find(params[:event_id])
EventMap.create!(event: event, entrant: entrant)
#.... go on with usual stuff
# Alternatively you could use build
event_map = EventMap.new
event_map.build(event: event, entrant: entrant)
end
Trying to update a post that I've made in my Ruby on Rails project but nothing happens. It is really annoying since I don't get any errors and can't seem to figure out what I am doing wrong.
I think it worked before, but since I first wrote the different actions I've added multiple things to my "feed"-model, such as impressions and tags. Don't know if this has affected my update action...
My controller looks like this:
def edit
#feed = Feed.find(params[:id])
end
def update
#feed = Feed.find(params[:id])
respond_to do |format|
if #feed.update_attributes(params[:feed])
format.html { redirect_to #feed, notice: 'Feed was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #feed.errors, status: :unprocessable_entity }
end
end
end
My feed model looks like this:
attr_accessible :content, :tag_list, :guid, :language, :location, :published_at, :summary, :url, :title, :user_id, :thumbnail_url, :url_to_feed, :type_of_feed
has_many :impressions, :as=>:impressionable
validates_length_of :tag_list, :maximum => 10
acts_as_taggable
My view looks like this:
<h1>Editing feed</h1>
<%= render 'form' %>
<%= link_to 'Show', #feed %> |
<%= link_to 'Back', feeds_path %>
____________________ form
<%= form_for(#feed) do |f| %>
<% if #feed.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#feed.errors.count, "error") %> prohibited this feed from being saved:</h2>
<ul>
<% #feed.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<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 :location %><br />
<%= f.text_field :location %>
</div>
<div class="field">
<%= f.label :language %><br />
<%= f.text_field :language %>
</div>
<div class="field">
<%= f.label :tag_list, "Tags (seperated by spaces)" %><br />
<%= f.text_field :tag_list %>
</div>
<div class="actions">
<%= f.submit %>
</div>
The log entry
Started PUT "/feeds/1" for 127.0.0.1 at 2013-02-17 12:27:36 +0100 Processing by FeedsController#show as HTML
says,that the PUT request (sending your form data) is being processed by FeedsController#show, but it has to be processed by FeedsController#update. So your routes seem to be wrong. Check out the Rails Routing Guide.
I would use a feeds ressource, because it creates the correct routes automatically:
resources :feeds
Hi
I'm pretty new with Ruby On Rails, and came across this problem.
I have 4 tables, and 1 that has the three others connected to it.
Sportcategories - name of each category
Sports - Name of each sport
Clubs - Name of each club
Results,
t.integer "sportcategory_id"
t.integer "sport_id"
t.integer "club_id"
I have managed to make a simple edit form with text_field for each field in results. But how can I get the names for the integers instead of the numbers?
<%= form_for(#result) do |f| %>
#if...
#..
#end
<div class="field">
<%= f.label :sportcategory_id%><br />
<%= f.text_field :sportcategory_id%>
</div>
<div class="field">
<%= f.label :sport_id %><br />
<%= f.text_field :sport_id %>
</div>
<div class="field">
<%= f.label :club_id %><br />
<%= f.text_field :club_id %>
</div>
<div class="field">
<%= f.label :result %><br />
<%= f.text_field :result %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I have made it so that SportCat, Sports and clubs has many results and that results belongs to all of them.
This is my controller file for results with edit & update
def edit
#result = Price.find(params[:id])
end
def update
#price = Price.find(params[:id])
respond_to do |format|
if #price.update_attributes(params[:price])
format.html { redirect_to(#price, :notice => 'Price was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #price.errors, :status => :unprocessable_entity }
end
end
end
And question two might be answered in question one, but I want to be able to choose from a drop-down list from all the available categories, sports and clubs with their actual name and then pass the right ID when I update it.
Check the Rails Form select helper
http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-select
<%= form_for(#result) do |f| %>
<div class="field">
<%= f.label :sportcategory_id%><br />
<%= f.select :sportcategory_id, #sportcategories.map {|s| [s.name, s.id]} %>
</div>
<div class="field">
<%= f.label :sport_id %><br />
<%= f.select :sport_id, #sports.map {|s| [s.name, s.id]} %>
</div>
<div class="field">
<%= f.label :club_id %><br />
<%= f.select :club_id, #clubs.map {|c| [c.name, c.id]} %>
</div>
<div class="field">
<%= f.label :result %><br />
<%= f.text_field :result %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Get #sportcategories, #sports, #clubs in your controller actions.
I'm on Rails 3. I have a model called Client that has name, phone and email. My model file looks like this:
class Client < ActiveRecord::Base
belongs_to :salon
belongs_to :address
validates_presence_of :name
validates_presence_of :phone
validates_presence_of :email
accepts_nested_attributes_for :address
attr_accessible :address_attributes
end
As you can see, name, phone and email are all required. When I go to the form where I'm supposed to be able to create a new Client and submit it, all three validations fail, no matter what I put in the fields. Here is my form file:
<%= form_for(#client) do |f| %>
<% if #client.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#client.errors.count, "error") %> prohibited this client from being saved:</h2>
<ul>
<% #client.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.hidden_field :salon_id, :value => Salon.logged_in_salon.id %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :phone %><br />
<%= f.text_field :phone %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<%= f.fields_for :address do |address_form| %>
<div class="field">
<%= address_form.label :line1 %><br />
<%= address_form.text_field :line1 %>
</div>
<div class="field">
<%= address_form.label :line2 %><br />
<%= address_form.text_field :line2 %>
</div>
<div class="field">
<%= address_form.label :city %><br />
<%= address_form.text_field :city %>
</div>
<div class="field">
<%= address_form.label :state_id %><br />
<%= select("client[address]", "state_id", State.all.collect {|s| [ s.name, s.id ] }) %>
</div>
<div class="field">
<%= address_form.label :zip %><br />
<%= address_form.text_field :zip %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Here's my create action:
def create
#client = Client.new(params[:client])
respond_to do |format|
if #client.save
format.html { redirect_to(#client, :notice => 'Client was successfully created.') }
format.xml { render :xml => #client, :status => :created, :location => #client }
else
format.html { render :action => "new" }
format.xml { render :xml => #client.errors, :status => :unprocessable_entity }
end
end
end
Any idea why this is happening?
It's because you set :address_attributes as the only accessible attribute. Change
attr_accessible :address_attributes
to
attr_accessible :address_attributes, :name, :phone, :email
or don't use mass assignment.