Can we manually add one entry into dynamic drop down list, If then how in Ruby On Rails - ruby-on-rails-3.1

I have a student, student_parent and address_detail table i want to add student and it's parent(Father and Mother) address in address_detail table, I have folowing relation between tables
Student:-
has_many :student_parents
has_many :address_details
Student_parent:
belongs_to :student
has_many :address_detail
address_detail:
belongs_to :student
belongs_to :student_parent
In address_detail form i have a drop down for only Father and mother i want to add student entry manually how can i do, Here is my address_detail form``
<%= simple_form_for #address_detail, :html => { :class => 'form-horizontal' } do |f| %>
<div class="control-group">
<label class = "control-label"> Address Correspond To <abbr title="required">*</abbr></label>
<div class="controls">
<%= f.collection_select(:student_parent_id, student_parent_relation_collection , :id, :relation_to_student, {:prompt => true}, :required =>true )%>
<%= f.hidden_field :student_id, :value => current_student_id %>
</div>
</div>
....
.....
Here is my Helper method for Address_correspond_to drop down method
# return collection of parent relation to student
def student_parent_relation_collection
if current_user != nil
student = Student.find_all_by_user_id(current_user.id)
logger.info "student_is = #{student}"
if student != nil
return StudentParent.find_all_by_student_id(student)
end
end
end
current OutPut is
Father
Mother
I want Out
Student
Father
Mother

Class AddressDetail < ActiveRecord::Base
def student_and_parents
[student, student_parent]
end
end
Then, in the view you can either refer to
address_detail.student_and_parents
or in User
Class User < ActiveRecord::Base
has_many :students
has_many :student_parents, :through => :students
def students_and_parents
[students, student_parents].compact.flatten
end
end
you can refer to
current_user.try(:students_and_parents)

if current_user
student = Student.find_by_user_id(current_user.id)
return [student] + student.student_parents if student
end

Related

Unpermitted parameters - Rails 4.1.1, Ruby 2.1.2

I cannot seem to get to the bottom of where I am going wrong. My "order.rb" fields populate ok, but I can't get the "order_row" table values to populate. I just keep getting the following error in terminal(not worried about date for now, should be ok with that)...
Unpermitted parameters: date(i), order_row
Customer model(customer.rb)...
class Customer < ActiveRecord::Base
has_many :orders, dependent: :destroy
end
Order model(order.rb)...
class Order < ActiveRecord::Base
belongs_to :customer
has_many :order_rows, dependent: :destroy
accepts_nested_attributes_for :order_rows
end
Order_Row model(order_row.rb)
class OrderRow < ActiveRecord::Base
belongs_to :order
end
(orders_controller.rb)....
def new
#order = Order.new
end
def create
#order = Order.new(order_params)
respond_to do |format|
if #order.save
format.html { redirect_to(#order, :notice => 'Order was successfully created.') }
else
format.html { render :action => "new" }
end
end
end
private
def order_params
params.require(:order).permit(:customer_id, :date, :total,
:order_row_attributes => [:description, :quantity, :price, :order_id])
end
Form code on new.html.haml
= semantic_form_for #order do |f|
= f.input :customer_id, :as => :select, :collection => Hash[Customer.all.map{|c| [c.company,c.id]}]
= f.input :date
= f.fields_for :order_row do |ff|
= ff.input :description
= ff.input :quantity
= ff.input :price
= ff.hidden_field :order_id
= f.input :total
= f.action :submit, :as => :button
The problem is this line order_row_attributes.It should be order_rows_attributes. And with the date not being permitted,try changing the date attribute to some name like order_date.
This should work
private
def order_params
params.require(:order).permit(:customer_id, :order_date, :total,
:order_rows_attributes => [:description, :quantity, :price, :order_id])
end
I got it working by changing the new method to....
def new
#order = Order.new
#order.order_rows.build
end
So combination of this and Pavans answer did the trick.

Subscribed Members can Unlock Un-released Books

I've created an App where a signed up Members can access our Library of Books. If the Book's release_date is greater than today's date. Members have the ability to purchase an Unreleased Book & Unlock It(Early Bird Special).
But if the Unreleased Book has not been purchased, I would like to display it as Coming Soon.
I am having trouble creating a method/view that will help me display our Regular Books, Unreleased Books, & Purchased Books to a current_user.
My Code is Below, any help will be greatly appreciated.
VIEWS
<% if current_user.member? %>
<% #books.each do |book| %>
<% if book.unreleased_book %>
###I am having trouble getting this conditional or loop to work
<% if current_user has purchased the book %>
LIST ALL PURCHASED BOOKS
<% end %>
<% if current_user has not purchased the book %>
LIST ALL UNRELEASED BOOKS
<% end %>
<% elsif book.release_date <= Date.today %>
LIST ALL AVAILABLE BOOKS
<% end %>
<% else %>
DISPLAY ALL BOOKS AS STATIC
<% end %>
MODELS
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :member
has_many :books, through: :orders
has_many :orders, :dependent => :destroy
end
class Order < ActiveRecord::Base
attr_accessible :book_id, :order_date, :user_id
belongs_to :user
belongs_to :book
end
class Book < ActiveRecord::Base
attr_accessible :description, :pages, :title, :available_in, :price, :release_date
has_many :orders
has_many :users, through: :orders
###Definition of unreleased books
def unreleased_book
Date.today < self.release_date
end
end
CONTROLLER
class BooksController < ApplicationController
def index
#books = Book.all
#orders = current_user.orders
respond_to do |format|
format.html
format.json { render :json => #issues }
end
end
end
SCHEMA
create_table "users", :force => true do |t|
t.string "name"
t.string "email"
t.boolean "member", :default => false ###Becomes Member on SignUp
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "orders", :force => true do |t| ###Created when Purchased a BOOK
t.integer "user_id"
t.integer "book_id"
t.date "order_date"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "books", :force => true do |t|
t.string "title"
t.string "pages"
t.text "description"
t.decimal "price", :precision => 8, :scale => 2
t.date "release_date" ###If Release_Date > Time.Now then Book is Unreleased
t.datetime "created_at", :null => false
t.datetime "updated_at",
end
I think your model relations are a bit off. Here is my suggestion:
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :member
has_many :orders # a user typically can have many orders
end
class Order < ActiveRecord::Base
attr_accessible :book_id, :order_date, :user_id
belongs_to :user #each order belongs to a single user
has_many :books # one order can have consist of many books
end
class Book < ActiveRecord::Base
attr_accessible :description, :pages, :title, :available_in, :price, :release_date
belongs_to :order
has_many :users, through: order # since a book belongs to an order and an order belongs to a user, a book has many users goes the logic
end
Move the logic in your view to a help. consider using the case expression. This helper will give you an outline.
module BooksHelper
ActionView::Helpers::UrlHelper #this will give access to Url helpers
def purchases(book)
case book
when book.unreleased_book
link_to path_to_new_action #configure this path depending on how you set up your routes.
when current_user has purchased the book
#LIST ALL PURCHASED BOOKS
when current_user has_not purchased the book
#LIST ALL UNRELEASED BOOKS
when book.release_date <= Date.today
#LIST ALL AVAILABLE BOOKS
else
#DISPLAY ALL BOOKS AS STATIC
end
end
then in your VIEWS, render the helper like this.
<% if current_user.member? %>
<% #books.each do |book| %>
<%= purchases(book) %>
<% end %>
This will keep your views clean.
books controller:
since you changed your models associations, you need to tweak your controllers.
First, load the order (a specific order) by id. Then, since order has_many :books, find all the books associated with that order.
def index
#order = Order.find(params[:order_id])
#books = #orders.books
end
or if you have defined the current_user.orders, then you can do #orders = current_user.orders. but the way you have it now, the first line is not doing anything

Update multiple records using one form

I have a following situation: user has multiple assets and each asset has one asset_detail record.
Models:
class User < ActiveRecord::Base
has_many :assets
end
class Asset < ActiveRecord::Base
has_one :asset_detail
belongs_to :user
accepts_nested_attributes_for :asset_detail,
:allow_destroy => false
attr_accessible # ...
end
class AssetDetail < ActiveRecord::Base
belongs_to :asset
attr_accessible # ...
end
Controller actions:
def edit
#user = current_user
#assets = Asset.all
end
def update
#user = current_user
#user.update_attributes(params["user"])
end
View:
= form_for #user, url: 'update action url' do |f|
= f.fields_for :assets do |ff|
= ff.text_field :title
= ff.fields_for :asset_detail do |fff|
= fff.text_field :value
The problem is that all the form fields are populated properly but i'm not able to save them. The form is sent without any error but the data is not updated.
I think your models should look like this:
class User < ActiveRecord::Base
attr_accessible :assets_attributes #...
has_many :assets
accepts_nested_attributes_for :assets_attributes
end
class Asset < ActiveRecord::Base
attr_accessible :asset_detail_attrbutes # ...
has_one :asset_detail
belongs_to :user
accepts_nested_attributes_for :asset_detail_attributes,
:allow_destroy => false
end
the reason being, you need to be able to set the attributes via the attributes hash passed to each model. HTH!

How to pass user_id to nested_resource model?

I have a small project setup with devise and cancan. There are User, Project, Responsible and Task Models. Project has nested Tasks. Each Project is assigned to one or multiple users. The task model has a name, user_id and project_id. Authentication and Authorization is working like expected.
When adding a new Task (only an input for name) the project_id gets automatically passed to model/table (i think this is because of routing) but not the user_id.
Do i have to pass the user_id in a hidden_field or is it somehow possible to set this in a before filter?
Can somebody give a hint on howto set user_id in taskcontroller?
Thanks
# Routes
resources :projects do
resources :tasks
end
#Models
class User < ActiveRecord::Base
has_many :responsibilities, :dependent => :destroy
has_many :projects, :through => :responsibilities
has_many :tasks, :dependent => :destroy
...
class Project < ActiveRecord::Base
has_many :tasks, :dependent => :destroy
...
class Task < ActiveRecord::Base
belongs_to :project
belongs_to :user
...
# Tasks Controller with all Task.find/new/update/...
# methods removed like explained in cancan manual
class TasksController < ApplicationController
load_and_authorize_resource :project
load_and_authorize_resource :task, :through => :project
...
def create
respond_to do |format|
if #task.save
format.html { redirect_to [#project, #task], notice: 'created.' }
else
format.html { render action: "new" }
end
end
# Task Form View
<%= semantic_form_for [#project, #task] do |f| %>
<%= f.inputs do %>
<%= f.input :name %>
<% end %>
<%= f.actions %>
<% end %>
Update
It seems to work with a before filter. Is this the right way?
class TasksController < ApplicationController
before_filter :set_user, :only => [:create]
load_and_authorize_resource :client
load_and_authorize_resource :task, :through => :client, :shallow => true
...
def set_user()
params[:task][:user_id] = current_user.id.to_s
end
...
if you are using devise you can just pass in the create action you user_id
def create
#task.user = current_user
respond_to do |format|
if #task.save
format.html { redirect_to [#project, #task], notice: 'created.' }
else
format.html { render action: "new" }
end
end
not quiet sure if this is what you mean

simple_form, bug with :has_many :through relation?

I have 3 models like these:
class CertificatorBtwInstructor < ActiveRecord::Base
belongs_to :certificator
belongs_to :instructor
# other code ...
end
class Certificator < ActiveRecord::Base
has_many :btw_instructors, :class_name => "CertificatorBtwInstructor"
has_many :instructors, :through => :btw_instructors
# other code ...
end
class Instructor < ActiveRecord::Base
has_many :btw_certificators, :class_name => "CertificatorBtwInstructor"
has_many :certificators, :through => :btw_certificators
# other code ...
end
on my Instructor new form I have setting:
= simple_form_for( [:cm, #instructor], :html => { :class => "fAdm" } ) do |f|
= f.object.errors
- others fields ...
= f.input :certificator_ids, :required => false, :collection => Certificator.choices_relation_select, :input_html => { :multiple => true, :size => 12 }
%div.row.buttons
= f.button :submit
then, when i submit the form without select any Certificator from the 'certificator_ids' input collection, the new record is created without problem.
But, when I choose any item on the 'certificator_ids' input collection, an error appear (i visualize it with the = f.object.errors ), and the error is this:
{:certificators=>["is not valid"]}
but on my form i haven't setting the field 'certificators', so I don't undestand why they got this attribute.
Change it to
<%= f.association :certificators, :as => :check_boxes %>
this will show to you all your certificators on check boxes, you should take a look at this
https://github.com/plataformatec/simple_form
and this
http://railscasts.com/episodes/47-two-many-to-many

Resources