How to fix level.rb to work with :committed days? - ruby-on-rails

Originally I had :committed days working beautifully, but upon changing up the models a bit in order to accommodate the User's ability to check off if he missed a :committed day I now get an error message for the code relating to :committed:
undefined method to_date for nil:NilClass
Line #30 n_days = ((date_started.to_date)..Date.today).count { |date| committed_wdays.include? date.wday }
This code comes from the habit model:
class Habit < ActiveRecord::Base
belongs_to :user
has_many :levels
has_many :days, through: :levels #for being able to access Habit.find(*).days
accepts_nested_attributes_for :levels, :days
before_save :set_level
acts_as_taggable
serialize :committed, Array
def evaluate(user)
levels.each { |level| level.evaluate }
user.missed_levels << levels.where(passed: false).ids
user.missed_days << days.where(missed: true).ids
user.save
end
def self.committed_for_today
today_name = Date::DAYNAMES[Date.today.wday].downcase
ids = all.select { |h| h.committed.include? today_name }.map(&:id)
where(id: ids)
end
def levels
committed_wdays = committed.map { |day| Date::DAYNAMES.index(day.titleize) }
n_days = ((date_started.to_date)..Date.today).count { |date| committed_wdays.include? date.wday }
case n_days
when 0..9
1
when 10..24
2
when 25..44
3
when 45..69
4
when 70..99
5
else
"Mastery"
end
end
private
def set_level
self.level = levels
end
end
The logic behind it all is that a User creates a habit he wants to challenge. To achieve "mastery" in the habit he must complete 5 levels. Each level has a certain amount of :committed days that must be completed before advancing, as broken down above with n_days.
The User commits in the _form to what days (Sun thru Sat) he wants to do the habit. For example he could just choose sun, wed, sat. Then the app should only calculate n_days according to non-:missed :committed days (once 10 of those days passes it moves onto the 2nd level).
class Level < ActiveRecord::Base
belongs_to :habit
belongs_to :user
has_many :days
accepts_nested_attributes_for :days
def evaluate
if days.where(missed: true ).count == days_needed
update_attributes(passed: false)
else
update_attributes(passed: true)
end
end
end
class Day < ActiveRecord::Base
belongs_to :level
belongs_to :habit
end
class HabitsController < ApplicationController
before_action :set_habit, only: [:show, :edit, :update, :destroy]
before_action :logged_in_user, only: [:create, :destroy]
def index
if params[:tag]
#habits = Habit.tagged_with(params[:tag])
else
#habits = Habit.all.order("date_started DESC")
#habits = current_user.habits
end
end
def show
end
def new
#goal = current_user.goals.build
#habit = current_user.habits.build
#level = current_user.levels.build
3.times { #level.days.build }
end
def edit
end
def create
#habit = current_user.habits.build(habit_params)
#levels = #habit.levels
if #habit.evaluate(#user)
redirect_to #habit, notice: 'Habit was successfully created.'
else
#feed_items = []
render 'pages/home'
end
end
def update
if #habit.update(habit_params)
redirect_to #habit, notice: 'Habit was successfully updated.'
else
render action: 'edit'
end
end
def destroy
#habit.destroy
redirect_to habits_url
end
private
def set_habit
#habit = Habit.find(params[:id])
end
def correct_user
#habit = current_user.habits.find_by(id: params[:id])
redirect_to habits_path, notice: "Not authorized to edit this habit" if #habit.nil?
end
def habit_params
params.require(:habit).permit(
:user_id,
:level,
:left,
:date_started,
:trigger,
:target,
:positive,
:negative,
:tag_list,
:committed => [],
:levels_attributes => [
:passed,
:days_attributes => [
:missed,:level_id]])
end
end
<%= simple_form_for(#habit) do |f| %>
<%= f.error_notification %>
<div class="america">
<form>
<div class="committed">
<%= f.label "Committed to:" %>
<%= f.collection_check_boxes :committed, Date::DAYNAMES, :downcase, :to_s %>
</div>
<p>
<div class="date-group">
<label> Started: </label>
<%= f.date_select :date_started, :order => [:month, :day, :year], class: 'date-select' %>
</div>
</p>
<p>
<%= f.text_field :trigger, class: 'form-control', placeholder: 'Enter Trigger' %></p>
<p>
<%= f.text_field :tag_list, habit: #habit.tag_list.to_s.titleize, class: 'form-control', placeholder: 'Enter Action' %>
</p>
<p>
<%= f.text_field :target, class: 'form-control', placeholder: 'Enter Target' %>
</p>
<p>
<%= f.text_field :positive, class: 'form-control', placeholder: 'Enter Reward' %>
</p>
<% 5.times.each_with_index do |number, index| %>
<h1>Level <%= index + 1 %></h1>
<%= f.fields_for :levels do |level| %>
<%= level.fields_for :days do |day| %>
<%= day.label :missed %>
<%= day.check_box :missed %> <br/>
<% end %>
<% end %>
<% end %>
<div class="america2">
<%= button_tag(type: 'submit', class: "btn") do %>
<span class="glyphicon glyphicon-plus"></span>
<% end %>
<%= link_to habits_path, class: 'btn' do %>
<span class="glyphicon glyphicon-chevron-left"></span>
<% end %>
<%= link_to #habit, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn' do %>
<span class="glyphicon glyphicon-trash"></span>
<% end %>
</div>
</form>
</div>
<% end %>
<!-- Default bootstrap panel contents -->
<div id="valuations" class="panel panel-default">
<div class="panel-heading"><h4><b>HABITS</b></h4></div>
<!-- Table -->
<table>
<thead>
<tr>
<th>Level</th>
<th>Left</th>
<th>Strike</th>
<th>Trigger</th>
<th>Action</th>
<th>Target</th>
<th>Reward</th>
<th>Days</th>
</tr>
</thead>
<tbody>
<% #habits.each do |challenged| %>
<tr>
<td><%= challenged.level %></td>
<td><%= challenged.left %></td>
<td>
<%= link_to edit_habit_path(challenged) do %>
<%= [params[:missed]].flatten.length %>
<% end %></td>
<td><%= challenged.trigger %></td>
<td class="category">
<b><%= raw challenged.tag_list.map { |t| link_to t.titleize, taghabits_path(t) }.join(', ') %></b>
</td>
<td><%= challenged.target %></td>
<td><%= challenged.positive %></td>
<td class= "committed">
<%= challenged.committed.map { |d| d.titleize[0,3] }.join ', ' %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
Thank you so much for your help!
Some of this code came from this answer here: How to integrate :missed days with :committed days in habits.rb? which messed up what worked with this answer: How to Make :level Change Based on :committed Days?

It appears that date_started is an attribute of your Habit model, probably a database column, and that there are NULLs in date_started. Open up your Rails console and see if this is the case with:
Habit.where(date_started: nil).count
If you expect that date_started should never be null, add a validation to ensure that is the case. As soon as you test the code which is saving nulls into that column, the validation errors will point you to the bug.
On the other hand, if you want to allow nulls in date_started, then rewrite your levels method to allow for that.

Related

Rails 5: Displaying object value not ID

I have a simple app for a skydiving dropzone. Parachute packers keep track of their packsjobs. There are several packjobs for each parachute rig.
I have the Show view working perfectly by showing the rig_type_number under the rig detail (ie Reflex #2) but I can only get the rig_id to work in the same column for the index. Ideally, I'd like to so the rig_type_number as well instead of the ID.
How can I reference in the view something to the effect of #rigs.rig_type_number?
This makes sense to me, but does not work:
<td><%= link_to packjob.rig_id,rig_path(rig.rig_type_number) %>
Will I have to a where clause for the index controller?
db:
class CreatePackjobs < ActiveRecord::Migration[5.1]
def change
create_table :packjobs do |t|
t.string :packer
t.string :rig
t.references :rig, foreign_key: true
t.timestamps
end
end
end
class CreateRigs < ActiveRecord::Migration[5.1]
def change
create_table :rigs do |t|
t.boolean :rig_status
t.string :rig_type_number
t.integer :rig_season_jumpnum
t.date :rig_res_last
t.string :rig_res_who
t.timestamps
end
end
end
packjobs_controller:
class PackjobsController < ApplicationController
def index
#packjobs = Packjob.paginate(page: params[:page]).order('id DESC')
#rigs = Rig.where(rig_status: "t")
end
def show
#packjob = Packjob.find(params[:id])
#rig = Rig.find(#packjob.rig_id)
end
def new
#packjob = Packjob.new
#rigs = Rig.where(rig_status: "t")
end
def edit
#packjob = Packjob.find(params[:id])
#rigs = Rig.where(rig_status: "t")
end
def create
#packjob = Packjob.new(packjob_params)
#rigs = Rig.where(rig_status: "t")
if #packjob.save
redirect_to #packjob
else
render 'new'
end
end
def update
#packjob = Packjob.find(params[:id])
#rigs = Rig.where(rig_status: "t")
if #packjob.update(packjob_params)
redirect_to #packjob
else
render 'edit'
end
end
def destroy
#packjob = Packjob.find(params[:id])
#packjob.destroy
redirect_to packjobs_path
end
private
def packjob_params
params.require(:packjob).permit(:packer, :rig_id)
end
def rigs_params
params.require(:rig).permit(:rig_status, :rig_type_number)
end
end
show.html.erb:
<p>
<b>Datestamp:</b>
<%= #packjob.created_at.strftime("%m/%d/%Y %I:%M %P") %><br>
</p>
<p>
<strong>Packer:</strong>
<%= #packjob.packer %>
</p>
<p>
<strong>Rig:</strong>
<%= #rig.rig_type_number %><br>
</p>
<%= link_to 'Edit', edit_packjob_path(#packjob) %> |
<%= link_to 'Back', packjobs_path %>
index.html.erb:
<h1>Listing Packjobs</h1>
<%= link_to 'New Packjob', new_packjob_path %> | <br>
<br>
<div class="digg_pagination">
<%= will_paginate #packjobs, :container => false %>
</div>
<table id=listtable CELLPADDING="4" border="1">
<tr class="headerBlue" >
<th>Datestamp</th>
<th>Packer</th>
<th>Rig</th>
<th colspan="3"></th>
</tr>
<% #packjobs.each do |packjob| %>
<tr class="<%= cycle('rowA', 'rowB') %>">
<td><%= link_to packjob.created_at.strftime("%m/%d/%Y %I:%M:%S %P"),packjob_path(packjob.id) %></td>
<td><%= packjob.packer %></td>
<td><%= link_to packjob.rig_id,rig_path(packjob.rig_id) %>
<td><%= link_to 'Show', packjob_path(packjob) %></td>
<td><%= link_to 'Edit', edit_packjob_path(packjob) %></td>
<td><%= link_to 'Destroy', packjob_path(packjob),
method: :delete,
data: { confirm: 'Are you sure?' } %></td>
<% end %>
</tr>
</table>
<div class="digg_pagination">
<div class="page_info">
<%= page_entries_info #packjobs %>
</div>
<%= will_paginate #packjobs, :container => false %>
</div>
<br><%= link_to 'New Packjob', new_packjob_path %> |
EDITED:
models:
class Packjob < ApplicationRecord
belongs_to :rig
validates :packer, presence: true
validates :rig_id, presence: true
self.per_page = 25
end
class Rig < ApplicationRecord
has_many :packjobs
validates :rig_type_number, presence: true
self.per_page = 25
end
Your associations are set correctly, you can reference the associated object like this:
<td><%= link_to packjob.rig.rig_type_number,rig_path(packjob.rig_id) %>
You can call it as below in case you have has_one :rig association in PackJob model :
<td><%= link_to packjob..rig.rig_type_number,rig_path(packjob.rig_id) if packjob.rig.present? %> </td>

How to stop double rendering in sidebar?

The code is double rendering like so:
when it should just list it out once like so:
Ran 1 miles Apr
Journal 1 days Apr
views/layouts/_stats.html.erb
<% #averaged_quantifieds.each do |averaged| %>
<% averaged.results.each do |result| %>
<div class="<%= result.good? ? 'green' : 'red' %>">
<li>
<%= raw averaged.tag_list.map { |t| link_to t.titleize, tag_path(t) }.join(', ') %><%= link_to edit_quantified_path(averaged) do %> <%= averaged.results.first.result_value %> <%= averaged.metric %> <span class="<%= date_value_label_class(result) %>"> <%= averaged.results.first.date_value.strftime("%b") %></span><% end %>
</li>
</div>
<% end %>
<% end %>
application_controller
def set_stats
#averaged_quantifieds = current_user.quantifieds.averaged if current_user
#instance_quantifieds = current_user.quantifieds.instance if current_user
end
Results are a nested_attribute to Quantifieds.
quantifieds_controller
class QuantifiedsController < ApplicationController
before_action :set_quantified, only: [:show, :edit, :update, :destroy]
before_action :logged_in_user, only: [:create, :destroy]
def index
if params[:tag]
#quantifieds = Quantified.tagged_with(params[:tag])
else
#quantifieds = Quantified.joins(:results).all
#averaged_quantifieds = current_user.quantifieds.averaged
#instance_quantifieds = current_user.quantifieds.instance
end
end
def show
end
def new
#quantified = current_user.quantifieds.build
end
def edit
end
def create
#quantified = current_user.quantifieds.build(quantified_params)
if #quantified.save
redirect_to quantifieds_url, notice: 'Quantified was successfully created'
else
#feed_items = []
render 'pages/home'
end
end
def update
if #quantified.update(quantified_params)
redirect_to quantifieds_url, notice: 'Goal was successfully updated'
else
render action: 'edit'
end
end
def destroy
#quantified.destroy
redirect_to quantifieds_url
end
private
def set_quantified
#quantified = Quantified.find(params[:id])
end
def correct_user
#quantified = current_user.quantifieds.find_by(id: params[:id])
redirect_to quantifieds_path, notice: "Not authorized to edit this goal" if #quantified.nil?
end
def quantified_params
params.require(:quantified).permit(:categories, :metric, :date, :comment, :private_submit, :tag_list, results_attributes: [:id, :result_value, :date_value, :good, :_destroy])
end
end
quantified.rb
class Quantified < ActiveRecord::Base
belongs_to :user
has_many :results #correct
has_many :comments, as: :commentable
accepts_nested_attributes_for :results, :reject_if => :all_blank, :allow_destroy => true #correct
scope :averaged, -> { where(categories: 'Averaged') }
scope :instance, -> { where(categories: 'Instance') }
scope :private_submit, -> { where(private_submit: true) }
scope :public_submit, -> { where(private_submit: false) }
validates :categories, :metric, presence: true
acts_as_taggable
CATEGORIES = ['Averaged', 'Instance']
end
result.rb
class Result < ActiveRecord::Base
belongs_to :user
belongs_to :quantified
has_many :comments, as: :commentable
default_scope { order('date_value DESC') }
scope :good, -> { where(good: true) }
scope :good_count, -> { good.count }
end
The issue came about when trying to introduce differing font colors for results. To make that possible I had to introduce these two lines which are causing the double rendering: <% averaged.results.each do |result| %> <div class="<%= result.good? ? 'green' : 'red' %>">
Thank you for your time and expertise.
You should explain more about the logic and the data stored.
A guess is that there's two records in #averaged_quantifieds and three in averaged.results. It is hard to determine the desired results without knowing the data stored.
Note that you are only displaying the firsts records results (averaged.results.first) in the <%= raw ... line
Try
<% #averaged_quantifieds.each do |averaged| %>
<div class="<%= averaged.results.first.good? ? 'green' : 'red' %>">
<li>
<%= raw averaged.tag_list.map { |t| link_to t.titleize, tag_path(t) }.join(', ') %><%= link_to edit_quantified_path(averaged) do %> <%= averaged.results.first.result_value %> <%= averaged.metric %> <span class="<%= date_value_label_class(result) %>"> <%= averaged.results.first.date_value.strftime("%b") %></span><% end %>
</li>
</div>
<% end %>
Edit: My bad, I missed one result object (<%= date_value_label_class(result) %>) hiding in the rest of the line
Change result to averaged.results.first wherever applicable
<% #averaged_quantifieds.each do |averaged| %>
<div class="<%= averaged.results.first.good? ? 'green' : 'red' %>">
<li>
<%= raw averaged.tag_list.map { |t| link_to t.titleize, tag_path(t) }.join(', ') %><%= link_to edit_quantified_path(averaged) do %> <%= averaged.results.first.result_value %> <%= averaged.metric %> <span class="<%= date_value_label_class(averaged.results.first) %>"> <%= averaged.results.first.date_value.strftime("%b") %></span><% end %>
</li>
</div>
<% end %>

How to Order Nested Attribute according to its Date?

How can we DESC order results according to its :date_value in the quantifieds index?
Results being the nested attribute to quantifieds.
Right now the order is according to where the User added the result in the form, regardless of :date_value.
This has proven more difficult than I would have guessed.
class QuantifiedsController < ApplicationController
before_action :set_quantified, only: [:show, :edit, :update, :destroy]
before_action :logged_in_user, only: [:create, :destroy]
def index
if params[:tag]
#quantifieds = Quantified.tagged_with(params[:tag])
else
#quantifieds = Quantified.joins(:results).all
#averaged_quantifieds = current_user.quantifieds.averaged
#instance_quantifieds = current_user.quantifieds.instance
end
end
def show
end
def new
#quantified = current_user.quantifieds.build
end
def edit
end
def create
#quantified = current_user.quantifieds.build(quantified_params)
if #quantified.save
redirect_to quantifieds_url, notice: 'Quantified was successfully created'
else
#feed_items = []
render 'pages/home'
end
end
def update
if #quantified.update(quantified_params)
redirect_to quantifieds_url, notice: 'Goal was successfully updated'
else
render action: 'edit'
end
end
def destroy
#quantified.destroy
redirect_to quantifieds_url
end
private
def set_quantified
#quantified = Quantified.find(params[:id])
end
def correct_user
#quantified = current_user.quantifieds.find_by(id: params[:id])
redirect_to quantifieds_path, notice: "Not authorized to edit this goal" if #quantified.nil?
end
def quantified_params
params.require(:quantified).permit(:categories, :metric, :result, :date, :tag_list, results_attributes: [:id, :result_value, :date_value, :_destroy])
end
end
class Quantified < ActiveRecord::Base
belongs_to :user
has_many :results #correct
accepts_nested_attributes_for :results, :reject_if => :all_blank, :allow_destroy => true #correct
scope :averaged, -> { where(categories: 'Averaged') }
scope :instance, -> { where(categories: 'Instance') }
validates :categories, :metric, presence: true
acts_as_taggable
CATEGORIES = ['Averaged', 'Instance']
end
class Result < ActiveRecord::Base
belongs_to :user
belongs_to :quantified
end
class CreateQuantifieds < ActiveRecord::Migration
def change
create_table :quantifieds do |t|
t.string :categories
t.string :metric
t.references :user, index: true
t.timestamps null: false
end
add_foreign_key :quantifieds, :users
add_index :quantifieds, [:user_id, :created_at]
end
end
class CreateResults < ActiveRecord::Migration
def change
create_table :results do |t|
t.string :result_value
t.date :date_value
t.integer :quantified_id
t.timestamps null: false
end
end
end
form
<%= javascript_include_tag "quantified.js" %>
<%= simple_form_for(#quantified) do |f| %>
<%= f.error_notification %>
<div class="america">
<form>
<% Quantified::CATEGORIES.each do |c| %>
<%= f.radio_button(:categories, c, :class => "date-format-switcher") %>
<%= label(c, c) %>
<% end %>
<br/>
<br/>
<div class="form-group">
<%= f.text_field :tag_list, quantified: #quantified.tag_list.to_s.titleize, class: 'form-control', placeholder: 'Enter Action' %>
</div>
<div class="form-group">
<%= f.text_field :metric, class: 'form-control', placeholder: 'Enter Metric' %>
</div>
<div id="results">
<%= f.fields_for :results do |result| %>
<%= render 'result_fields', :f => result %>
<% end %>
</div>
<div class="links">
<b><%= link_to_add_association 'Add Result', f, :results %></b>
</div>
<div class="america2">
<%= button_tag(type: 'submit', class: "btn") do %>
<span class="glyphicon glyphicon-plus"></span>
<% end %>
<%= link_to quantifieds_path, class: 'btn' do %>
<span class="glyphicon glyphicon-chevron-left"></span>
<% end %>
<%= link_to #quantified, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn' do %>
<span class="glyphicon glyphicon-trash"></span>
<% end %>
</div>
</form>
</div>
<% end %>
index
<!-- Default bootstrap panel contents -->
<div id="valuations" class="panel panel-default">
<div class="panel-heading"><h4><b>AVERAGE</b></h4></div>
<% #averaged_quantifieds.each do |averaged| %>
<div class="attempt">
<b><%= raw averaged.tag_list.map { |t| link_to t.titleize, tagquantifieds_path(t) }.join(', ') %>
<%= link_to edit_quantified_path(averaged) do %>
(<%= averaged.metric %>)</b>
<% end %>
<ul>
<% averaged.results.each do |result| %>
<li>
<b><%= result.result_value %></b>
<%= result.date_value.strftime("%b %Y") %>
</li>
<% end %>
</ul>
</div>
<% end %>
</div>
<div class="valuations-button">
<%= link_to new_quantified_path, class: 'btn' do %>
<b><span class="glyphicon glyphicon-plus"</span></b>
<% end %>
</div>
<br>
<!-- Default bootstrap panel contents -->
<div id="valuations" class="panel panel-default">
<div class="panel-heading"><h4><b>INSTANCE</b></h4></div>
<% #instance_quantifieds.each do |instance| %>
<div class="attempt">
<b><%= raw instance.tag_list.map { |t| link_to t.titleize, tagquantifieds_path(t) }.join(', ') %>
<%= link_to edit_quantified_path(instance) do %>
(<%= instance.metric %>)</b>
<% end %>
<ul>
<% instance.results.each do |result| %>
<li>
<%= result.date_value.strftime("%b.%d.%y") %>
<%= result.result_value %>
</li>
<% end %>
</ul>
</div>
<% end %>
</div>
<div class="valuations-button">
<%= link_to new_quantified_path, class: 'btn' do %>
<b><span class="glyphicon glyphicon-plus"</span></b>
<% end %>
</div>
Thanks so much for your time!
Got it! Add default_scope { order('date_value DESC') } in result.rb

Displaying items captured via a nested form

I'm trying to build a small expense tracking app. Using the nested_form gem to add line items. There is an Expense model which accepts nested attributes. Items belong to expenses and there is a foreign key association. Here's the expense controller:
class ExpensesController < ApplicationController
def new
#expense = Expense.new
#item = #expense.items.build
end
def index
#expenses = Expense.all
##items = Item.where(:expense_id => #expense.id)
end
def show
#expense = Expense.find(params[:id])
#items = Item.where(:expense_id => #expense.id)
end
def create
#expense = Expense.new(expense_params)
respond_to do |format|
if #expense.save
format.html { redirect_to #expense, notice: 'Expense Report Submitted.' }
format.json { render :show, status: :created, location: #expense }
else
format.html { render :new }
format.json { render json: #expense.errors, status: :unprocessable_entity }
end
end
end
def edit
#expense = Expense.find(params[:id])
end
def update
#expense = Expense.find(params[:id])
if #expense.save(expense_params)
flash[:notice] = "Expense Report Updated"
redirect_to #expense
else
render 'edit'
end
end
def destroy
#expense = Expense.find(params[:id])
#expense.destroy
redirect_to 'root'
end
private
def expense_params
params.require(:expense).permit(:department_id, :expense_type_id, :notes, items_attributes: [:id, :description, :amount, :issue_date, :_destroy])
end
end
The form looks like:
<%= nested_form_for (#expense) do |f| %>
<% if #expense.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#expense.errors.count, "error") %> prohibited
this expense from being saved:</h2>
<ul>
<% #expense.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class"row">
<div class="col-md-8">
<div class="form-group">
<%= f.label :department_id %><br>
<%= f.collection_select(:department_id, Department.all, :id, :department_name, prompt: true, class: "dropdown-menu") %>
</div>
<div class="form-group">
<%= f.label :expense_type_id %><br>
<%= f.collection_select(:expense_type_id, ExpenseType.all, :id, :expense_name, prompt: true, class: "form-control") %>
</div>
<%= f.fields_for :items do |i| %>
<div class="form-group">
<%= i.label :description%>
<%= i.text_field :description, class: "form-control" %>
</div>
<div class="form-group">
<%= i.label :amount%>
<%= i.text_field :amount, class: "form-control" %>
</div>
<div class="form-group">
<%= i.label :issue_date%>
<%= i.date_select :issue_date, class: "form-control" %>
</div>
<%= i.link_to_remove "Remove", class: "btn btn-default" %>
<% end %>
<div><p><%= f.link_to_add "Add Expense", :items, class: "btn btn-default" %></p></div>
<div class="form-group">
<%= f.label :notes %>
<%= f.text_area :notes, class: "form-control" %>
</div>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
</div>
</div>
When I hit submit, the expense and items are saved. I checked with Sqlite browser and the foreign key values are captured for each item.
The index file looks like:
<% #expenses.each do |expense| %>
<tr>
<td><%= expense.item.description %></td>
<td><%= number_to_currency(expense.item.amount) %></td>
<td><%= expense.item.issue_date %></td>
<% end %>
I tried the usual combinations (like expense.item.description) by passing through a block, but they aren't working. I would like to know how to display the expense and the associated items in the show and index pages.
Looking at your new action, in your models you would have
class Expense < ActiveRecord::Base
has_many :items
accepts_nested_attributes_for :items
end
So when you are doing expense.items in your view it gives you an active record relation(since expense has many items), try this:
<% #expenses.each do |expense| %>
<% expense.items.each do |item| %>
<tr>
<td><%= item.description %></td>
<td><%= number_to_currency(item.amount) %></td>
<td><%= item.issue_date %></td>
</tr>
<% end %>
<% end %>

ActiveSupport::HashWithIndifferentAccess

My contorller is like this
class FriendController < ApplicationController
def friend_list
#user = User.new
end
def be_mine_friend
#user = params[:user]
if #user.save?
redirect_to friend_mine_friend_url
flash[:notice] = "#{#user[:name]} have been added to my friend list"
else
redirect_to friend_friend_list_path
end
end
def mine_friend
#title = "Details list of Mine Friend"
#friend = #user.paginate(page: params[:page], per_page: 10)
respond_to do |format|
format.html
format.json { render json: #friend }
end
end
end
View page for friend_list
<div class="container">
<%= notice %>
<%#= errors %>
<%= form_for(#user, url: friend_be_mine_frien_path) do |user| %>
<%= user.text_field 'name', placeholder: "Your name Please" %></br>
<%= user.text_field 'email', placeholder: "Your Email Please" %></br>
<%= user.text_field 'address', placeholder: "Your Address Please" %></br>
<%= user.submit "Be Mine Friend", class: "btn btn-primary" %>
<% end %>
</div>
view page for mine_friend
<div class="container">
<p><strong><%= #title %></strong><p>
<%= notice %>
<%= will_paginate #friend, previous_label: "<<", next_label: ">>", class: "pagination pagination-large" %>
<table class="table table table-striped">
<tr>
<th>Name</th>
<th>Address</th>
<th>Email</th>
</tr>
<% #friend.each do |friend| %>
<tr>
<td><%= friend.name %></td>
<td><%= friend.address %></td>
<td><%= friend.email %></td>
</tr>
<% end %>
</table>
</div>
and model is
class User < ActiveRecord::Base
attr_accessible :address, :email, :message, :name
validates :address, :email, :message, :name, presence: :true
end
I while I try to save user from friend_list I get such
Processing by FriendController#be_mine_friend as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"5A1dXtuYJpfqpOphkdl+WA657T3ok2zu/8U1v1B8tEg=", "user"=>{"name"=>"Amritdeep", "email"=>"amritdeepdhungana#hotmail.com", "address"=>"Bou"}, "commit"=>"Be Mine Friend"}
Completed 500 Internal Server Error in 1ms6090>:
the error is
NoMethodError - undefined method `save?' for #<ActiveSupport::HashWithIndifferentAccess:0x00000003c06090>:
What should I do now? Do you guys have any solution for it? I don't know why this ActiveSupport::HashWithIndifferentAccess error is following. Do you guys have any idea about it?
#user = params[:user]
if #user.save?
The params[:user] is a hash. it is not a user object. This is the norm:
#user = User.create(params[:user])

Resources