Store data from one table to another in rails - ruby-on-rails

I have a fundings table and organisations table. Fundings table has organisation_id. In fundings table I have fields that are same with organisations table. What I want is when application is created and on funding show page there is a add button to add all fields that are same in fundings and organisations table gets stored in organisations table as well. Please help
_form.html.erb (funding_form)
<%= form_for([#parent, #child, #funding], :html => {class: "form-horizontal",role: "form"}) do |form| %>
<div class = "form-group">
<div class="control-label col-sm-2">
<%= form.label :activity_details, class: "required" %>
</div>
<div class="col-sm-8">
<%= form.text_area :activity_details, required: true %>
</div>
</div>
<!--Adding organisation -->
<div class = "form-group">
<div class="control-label col-sm-2">
<%= form.label :name_of_organisation, id: "name_of_organisation-label" %>
</div>
<div class="col-sm-8">
<%= form.text_field :name_of_organisation, class: "form-control hidden", id: "name_of_organisation-textfield" %>
</div>
</div>
<div class = "form-group">
<div class="control-label col-sm-2">
<%= form.label :address, id: "address-label" %>
</div>
<div class="col-sm-8">
<%= form.text_field :address, class: "form-control hidden", id: "address-textfield" %>
</div>
</div>
<div class = "form-group">
<div class="control-label col-sm-2">
<%= form.label :city, id: "city-label" %>
</div>
<div class="col-sm-8">
<%= form.text_field :city, class: "form-control hidden", id: "city-textfield" %>
</div>
</div>
<div class = "form-group">
<div class="control-label col-sm-2">
<%= form.label :province, id: "province-label" %>
</div>
<div class="col-sm-8">
<%= form.text_field :province, class: "form-control hidden", id: "province-textfield" %>
</div>
</div>
<!-- End Adding organisation -->
<div class="form-group">
<div class="col-sm-10">
<%= form.submit "Apply", class: 'btn btn-primary btn-lg' %>
</div>
</div>
</div>
</div>
<% end %>
show.html.erb(funding show page)
<p>
<strong>Name of Organisation:</strong>
<%= #funding.name_of_organisation %></p><br>
<p>
<strong>Address:</strong>
<%= #funding.address %></p><br>
<p>
<strong>City:</strong>
<%= #funding.city %></p><br>
<p>
<strong>Province:</strong>
<%= #funding.province %></p><br>
<p>
<% if current_user.admin? %>
<%= link_to 'Add Organisation', "" %>
<% end %>
if admin clicks on add organisation fields get added to organisation table.
schema funding table
t.text "activity_details"
t.string "city"
t.string "name_of_organisation"
t.string "province"
t.text "address"
schema organisations table
t.string "name_of_organisation"
t.text "address"
t.string "city"
t.string "province"
funding.rb
belongs_to :organisation
organisation.rb
has_many :fundings
organisations controller
I have a new and create method to create organisation by the admin directly.so i have added a new_org method to get add the organisation from the funding table. But I am not able to find out how to implement it.
def new_org
#organisation = Organisation.new
end
def create_org
#organisation = Organisation.new(organisation_params)
if #organisation.save
flash[:success] = "Organisation is added"
redirect_to main_admin_service_provider_path
else
render 'new'
end
end

Something like this should work:
app/controllers/fundings_controller.rb
class FundingsController < ApplicationController
before_action :set_funding, on: %i[show add_organisation]
# ...
def update_organisation
return head :forbidden unless current_user.admin?
# assuming funding always has an organisation
whitelist = %w[your field names]
#funding.organisation.update!(#funding.attributes.slice(*whitelist))
redirect_to #funding, notice: 'fields successfully added to organisation'
end
# ...
private
def set_funding
#funding = Funding.find(params[:id])
end
end
config/routes.rb
Rails.application.routes.draw do
# ...
resources :fundings, only: :show do
# using patch because we are updating an existing resource
# but you can change this to whatever you like
patch 'update_organisation', on: :member
end
# ...
end
app/views/fundings/show.html.erb
<% if current_user.admin? %>
<%= link_to 'Add Organisation', update_organisation_funding_path(#funding), method: :patch %>
<% end %>
Alternatively you can update all double fields (without whitelisting) using the following code:
double_attribute_names = #funding.attribute_names & #funding.organisation.attribute_names
#funding.organisation.update!(#funding.attributes.slice(*double_attribute_names)
However keep in mind that this may produce unwanted results. For example some fields you don't want to update like 'id', 'created_at', 'updated_at' are most likely present on both instances, and maybe some custom double fields.
This can be resolved by creating a blacklist to exclude those fields:
blacklist = %w[id created_at updated_at]
double_attribute_names = #funding.attribute_names & #funding.organisation.attribute_names
#funding.organisation.update!(#funding.attributes.slice(*double_attribute_names).except(*blacklist))
But generally speaking it's better to whitelist.

This is not a good way to do it but you can define a hidden form with hidden fields with values of #funding.x on show page by defining
#organization = Organization.new in show method on Fundings.controller then you can simply post it as normal form. Or you can show this form to only admins.

Related

Rails: Paperclip Not Saving Image to DB

I have what should be a fairly simple setup for paperclip on my rails app.
My products_controller.rb is this:
class ProductsController < ApplicationController
...
def new
#product = Product.new
end
def create
#product = Product.new(product_params)
#product.save
flash[:notice] = "Your product has been created!"
redirect_to products_path
end
def edit
#product = Product.find(params[:id])
end
def update
#product = Product.find(params[:id])
if #product.update_attributes(product_params)
redirect_to products_path
flash[:notice] = "That product has been updated."
else
render :action => :edit
flash[:alert] = "Something went terribly wrong there..."
end
end
...
private
def product_params
params.require(:product).permit(:name, :price, :active, :short_description, :weight, :box_length, :box_width, :box_depth, :product_image)
end
end
My products#edit form (products#new doesn't work either, but it's the same form):
<%= form_for #product, html: { multipart: true } do |f| %>
<div class="form-inputs row">
<div class="form-group col-xs-9">
<%= f.label "Product Name" %>
<%= f.text_field :name, class: "form-control" %>
</div> <!-- form group -->
<div class="form-group col-xs-3">
<%= f.label :price %>
<%= f.text_field :price, class: "form-control", data: {autonumeric: true} %>
</div> <!-- form group -->
<div class="form-group col-xs-12">
<%= f.label "Product Description" %>
<%= f.text_area :short_description, class: "form-control" %>
</div> <!-- form group -->
<div class="form-group col-xs-12">
<%= f.file_field :image, as: :file %>
</div> <!-- form group -->
<div class="form-group text-center col-xs-12">
<p><%= f.check_box :active %> This is an active product.</p>
</div> <!-- form group -->
<div class="row">
<hr class="col-xs-6 col-xs-push-3" />
</div>
<div class="col-xs-12">
<h2 class="text-center">Shipping Information</h2>
</div>
<div class="form-group col-xs-6">
<%= f.label "Product Length (in Inches)" %>
<%= f.text_field :box_length, class: "form-control" %>
</div> <!-- form group -->
<div class="form-group col-xs-6">
<%= f.label "Product Width (in Inches)" %>
<%= f.text_field :box_width, class: "form-control" %>
</div> <!-- form group -->
<div class="form-group col-xs-6">
<%= f.label "Product Depth (in Inches)" %>
<%= f.text_field :box_depth, class: "form-control" %>
</div> <!-- form group -->
<div class="form-group col-xs-6">
<%= f.label "Product Weight (in Pounds)" %>
<%= f.text_field :weight, class: "form-control" %>
</div> <!-- form group -->
</div>
<div class="form-actions text-center">
<%= f.button :submit, class: "btn btn-manly" %>
</div>
<% end %>
And my relevant routes:
resources :products
And finally the product.rb model:
class Product < ActiveRecord::Base
has_many :order_items
has_attached_file :product_image
validates_attachment_content_type :product_image, content_type: /\Aimage\/.*\z/
validates_attachment_file_name :product_image, matches: [/png\z/, /jpe?g\z/]
default_scope { where(active: true) }
end
And the schema.rb for the products table:
create_table "products", force: :cascade do |t|
t.string "name"
t.decimal "price", precision: 12, scale: 3
t.boolean "active"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "short_description"
t.decimal "weight"
t.decimal "box_length"
t.decimal "box_width"
t.string "box_depth"
t.string "product_image_file_name"
t.string "product_image_content_type"
t.integer "product_image_file_size"
t.datetime "product_image_updated_at"
end
I am getting no errors when I submit. I have also tried both the simple_form_for and the form_for variations given in the Paperclip documentation. I have double checked and ImageMagick is installed. Can anyone see why it isn't saving? When I check the console after trying to upload an image it just says nil for all four paperclip fields.
You are using :image for file_field but your paperclip field is using product_image, change as follow to upload file
<div class="form-group col-xs-12">
<%= f.file_field :product_image, as: :file %>
</div> <!-- form group -->

Rails - Rendering form_for #user in a different view

I'm trying to render this code (partial to update users payment info).
/devise/registrations/_credit.html.erb
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
<form action="#">
<div class="form-group">
<label class="control-label">Card Holder Name</label>
<%= f.text_field :name, autofocus: true, class:"form-control" %></div>
<div class="form-group">
<label class="control-label">Card Number</label>
<%= f.text_field :card, autofocus: false, class:"form-control" %>
</div>
<div class="form-group">
<label class="control-label">CVV</label>
<%= f.text_field :cvv, autofocus: false, class:"form-control" %>
</div>
<div class="form-group">
<label class="control-label">Expiration Month</label>
<%= f.text_field :expmonth, autofocus: false, class:"form-control" %>
</div>
<div class="form-group">
<label class="control-label">Expiration Year</label>
<%= f.text_field :expyear, autofocus: false, class:"form-control" %>
</div>
<div class="margin-top-10">
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
<div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
<% end %>
<div class="actions">
<%= f.submit "Update", class:"btn green" %>
<% end %>
</div>
</form>
</div>
I'm trying to get this partial to show up in a different page that's not under users_controller.rb, but I keep getting an error.
NameError in Orders#new
Showing /home/nitrous/code/uvesty/app/views/devise/registrations/_credit.html.erb where line #2 raised:
undefined local variable or method `resource' for #<#<Class:0x00563138834928>:0x00563138821670>
In app/models/order.rb:
class Order < ActiveRecord::Base
belongs_to :user
# only use this if user instance is created before order,
# and alway associated with order
validates :user, presence: true
end
In app/models/user.rb:
class User < ActiveRecord::Base
has_many :orders
# --OR--
# has_one :order
end
In app/controllers/orders_controller.rb:
class OrdersController < ApplicationController
# 1)assuming `current_user` is populated
#
def new
#order = Order.new
#user = current_user
end
# --OR--
# 2) assuming the following line is in `config/routes.rb`:
# get '/orders/new/:id' => 'orders#new'
#
def new
if #order = Order.find_by_id(new_params[:id])
#user = #order.user
else
# do whatever here; replace the next line
raise "order not found"
end
end
private
# only needed for 2) above
def new_params
params.permit(:id)
end
end
see: http://guides.rubyonrails.org/action_controller_overview.html#strong-parameters
In app/view/orders/new.html.erb:
<% raise('#user not defined') unless #user %><%# <- Remove this line after partial is working %>
<%= render partial: "devise/registrations/credit", locals: {resource: #user, resource_name: :user} %>
see: http://guides.rubyonrails.org/layouts_and_rendering.html#passing-local-variables

Can't save nested model on polymorphic association

Forced to ask for help with saving nested models on polymorphic association. I'm missing something but can't figure out what.
Everithing pretty straightforward. There is Address which can have multiple Phones.
So models are
class Address < ActiveRecord::Base
has_many :phones, as: :phoneable
accepts_nested_attributes_for :phones, allow_destroy: true
validates :city, :street, :building, :name, presence: true
end
and
class Phone < ActiveRecord::Base
belongs_to :phoneable, polymorphic: true
validates :number, :extension, presence: true
end
addresses_controller.rb
def new
#address = Address.new
#phone = #address.phones.build
authorize #address
end
def create
#address = Address.create(address_params)
authorize #address
if #address.save
binding.pry
flash[:success] = "Address #{#address.name} created"
redirect_to address_path(#address)
else
flash.now[:danger] = 'Failed'
render :new
end
end
def address_params
params.require(:address).permit(:name, :street, :building, :city, phones_attributes: [:id, :number, :extension, :details] )
end
/app/views/address.html.erb
<div class="row">
<div class="col-md-12">
<%= form_for(#address, html: {class: 'form-horizontal', role: 'form'}) do |f| %>
<%= render 'shared/errors', obj: #address, model_name: 'addresses' %>
<div id="create-form">
<div class="form-group">
<div class="control-label col-md-4">
<%= f.label :city, 'Город' %>
</div>
<div class="col-md-4">
<%= f.select(:city, options_for_select(['Moscow', 'Samara']), {}, {class: "form-control"}) %>
</div>
</div>
<div class="form-group">
<div class="control-label col-md-4">
<%= f.label :street, 'Street' %>
</div>
<div class="col-md-4">
<%= f.text_field :street, class: 'form-control' %>
</div>
</div>
<div class="form-group">
<div class="control-label col-md-4">
<%= f.label :building, 'Building' %>
</div>
<div class="col-md-4">
<%= f.text_field :building, class: 'form-control' %>
</div>
</div>
<div class="form-group">
<div class="control-label col-md-4">
<%= f.label :name, 'Place name' %>
</div>
<div class="col-md-4">
<%= f.text_field :name, class: 'form-control' %>
</div>
</div>
<div class="form-group">
<div class="control-label col-md-4">
<%= f.label :phones, 'Phone' %>
</div>
<div class="col-md-4">
<%= f.fields_for :phone do |phone_form| %>
<%= phone_form.text_field :number, class: 'form-control' %>
</div>
</div>
<div class="form-group">
<div class="control-label col-md-4">
<%= phone_form.label :extension, 'Ext.' %>
</div>
<div class="col-md-4">
<%= phone_form.text_field :extension, class: 'form-control' %>
</div>
<% end %>
</div>
<div class="form-group">
<div class='col-md-offset-4 col-md-6'>
<%= f.submit #address.new_record? ? 'Add' : 'Update', class: 'btn btn-primary btn-md' %>
</div>
</div>
</div>
<% end %>
</div>
</div>
First issue I encountered with is if I set key :phones instead :phone into the following line <%= f.fields_for :phone do |phone_form| %> my phone text fields don't render in view but they should. One user emphasized this moment here https://stackoverflow.com/a/3328041/2049476
if I use :phone everything somehow works fine but seems like it's wrong.
And the second one.
Phone object doesn't save in DB, when I create new address or edit current I succeed but phone doesn't show any validation errors if I leave all it fields blank.
Here what I have in params hash
{"utf8"=>"✓",
"authenticity_token"=>"inwXr3Ev/Aj/hZRY2IadizDHDgdSFo2zFhY9DAvysfFu3jjD9AS66esKVsTzEuKo2WC46YQt6HnOKTgInvfUEg==",
"address"=>{"city"=>"Moscow", "street"=>"ul. Tsentralnaya d. 4 kv. 220", "building"=>"1212", "name"=>"Astoria", "phone"=>{"number"=>"9215555555", "extension"=>"111"}},
"commit"=>"Add",
"controller"=>"addresses",
"action"=>"create"}
What am I missing?
Try answer for 2 issues:
The correct way is to pass :phones, and then phone as variable to field_for, like is was done here:
<%- #address.phones.each.with_index do |phone, index| %>
<%- f.fields_for :phones, phone do |phone_form| %>
<%- end %>
<%- end %>
Should be resolved as of the 1-st question, since the fields shoudl sent ot server via params not a phone hash, but phones_attributes array of hashes, in order to accepts_nested_attributes_for could accept phones:
phones_attributes: [{ ... },{ ... }]

Updating comments and state from the same form

I'm trying to build a small expense tracking app using Rails 4.1. When a user submits the expense request, it's state is marked as pending by default. The admin has to approve the request. I'm using state_machine gem to do this.
I just added comment functionality using acts_as_commentable gem, which works fine on its own. I wanted to combine the approval drop down and the comment box in the same form and used the following code in the expense show page:
<div class="row">
<div class="col-md-8">
<%= form_for [#expense, Comment.new] do |f| %>
<div class="form-group">
<%= f.label :state %><br />
<%= f.collection_select :state, #expense.state_transitions, :event, :human_to_name, :include_blank => #expense.human_state_name, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :comment %><br />
<%= f.text_area :comment, class: "form-control" %>
</div>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
</div>
</div>
<br>
The problem is I get the "NoMethodError in Expenses#show - undefined method `state' for #". Is there a way I can update both the approval status and comment in one go?
The updated show page with nested attributes:
<div class="row">
<div class="col-md-8">
<%= nested_form_for (#expense) do |f| %>
<div class="form-group">
<%= f.label :state %><br />
<%= f.collection_select :state, #expense.state_transitions, :event, :human_to_name, :include_blank => #expense.human_state_name, class: "form-control" %>
</div>
<%= f.fields_for :comments do |comment| %>
<div class="form-group">
<%= comment.label :comment%>
<%= comment.text_area :comment, class: "form-control" %>
</div>
<% end %>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
</div>
</div>
Nested attributes are your friend. They are so easy to implement I'd recommend avoiding acts_as_commentable to remove an unnecessary dependency and so you understand what's going on.
Use them like this:
# expense.rb
class Expense < ActiveRecord::Base
has_many :comments # << if polymorphic add `, as: :commentable`
accepts_nested_attributes_for :comments
end
# expenses_controller.rb
def new
#expense = Expense.new
#expense.comments.build
end
# expenses/new.html.haml
= form_for(#expense) do |f|
- # expense inputs...
= f.nested_fields_for(:comments) do |comment|
= comment.text_area(:body)
= f.submit
There are many options, so check the docs for more details (they're quite good).

Rails model associations and relationships

I'm new in rails and currently trying to create an app but I can't seem to make it work. Here's my setup in model.
class User < ActiveRecord::Base
has_one :doctor, dependent: :destroy
accepts_nested_attributes :doctor
end
class Doctor < ActiveRecord::Base
belongs_to :user, :dependent => :destroy
end
In my users_controller, here's my code:
class UsersController < ApplicationController
def show
#user = current_user
# render text: #user.inspect
end
def new
#user = User.new
#user.build_doctor`
end
def create
# binding.pry
#user = User.new(user_params)
if #user.save
sign_in #user
redirect_to dashboard_path
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:role, :lastname, :firstname, :middlename, :email, :password, :password_confirmation, :doctor_attributes => [:institution, :license_number])
end
end
And my view:
<ul id="cbp-bislideshow" class="cbp-bislideshow">
<li>
<%= image_tag "blur1.jpg" %>
</li>
<li>
<%= image_tag "blur2.jpg" %>
</li>
</ul>
<% provide(:title, 'Sign Up') %>
<%= form_for(#user) do |f| %>
<div class="sign-up-wrapper divided-wrapper cf">
<div class="left-section">
<h3 class="section-title">JOIN US AND LET'S CHANGE THINGS</h3>
<div class="row">
<div class="w49 pull-left">
<%= f.text_field :firstname, class: "input-text personal ", placeholder: 'FIRSTNAME' %>
</div>
<div class="w49 pull-right">
<%= f.text_field :lastname, class: "input-text personal", placeholder: 'LASTNAME' %>
</div>
<%= f.hidden_field :role, value: :doctor %>
</div>
<div class="row">
<%# f.text_field :specialization, class: "input-text personal ", placeholder: 'SPECIALIZATION' %>
</div>
<%= f.fields_for :doctors do |p| %>
<div class="row">
<%= p.text_field :institution, class: "input-text personal ", placeholder: 'INSTITUTION' %>
</div>
<div class="row">
<%= p.text_field :license_number, class: "input-text personal ", placeholder: 'LICENSE NUMBER' %>
</div>
<% end %>
<span class="remind bottom-message"> ONCE INSIDE DON'T FORGET TO UPDATE YOUR PROFILE WITH MORE DETAILS </span>
</div>
<div class="right-section">
<h3 class="section-title"></h3>
<div class="row">
<%= f.text_field :email, class: "input-text personal ", placeholder: 'EMAIL' %>
</div>
<div class="row">
<%= f.password_field :password, class: "input-text personal ", placeholder: 'PASSWORD' %>
</div>
<div class="row">
<%= f.password_field :password_confirmation, class: "input-text personal ", placeholder: 'CONFIRM PASSWORD' %>
</div>
<div class="row cf">
<%= f.submit class: 'btn-join btn', value: 'JOIN NOW' %>
</div>
<div class="row">
SIGN UP WITH FACEBOOK / TWITTER ACCOUNT?
</div>
</div>
</div>
<% end %>
Everytimie I execute these pieces, only the user model gets populated but not the doctors table? Is there something wrong on my code?
EDIT
Changed doctors_attributes to doctor_attributes
changed #user.doctor.build`to #user.build_doctor
In the logs. I saw this error ---> Unpermitted parameters: doctors
So in theory, I think we know what's the problem, but I don't know how to fix this in the strong_parameters. Haven't tried a strong_parameter with accepted_nested_attributes_for in rails yet and this is my first time. Any solution?
In the fields_for, replace :doctors with :doctor. Remember that you're doing a 1 to 1 relationship.
In your user_params model, the attribute doctors_attributes should be doctor_attributes since it's a has_one relationship. If it was a has_many relationship, it would be doctors_attributes. The part before _attributes would be whatever the association is named.
Another note: If you want to be able to update the doctor from the user form, you should also include the id in the doctor_attributes array. Though now that I think of it, it might only be a requirement on has_many nested associations. I've never tried doing a has_one without including the id.

Resources