I have a Rails app that has "Datapoint" and "Dataset" model objects. Datasets belog to Datapoints.
models/dataset.rb:
# Table name: datasets
#
# id :integer not null, primary key
# name :string(255)
# created_at :datetime
# updated_at :datetime
class Dataset < ActiveRecord::Base
belongs_to :user
validates :name, :presence => true
end
models/datapoint.rb:
# Table name: datapoints
#
# id :integer not null, primary key
# dataset :integer
# date :date
# value :float
# created_at :datetime
# updated_at :datetime
class Datapoint < ActiveRecord::Base
belongs_to :dataset
validates :date, :presence => true
validates :dataset, :presence => true
validates :value, :presence => true
end
My controllers/datapoints_controller.rb successfully saves datapoints records:
class DatapointsController < ApplicationController
def create
#datapoint = Datapoint.new(params[:datapoint])
#datapoint.dataset = Dataset.find(current_user.dataset)
if #datapoint.save
redirect_to root_path
else
end
end
end
However, when I look in my database, the dataset field for each datapoint entry (which is a required foreign key) is empty. How is this possible?
Looks like a bad migration (wrong field name for foreign key):
# Table name: datapoints
# dataset :integer <<<< This should be dataset_id
# date :date
...
Related
I've got this whole surveys thing:
Survey.rb
# frozen_string_literal: true
# == Schema Information
#
# Table name: surveys
#
# id :bigint not null, primary key
# description :string
# hidden :boolean default(FALSE)
# internal_description :string
# internal_name :string
# min_green :integer
# min_orange :integer
# min_red :integer
# required :boolean default(FALSE)
# survey_type :integer default("medical")
# title :string
# created_at :datetime not null
# updated_at :datetime not null
#
class Survey < ApplicationRecord
has_many :questions, class_name: 'Question', dependent: :destroy
has_many :filled_surveys
has_many :study_surveys
has_many :studies, through: :study_surveys
accepts_nested_attributes_for :questions
enum survey_type: %i[medical law]
validates :title, :description, :internal_name, :internal_description, presence: true
end
filled_survey.rb
# frozen_string_literal: true
# == Schema Information
#
# Table name: filled_surveys
#
# id :bigint not null, primary key
# score :integer
# state :integer default("pending")
# created_at :datetime not null
# updated_at :datetime not null
# survey_id :bigint not null
# user_id :bigint not null
#
# Indexes
#
# index_filled_surveys_on_survey_id (survey_id)
# index_filled_surveys_on_user_id (user_id)
#
# Foreign Keys
#
# fk_rails_... (survey_id => surveys.id)
# fk_rails_... (user_id => users.id)
#
class FilledSurvey < ApplicationRecord
belongs_to :survey
has_many :questions, through: :survey
belongs_to :user, class_name: 'User'
has_many :answers, class_name: 'Answer'
accepts_nested_attributes_for :answers
has_one :study, through: :survey
enum state: %i[pending done redo]
end
question.rb
# frozen_string_literal: true
# == Schema Information
#
# Table name: questions
#
# id :bigint not null, primary key
# description :string
# max :integer
# min :integer
# order :integer default(0)
# placeholder :string
# question_type :integer
# title :string
# created_at :datetime not null
# updated_at :datetime not null
# survey_id :bigint not null
#
# Indexes
#
# index_questions_on_survey_id (survey_id)
#
# Foreign Keys
#
# fk_rails_... (survey_id => surveys.id)
#
class Question < ApplicationRecord
belongs_to :survey
has_many :question_options, class_name: 'QuestionOption', dependent: :destroy
has_many :answers, dependent: :destroy
accepts_nested_attributes_for :question_options, allow_destroy: true, reject_if: proc { |att| att['name'].blank? }
enum question_type: %i[short long number single multiple date]
validates :title, presence: true, on: :create
end
question_option.rb
# frozen_string_literal: true
# == Schema Information
#
# Table name: question_options
#
# id :bigint not null, primary key
# display :string
# name :string
# score :integer default(0)
# created_at :datetime not null
# updated_at :datetime not null
# question_id :bigint not null
#
# Indexes
#
# index_question_options_on_question_id (question_id)
#
# Foreign Keys
#
# fk_rails_... (question_id => questions.id)
#
class QuestionOption < ApplicationRecord
belongs_to :question, optional: true
validates :name, :display, :score, presence: true
end
answer.rb
# frozen_string_literal: true
# == Schema Information
#
# Table name: answers
#
# id :bigint not null, primary key
# content :string
# created_at :datetime not null
# updated_at :datetime not null
# filled_survey_id :bigint not null
# option_id :bigint
# question_id :bigint not null
#
# Indexes
#
# index_answers_on_filled_survey_id (filled_survey_id)
# index_answers_on_option_id (option_id)
# index_answers_on_question_id (question_id)
#
# Foreign Keys
#
# fk_rails_... (filled_survey_id => filled_surveys.id)
# fk_rails_... (question_id => questions.id)
#
class Answer < ApplicationRecord
belongs_to :filled_survey
belongs_to :question
belongs_to :option, class_name: 'QuestionOption', optional: true
validates :content, presence: true, length: { minimum: 1 }, on: :update
validate :content, :validate_question_rules, on: :update
end
And view:
/ Body
.w-full.flex-grow.overflow-y-auto
/ Surveys questions forms
= form_for #selected, url: update_filled_survey_path(#selected.id), html: { data: { 'participant-target' => "#{#selected.id}_form" } } do |form|
= form.hidden_field :survey_id
- #selected.questions.includes(:question_options).each do |question|
.rounded-md.bg-gray-100.opacity-75.flex.items-center.justify-between.mb-2.p-2.relative
%span.flex-grow
= render "components/inputs/#{question.question_type}", question: question, form: form
.flex.justify-center.bg-gray-100.rounded-md.cursor-pointer.my-3
%button.w-full.px-6.py-2.bg-green-200.rounded-md.cursor-pointer.hover:bg-green-300{'data-action' => 'click->participant#updateSurvey', 'data-filled' => #selected.id } #{t('views.participant_portal.surveys.complete')}
Partial(for single type question):
.input_group.flex.flex-col.justify-start
%label.text-gray-700.text-md.font-bold
= question.title
- if question.description
%label.text-gray-600.text-sm #{question.description}
.p-4
= form.fields_for question.question_options do |question_form|
= question_form.collection_select(:option_id, question.question_options, :id, :display, { selected: question.question_options.option_id, include_blank: false }, { id: question.id, name: "#{question.id}_answer", class: 'bg-transparent mx-2'})
JS controller (stimulus JS):
updateSurvey (e) {
document.getElementsByTagName('form')[0].submit()
}
Controller
before_action :set_filled, only: %i[fill_survey]
def set_filled
if current_user.profile.active_study && current_user.profile.paid?
#surveys = current_user.profile.active_study.surveys.select(&:medical).map do |survey|
FilledSurvey.includes.find_or_create_by(survey: survey, user: current_user)
end.reject(&:done?)
elsif current_user.profile.active_study && current_user.profile.approved?
#surveys = current_user.profile.active_study.surveys.select(&:medical?).map do |survey|
FilledSurvey.find_or_create_by(survey: survey, user_id: current_user.id,
created_at: FilledSurvey.this_month)
end.reject(&:done?)
elsif action_name == 'law_quiz'
#surveys = current_user.profile.active_study.surveys.select(&:law?).map do |survey|
FilledSurvey.find_or_create_by(survey: survey, user_id: current_user.id,
created_at: FilledSurvey.this_month)
end.reject(&:done?)
end
end
def fill_survey
set_meta_tags(title: t('page_title.participant_portal.fill_survey'))
aasm_state = current_user.profile.aasm_state
redirect_to authenticated_root_path unless %w[paid approved].include?(aasm_state) &&
!#surveys.empty?
#active_study = current_user.profile.active_study
#selected = params[:id] ? FilledSurvey.find(params[:id]) : #surveys.first
# #answers = #selected.survey.questions.map do |question|
# Answer.find_or_create_by(question_id: question.id, filled_survey_id: #selected.id)
# end
# #answers.sort_by { |answer| answer.question.order }
end
What I wanted to do:
Submit all forms with one button
Get ID of QuestionOption that I select for each question
Create Answer for each Question based on QuestionOption
What I get:
"undefined method `option_id' for #<ActiveRecord::Associations::CollectionProxy [#<QuestionOption id: 328, name:(...)"
Can someone explain how to make it works? I want to understand what's wrong with this code, so I can implement this right way
I'm using the version of that gem https://github.com/crowdint/acts_as_shopping_cart for rails 3
I did everything with the conventions names. But I'm getting the error Can't mass-assign protected attributes: item
class ShoppingCartsController < ApplicationController
before_filter :extract_shopping_cart
def create
#product = Video.find(params[:product_id])
#shopping_cart.add(#product, #product.price) # the error is generated on that line
redirect_to shopping_cart_path
end
My model ShoppingCart:
# == Schema Information
#
# Table name: shopping_carts
#
# id :integer not null, primary key
# created_at :datetime not null
# updated_at :datetime not null
#
class ShoppingCart < ActiveRecord::Base
acts_as_shopping_cart
attr_accessible :price
#accepts_nested_attributes_for :price
end
My model ShoppingCartItem:
# == Schema Information
#
# Table name: shopping_cart_items
#
# id :integer not null, primary key
# owner_id :integer
# owner_type :string(255)
# quantity :integer
# item_id :integer
# item_type :string(255)
# price :float
# created_at :datetime not null
# updated_at :datetime not null
#
class ShoppingCartItem < ActiveRecord::Base
attr_accessible :owner_id, :owner_type, :quantity, :item_id, :item_type, :price
acts_as_shopping_cart_item
end
Can anyone help me what I am missing here?
hope u are aware that
Rails 3
As of Version 0.2.0 Rails 3 is no longer supported. Please use the 0-1-x branch if you still need to implement this gem in a Rails 3 app
gem 'acts_as_shopping_cart', :github => 'crowdint/acts_as_shopping_cart', :branch => '0-1-x'
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
undefined method `to_f' for #<ActiveRecord::Relation:0x472d0a0>
I'm trying to make a call tracking application to learn twilio and rails.
Right now, I would like to make a graph that shows a user how many phone calls a particular phone number gets per day.
The schema is user has_many phones has_many calls.
I try to make the graph by creating an instance method that counts the number of phones on a particular day, but when I try executing the code, I get the error :
SQLite3::SQLException: no such column: calls.placed_at: SELECT COUNT(*) FROM "calls" WHERE "calls"."phone_id" = 44 AND ("calls"."placed_at" BETWEEN '2012-09-15 00:00:00.000000' AND '2012-09-15 23:59:59.999999')
I don't quite understand the code I'm using for the instance method, and it's probably calling the wrong column. Your help on this would be greatly appreciated.
Here's the important part of my call model:
def total_on(date)
calls.where(placed_at: date.beginning_of_day..date.end_of_day).count
end
Here's how I'm counting the phone calls in my show view
<%= (1.month.ago.to_date..Date.today).map { |date| #phone.total_on(date).to_f}.inspect %>
Here's how I define the #phone variable
#phone = Phone.find_by_id(params[:id])
Here's my complete phone model (for schema reference)
# == Schema Information
#
# Table name: phones
#
# id :integer not null, primary key
# name :string(255)
# twilio_number :integer
# original_number :integer
# user_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
class Phone < ActiveRecord::Base
attr_accessible :original_number, :user_id, :name, :twilio_number
belongs_to :user
has_many :calls, dependent: :destroy
validates :name, presence: true
validates :twilio_number, presence: true
validates :original_number, presence: true
validates :user_id, presence: true
default_scope order: 'phones.created_at DESC'
validate :check_phone_limit, :on => :create
def check_phone_limit
if User.find(self.user_id).at_max_phone_limit?
self.errors[:base] << "Cannot add any more phones"
end
end
def original_number=(value)
num = value.to_s.gsub(/[^0-9+]/, "")
write_attribute(:original_number, num.to_i)
end
def total_on(date)
calls.where(placed_at: date.beginning_of_day..date.end_of_day).count
end
end
Here's my complete call model
# == Schema Information
#
# Table name: calls
#
# id :integer not null, primary key
# AccountSid :string(255)
# From :string(255)
# To :string(255)
# CallStatus :string(255)
# ApiVersion :string(255)
# Direction :string(255)
# FromCity :string(255)
# FromState :string(255)
# FromZip :string(255)
# FromCountry :string(255)
# ToCity :string(255)
# ToState :string(255)
# ToZip :string(255)
# ToCountry :string(255)
# CallSid :string(255)
# DialCallSid :string(255)
# DialCallDuration :string(255)
# DialCallStatus :string(255)
# RecordingUrl :string(255)
# phone_id :integer
# DialCallMinutes :integer
# created_at :datetime
# updated_at :datetime
#
class Call < ActiveRecord::Base
attr_accessible :AccountSid, :From, :To, :CallStatus, :ApiVersion, :Direction, :FromCity, :FromState, :FromZip, :FromCountry, :ToCity, :ToState, :ToZip, :ToCountry, :CallSid, :DialCallSid, :DialCallDuration, :DialCallStatus, :RecordingUrl, :DialCallMinutes
belongs_to :phone
def self.create_from_incoming_call(params)
user_phone = Phone.find_by_twilio_number(params['To']) #Finds the phone number in the database based on what phone Twilio is calling
twilio_request_params = {
:CallSid => params['CallSid'],
:AccountSid => params['AccountSid'],
:From => params['From'],
:To => params['To'],
:CallStatus => params['CallStatus'],
:ApiVersion => params['ApiVersion'],
:Direction => params['Direction'],
:FromCity => params['FromCity'],
:FromState => params['FromState'],
:FromZip => params['FromZip'],
:FromCountry => params['FromCountry'],
:ToCity => params['ToCity'],
:ToState => params['ToState'],
:ToZip => params['ToZip'],
:ToCountry => params['ToCountry']
:phone_id => user_phone.phone_id
}
call = Call.new(twilio_request_params)
call.save
return call
end
def Call.update_dial_call(params)
twilio_request_params = {
:DialCallSid => params['DialCallSid'],
:DialCallDuration => params['DialCallDuration'],
:DialCallStatus => params['DialCallStatus'],
:RecordingUrl => params['RecordingUrl'],
:DialCallMinutes => (params['DialCallDuration'].to_f/60.to_f).ceil
}
call = Call.where( :CallSid => params['CallSid'] ).first
call.update_attributes twilio_request_params
call.save
end
end
I've been stuck on this for a while; any help would be greatly appreciated!
Your call model uses the standard rails created_at, yet your query was using placed_at, which doesn't exist.
I am pretty new to Rails and I have stumbled upoun this problem. I'm guessing it's going to be relatively simple to you pros. I have a model named User and this has all the user attributes in it. I also created a model called list and now I want to. I am now trying to call the method create from the user buy doing something like this below (all happening in the console)
sample = User.create(#attributes here)
newlist = sample.List.create(#attributes here)
i then get this error
irb(main):011:0> sample.Lists.new
NoMethodError: undefined method `Lists' for #<User:0x4146750>
Below are my model files for User and List
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# firstName :string(255)
# middleName :string(255)
# lastName :string(255)
# email :string(255)
# facebookexternalId :integer
# userType :integer
# gender :string(255)
# description :string(255)
# location :string(255)
# image :string(255)
# password :string(255)
# notificationId :string(255)
# disabled :boolean
# disabledNotes :string(255)
# city :string(255)
# country :string(255)
# joinDate :string(255)
# created_at :datetime not null
# updated_at :datetime not null
class User < ActiveRecord::Base
attr_accessible :firstName, :middleName , :lastName ,:email , :facebookexternalId, :gender , :description, :location , :image , :city, :country, :disabled
email_regex= /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :firstName , :presence =>true,
:length => {:maximum => 45}
validates :lastName , :presence =>true,
:length => {:maximum => 45}
validates :email , :presence =>true,
:format =>{:with => email_regex},
:uniqueness => {:case_sensitive => false}
validates :description, :length => {:maximum => 140}
has_many :lists
end
Lists
# == Schema Information
#
# Table name: lists
#
# id :integer not null, primary key
# name :string(255)
# user_Id :integer
# active :boolean
# type :string(255)
# description :string(255)
# roughList :boolean
# created_at :datetime not null
# updated_at :datetime not null
#
class List < ActiveRecord::Base
belongs_to :user
end
You should use list in it's plural form which would be something like,
sample_user.lists.create ...
or
sample_user.lists.new
like how you named it in the :has_many
This is the error I get:
ContactPostalcardsController#skip (NoMethodError) "undefined method `status=' for #<ContactPostalcard:0x2b21433d64b0>"
This is the code calling it and trying to assign a value to the status attribute for ContactPostalcard (the Model):
def skip
#contact_postalcard = ContactPostalcard.new(params[:contact_postalcard])
#contact_postalcard.contact_id = params[:contact_id]
#contact_postalcard.postalcard_id = params[:postalcard_id]
#contact_postalcard.status = "skipped"
#contact_postalcard.date_sent = Date.today
#contact_postalcard.date_created = Date.today
if #contact_postalcard.save
render :text => 'This email was skipped!'
end
end
This is the Model referred. Note the "annotate" output shows status as an attribute:
class ContactPostalcard < ActiveRecord::Base
attr_accessible :title, :contact_id, :postal_id, :postalcard_id, :message, :campaign_id, :date_sent, :status
belongs_to :contact
belongs_to :postalcard
alias_attribute :body, :message
alias_attribute :subject, :title
named_scope :nosugar, :conditions => { :sugarcrm => false }
def company_name
contact = Contact.find_by_id(self.contact_id)
return contact.company_name
end
def asset
Postalcard.find_by_id(self.postalcard_id)
end
def asset_class
Postalcard.find_by_id(self.postalcard_id).class.name
end
end
# == Schema Information
#
# Table name: contact_postalcards
#
# id :integer not null, primary key
# title :string(255)
# contact_id :integer
# postalcard_id :integer
# message :text
# campaign_id :integer
# date_sent :datetime
# created_at :datetime
# updated_at :datetime
# postal_id :integer
# sugarcrm :boolean default(FALSE)
# status :string(255)
#
I am unclear as to why I keep getting an 'undefined method' -- I have added the status attribute (it had been missing before but used a migration and then raked), so need some help...thank you.
Have you restarted your Rails application since you ran your migration? If you're running in production mode, Rails caches your classes until you restart it, and since status wasn't an attribute before the migration, Rails wouldn't have added accessor methods for it, which would explain why status= is undefined.