I'm confused writing my backend for the barangay profiles. In my form there is a field where ask to input the your barangay then when it save the barangay field will be save at the barangay model. In the brgyprofile it is associated to barangay model where the id of barangay model is FK of brgyprofile model. How can I save the data in barangay model. I already try to twerk it but nothing happens. brgy_name didn't save in the barangay model. I'm confuse how. I'm really new to rails and trying to create an app.
routes.rb
resources :brgyadmins do
resources :brgyprofiles
end
models
class Brgyprofile < ActiveRecord::Base
belongs_to :barangay
belongs_to :brgyadmin
end
class Barangay < ActiveRecord::Base
has_one :brgyprofile
end
_form.html.erb
<%= simple_form_for ([#brgyadmin,#new_profile]) do |f| %>
<%= f.input :firstname, placeholder: 'Firstname' %>
<%= f.input :lastname, placeholder: 'Lastname' %>
<%= f.input :birthdate, :order => [:month, :day, :year] %>
<%= f.input :gender,
:as => :radio_buttons,
:collection => %w[Female Male]
%>
<%= f.input :brgy_name, placeholder: 'Barangay' %>
<%= f.input :brgy_position, placeholder: 'Barangay Position' %>
<%= f.input :contact_number, placeholder: 'Contact Number' %>
<%= f.button :submit, 'Submit' %>
<% end %>
brgyprofile controller
class BrgyprofilesController < ApplicationController
before_action :set_brgyprofile, only: [:new, :create]
def new
#new_profile = #brgyadmin.build_brgyprofile
end
def create
#respond_to do |format|
if #brgyadmin.create_brgyprofile(profile_params) && Barangay.create(brgy_name: params[:brgy_name])
logger.info "Saved!"
else
logger.info "Nothing happens"
end
#end
end
private
def set_brgyprofile
#brgyadmin = Brgyadmin.find(session[:user_id])
end
def profile_params
params.require(:brgyprofile).permit(:firstname, :lastname, :birthdate, :gender, :brgy_position, :contact_number, :barangay_id, :brgy_name)
end
end
Related
I just started working on my second Rails project and am having some trouble with something that seems pretty basic. I am completely confounded though.
I've set up two models, User and Profile. A Profile belongs_to a User and the User has_one Profile.
I am setting up the edit form for a Profile right now and cannot get past this. The edit form loads correctly and inserts the data in the database but when I submit the form I get the following error
No route matches {:action=>"show", :controller=>"profiles", :format=>nil, :id=>#<Profile id: 7, user_id: 7, content: "Fill this in", created_at: "2015-01-08 19:08:22", updated_at: "2015-01-08 19:08:22", title: "fooobar", department: "one bar", school: "dsadsa", education: "two bar", academic_focus: "my bar is broken", website: "who bar is bokrbne">} missing required keys: [:id]
My models look like this
Class User < ActiveRecord::Base
has_one :profile, :class_name => 'Profile', :foreign_key => 'user_id'
attr_accessor :remember_token
end
class Profile < ActiveRecord::Base
belongs_to :user, :class_name => "User", :foreign_key => 'user_id'
attr_accessor :id
validates :content, presence: true, length: {maximum: 5000}
validates :user_id, presence: true
end
This is the form. I've tried various ways of adding a url: parameter to form_for but had no luck.
<%= form_for #profile do |f| %>
<%= f.label :title, class: 'col-lg-3 control-label' %>
<%= f.text_field :title, class: 'form-control' %>
<%= f.label :department, class: 'col-lg-3 control-label' %>
<%= f.text_field :department, class: 'form-control' %>
<%= f.label :school, class: 'col-lg-3 control-label' %>
<%= f.text_field :school, class: 'form-control' %>
<%= f.label :education, class: 'col-lg-3 control-label' %>
<%= f.text_field :education, class: 'form-control' %>
<%= f.label :academic_focus, class: 'col-lg-3 control-label' %>
<%= f.text_field :academic_focus, class: 'form-control' %>
<%= f.label :website, class: 'col-lg-3 control-label' %>
<div class="col-lg-8">
<%= f.text_field :website, class: 'form-control' %>
<%= f.hidden_field :id %>
<%= f.submit "Save changes", class: "btn btn-primary" %>
<% end %><!-- End of Form -->
Finally, here is the controller I am using.
class ProfilesController < ApplicationController
include ApplicationHelper
def index
# #profiles = Profile.limit(5)
#profiles = Profile.limit(15)
end
def show
#profile = Profile.find(params[:id])
end
def new
end
def create
#profile = Profile.new(profile_params)
if #profile.save
#successful save
flash[:success] = "Look at that. Ur Profile was ssaved"
redirect_to #profile
else
#unsuccesful
render 'new'
end
end
def edit
#user = current_user
#profile = Profile.find(#user.id)
end
def update
#profile = Profile.find(params[:id])
if #profile.update_attributes!(profile_params)
flash[:notice] = 'The User is successfully updated!'
redirect_to edit_profile_path
else
flash[:error] = #profile.errors.full_messages[0]
redirect_to edit_user_path
end
end
def view
#profile = Profile.find(params[:id])
end
private
def profile_params
params.require(:profile).permit(:id, :user_id, :content, :title, :department, :school, :education, :academic_focus, :website)
end
end
It is weird because I am using pretty much the exact same code I use for editing/creating users, but it isn't working. I figure it has something to do with relationship in the database.
Any insight would be much appreciated.
Thanks.
EDIT #1
Here's a photo of what happens when I submit the form
EDIT #2
If that image is too small here is a better one
http://i.imgur.com/Wu3v7Gu.png
EDIT #3
I changed the form_for arguments to
<%= form_for #profile, url: profile_update_path(#profile) do |f| %>
Now when the form is submitted I get this error
undefined method `profile_update_path' for #<#<Class:0x007fe1ae0e5618>:0x007fe1aca90458>
Remove the attr_accessor :id statement, it's likely interfering with the ActiveRecord default accessors in some way.
I have a serialized object :address in Hotel model and I don't know how to save it properly in the DB. I have the following:
#model hotel
class Hotel < ActiveRecord::Base
belongs_to :user
serialize :address, Hash
end
...and view 'new'
<%= form_for(#hotel) do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :stars %>
<%= f.text_field :stars %>
<%= f.label :room, "Room description" %>
<%= f.text_area :room, size: "20x10" %>
<%= f.label :price %>
<%= f.number_field :price %>
<%= f.fields_for :address do |o| %>
<%= o.label :country %>
<%= o.text_field :country %>
<%= o.label :state %>
<%= o.text_field :state %>
<%= o.label :city %>
<%= o.text_field :city %>
<%= o.label :street %>
<%= o.text_field :street %>
<% end %>
<%= f.submit "Create hotel", class: "btn btn-large btn-primary" %>
<% end %>
With this code what I get is: hotel address nil...
Okay.. We will go another way. After googling much I came to this code:
# hotel.rb model
class Hotel < ActiveRecord::Base
class Address
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :country, :state, :city, :street
def persisted?; true end
def id; 1 end
def self.load json
obj = self.new
unless json.nil?
attrs = JSON.parse json
obj.country = attrs['country']
obj.state = attrs['state']
obj.city = attrs['city']
obj.street = attrs['street']
end
obj
end
def self.dump obj
obj.to_json if obj
end
end
belongs_to :user
serialize :address, Address
end
and the same view new.html.erb
The result is: Address:0xb0e530c
So, nothing saves in the database... I don't know what to try next, I'll appreciate any help. Didn't know that serialized object will cause so much problems to me.
THANKS!
PS Here's hotels_controller.
class HotelsController < ApplicationController
before_action :signed_in_user, only: [:index, :edit, :update, :destroy]
def new
#hotel = Hotel.new
end
def index
#hotels = Hotel.paginate(page: params[:page])
end
def show
#hotel = Hotel.find(params[:id])
end
def create
#hotel = current_user.hotels.build(hotel_params)
if #hotel.save
flash[:success] = "Hotel created!"
redirect_to #hotel
else
render 'new'
end
end
private
def hotel_params
params.require(:hotel).permit(:title, :stars, :room, :price, :address)
end
end
First thing on your migration file make sure that you are saving your fields as a test like
def self.up
add_column : hotels, : address, :text
end
Then Rails will convert it into YAML / Hash for you (and perform proper serialization).
Wish you the best of luck.
PS take a look at https://stackoverflow.com/a/6702790/1380867
I have models for Venues and Photos:
class Venue < ActiveRecord::Base
has_and_belongs_to_many :photos
validates :name, presence: true
validates :permalink, presence: true, uniqueness: true
def to_param
permalink
end
end
class Photo < ActiveRecord::Base
mount_uploader :image, PhotoUploader
has_and_belongs_to_many :venues
end
I'm using simple_form to make the following form:
<div class="content-box">
<%= simple_form_for [:admin, #venue] do |f| %>
<%= f.input :name %>
<%= f.input :permalink %>
<%= f.input :description, input_html: { cols: 100, rows: 6 }%>
<%= f.input :address %>
<%= f.input :city %>
<%= f.input :phone %>
<%= f.association :photos %>
<%= f.button :submit, class: 'small radius' %>
<% end %>
</div>
And here is my controller for the Edit and Update methods:
class Admin::VenuesController < ApplicationController
def edit
#venue = Venue.find_by_permalink!(params[:id])
#photos = #venue.photos.all
end
def update
#venue = Venue.find_by_permalink!(params[:id])
if #venue.update_attributes(venue_params)
redirect_to edit_admin_venue_path(#venue), notice: 'Venue was successfully updated.'
else
render action: "edit"
end
end
private
def venue_params
params.require(:venue).permit(:name, :permalink, :description, :address, :city, :phone, :photo_ids)
end
end
The problem is that when I update using the form, all of the attributes for the venue model update fine, but the photo_ids are not updated or stored. I'm guessing it's something simple, but I'm not sure what it is. I'm using Rails 4, btw.
You need to permit photo_ids as an Array because photo_ids is passed as an Array upon form submission. Currently, photo_ids are not getting updated as you didn't permit them as an Array.
Update the venue_params as below:
def venue_params
params.require(:venue).permit(:name, :permalink, :description, :address, :city, :phone, :photo_ids => [])
end
Notice: :photo_ids => [] and NOT :photo_ids
Nested attributes of join model won't be saved. relation id's seems to be missing. The following error messages are added when the fields get validated:
* Assigned projects user can't be blank
* Assigned projects project can't be blank
The submitted params look like this ( <%= debug(params) %> )
--- !map:ActionController::Parameters
utf8: "\xE2\x9C\x93"
authenticity_token: HrF1NHrKNTdMMFwOvbYFjhJE1ltlKbuz2nsfBYYBswg=
project: !map:ActionController::Parameters
name: Peter Pan
assigned_projects_attributes: !map:ActiveSupport::HashWithIndifferentAccess
"0": !map:ActiveSupport::HashWithIndifferentAccess
position: Group Leader
currency: " Neverland Dollars"
commit: Add Project
action: create
controller: projects
I have 3 models, as followed:
class User < ActiveRecord::Base
has_many :assigned_projects
has_many :projects, :through => :assigned_projects
has_many :created_projects, :class_name => "Project", :foreign_key => :creator_id
end
class AssignedProject < ActiveRecord::Base
belongs_to :user, class_name: "User"
belongs_to :project, class_name: "Project"
attr_accessible :project_id, :user_id, :position, :project_attributes
accepts_nested_attributes_for :project
validates :user_id, presence: true
validates :project_id, presence: true
validates :position, presence: true
end
class Project < ActiveRecord::Base
belongs_to :user
has_many :assigned_projects
has_many :users, :through => :assigned_projects
belongs_to :creator, :class_name => "User", :foreign_key => :creator_id
attr_accessible :name, :creator_id, :currency :assigned_projects_attributes
accepts_nested_attributes_for :assigned_projects
validates :name, presence: true, length: { minimum: 3, maximum: 100 }
validates :currency, presence: true, length: { minimum: 1, maximum: 5 }
validates :creator_id, presence: true
end
So each User can create a Project. He can add any User to the Project through the join model.
Each Project belongs to a User resp. Creator and has_many user through assigned_projects
I want to give each user of a project a "position", which should be saved in the join model: assigned_project :position
the Project controller looks like that:
class ProjectsController < ApplicationController
def new
#project = Project.new
#project.assigned_projects.build(user_id: current_user)
end
def create
#project = current_user.assigned_projects.build.build_project(params[:project])
#project.creator = current_user
if #project.save
redirect_to current_user
else
render 'new'
end
end
end
and the project/new.html.erb form looks like that:
<%= form_for( #project ) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.fields_for :assigned_projects do |ff| %>
<%= ff.label :position %>
<%= ff.text_field :position%>
<% end %>
<%= f.label :currency %>
<%= f.text_field :currency %>
<%= f.submit "Add Project", class: "" %>
<% end %>
UPDATE: current controller & view
def create
#project = Project.new(params[:project])
if #project.save
redirect_to current_user
else
render 'new'
end
end
<%= form_for( #project ) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.hidden_field :creator_id, value: current_user.id %>
<%= f.fields_for :assigned_projects, #project.assigned_projects do |ff| %>
<%= ff.label :position %>
<%= ff.text_field :position%>
<% end %>
<%= f.label :currency %>
<%= f.text_field :currency %>
<%= f.submit "Add Project", class: "" %>
<% end %>
View:
I think you need to pass the objects collection #project.assigned_projects you built in the new action to the fields_for:
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.fields_for :assigned_projects, #project.assigned_projects do |ff| %>
<%= ff.label :position %>
<%= ff.text_field :position%>
<% end %>
<%= f.label :currency %>
<%= f.text_field :currency %>
<%= f.submit "Add Project", class: "" %>
Controller:
If i understood the first line in the create action i think you try to re-build the project assigned_projects in-order to stamp the creator attribute !!
Instead you could remove this line and put a hidden field in the nested for, something like:
<%= ff.hidden_field :creator, current_user %>
So your controller looks pretty basic now:
def create
#project = Project.new(params[:prject])
if #project.save #nested objects will be saved automatically
redirect_to current_user
else
render 'new'
end
end
What does the build_project method do?
I think in your controller you should just have build, not build.build_project, so like this:
#project = current_user.assigned_projects.build(params[:project])
of if build_project is a method used to create the params then
#project = current_user.assigned_projects.build(project_params)
in the case of rails 4 you would need something like this:
def project_params
params.require(:project).permit(:your_params)
end
In the case of rails 3 I think you need to add
attr_accessible :param1, :param2
in the project model for the parameters you want to set.
Problem is solved by removing the validations for project_id and user_id in the join table "AssignedProject"
So the join Model looks like that:
# Join Model AssignedProject
class AssignedProject < ActiveRecord::Base
belongs_to :user#, class_name: "User"
belongs_to :project#, class_name: "Project"
attr_accessible :project_id, :user_id, :position, :project, :project_attributes
accepts_nested_attributes_for :project
validates :position, presence: { message: " can't be blank." }
end
The New and Create methods look like that:
# Projects Controller
class ProjectsController < ApplicationController
def new
#project = Project.new
#project.assigned_projects.build(user_id: current_user)
end
def create
#project = Project.new(params[:project])
if #project.save
#project.assigned_projects.create(user_id: current_user)
redirect_to current_user
else
render 'new'
end
end
end
And the form in the view for the new method looks like that:
<%= form_for( #project ) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.hidden_field :creator_id, value: current_user.id %>
<%= f.fields_for :assigned_projects, #project.assigned_projects do |ff| %>
<%= ff.hidden_field :project_id, value: #project %>
<%= ff.hidden_field :user_id, value: current_user.id %>
<%= ff.label :position %>
<%= ff.text_field :position%>
<% end %>
<%= f.label :currency %>
<%= f.text_field :currency %>
<%= f.submit "Add Project", class: "" %>
<% end %>
During registration of a new user with Devise, I need to create a new Family object link to this new user at the same time (the user being the head of the family).
My family model:
belongs_to user
My user model:
attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :family
has_one :family
accepts_nested_attributes_for :family
In devise/registration/new.html.erb
<%= simple_form_for([resource, Family.new], :as => resource_name, :url => registration_path(resource_name), :html => {:class => 'form-vertical' }) do |f| %>
<%= f.error_notification %>
<%= display_base_errors resource %>
<%= f.input :name, :autofocus => true %>
<%= f.input :email, :required => true %>
<%= f.input :password, :required => true %>
<%= f.input :password_confirmation, :required => true %>
<% f.fields_for :family do |family_form| %>
<p><%= family_form.label :name %></p>
<p><%= family_form.text_field :name %></p>
<% end %>
<%= f.button :submit, 'OK', :class => 'btn-primary' %>
<% end %>
But this is not working, I find a couple of question like this but I did not manage to fix that.
Any idea ?
UPDATE 1
I got the following error:
undefined method `email' for #<Family:0x007f892a12c310>
Family is a model that do not have any email, just a name. I just need to be able to create a new Family object with a name when creating a new user (and link it to the user as well).
UPDATE 2
I have added resource.build_family in my registrations controller. The family object is correctly created and associated to the user (I can display <%= resource.family %> in new.html.erb for debugging), but still no form displayed for the family.
You need the equal sign in the <%=fields_for
<%= f.fields_for :family do |family_form| %>
<p><%= family_form.label :name %></p>
<p><%= family_form.text_field :name %></p>
<% end %>
And in your user model you need to make the :family_attribues accessible and not :family
attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :family_attributes
has_one :family
accepts_nested_attributes_for :family
If you're getting undefined method 'email' for #<Model:0x007f892a12c310>:
You need to overwrite Devise::RegistrationsController as described in the docs: https://github.com/heartcombo/devise#configuring-controllers. E.g.
class Users::RegistrationsController < Devise::RegistrationsController
def new
super do |resource|
resource.build_<model>
end
end
end
And you must only specify resource in form_for: simple_form_for(resource, ... instead of simple_form_for([resource, Model.new], ...