currently I am creating a snapchat like application by using Rails. I get the error:
undefined method `sender_id=' for nil:NilClass
while I am trying to submit the new message form, I don't really know where I make the mistake. Moreover, I am not sure about the logic of the create action in my messages_controller, basically I just want the sender sends a message to the people in their friendlist by choosing one or more recipients at the same time(of course, the recipients must be in their friendlist, and I have already accomplished this feature). However, because I still haven't figured out how can I pass the the params recipient_id to the form(I am using simple form gem and devise gem by the way), so I hardcoded the recipient_id in my create action. So,all of suggestions/advices are welcome.
Here are my files:
messages_controller.rb:
class MessagesController < ApplicationController
def new
#message = Message.new
end
def create
#message.sender_id = current_user
#message.recipient_id = current_user.friendships.friend_id
#message = Message.new(message_params)
if #message.save?
flash[:success] = 'Message sent successfully'
redirect_to welcome_profile_path
else
render 'new'
end
end
private
def message_params
params.require(:message).permit(:body, :sender_id, :recipient_id, :user_id)
end
end
messages/new.html.erb:
<h1>Create New Message</h1>
<%= simple_form_for #message do |f| %>
<%= f.input :body %>
<%#= f.association :user, :as => :hidden, :input_html => { :value => current_user.id }, :include_blank => false %>
<%= f.button :submit, "Send Message", class: "btn btn-secondary" %>
<% end %>
message.rb:
class Message < ActiveRecord::Base
belongs_to :user, foreign_key: :recipient_id
belongs_to :sender, :foreign_key => :sender_id, class_name: 'User'
belongs_to :recipient, :foreign_key => :recipient_id, class_name: 'User'
validates_presence_of :body
end
user.rb:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
validates :username,
:presence => true,
:uniqueness => {
:case_sensitive => false
}
validate :validate_username
def validate_username
if User.where(email: username).exists?
errors.add(:username, :invalid)
end
end
has_many :friendships
has_many :friends, :through => :friendships
has_many :inverse_friendships, :class_name => "Friendship", :foreign_key => "friend_id"
has_many :inverse_friends, :through => :inverse_friendships, :source => :user
has_many :messages, dependent: :destroy
end
schema.rb:
ActiveRecord::Schema.define(version: 20160316170009) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "friendships", force: :cascade do |t|
t.integer "user_id"
t.integer "friend_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "messages", force: :cascade do |t|
t.text "body"
t.boolean "read"
t.integer "sender_id"
t.integer "recipient_id"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "messages", ["user_id"], name: "index_messages_on_user_id", using: :btree
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "username"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
add_index "users", ["username"], name: "index_users_on_username", unique: true, using: :btree
add_foreign_key "messages", "users"
end
That error is because you don't have #message defined before setting #message.sender_id in your create action. Move #message = Message.new(message_params) to the top of the create action before setting #message.sender_id as follows:
class MessagesController < ApplicationController
...
def create
#message = Message.new(message_params)
#message.sender_id = current_user
#message.recipient_id = current_user.friendships.friend_id
if #message.save?
flash[:success] = 'Message sent successfully'
redirect_to welcome_profile_path
else
render 'new'
end
end
private
def message_params
params.require(:message).permit(:body, :sender_id, :recipient_id, :user_id)
end
end
The second part of the question - current_user is available in your controllers, so you don't need a hidden field for that. You can call #message.sender_id = current_user.id in your create action as you currently have. Next, to set #message.recipient_id, you could update your new.html.erb as follows:
# new.html.erb
<h1>Create New Message</h1>
<%= simple_form_for #message do |f| %>
<%= f.input :body %>
<%# Updated the following line. You could chose to create a hidden field here, or however you wish to implement this in your view as long as you specify `recipient` as the association or `recipient_id` as the field. %>
<%= f.association :recipient, :include_blank => false %>
<%= f.button :submit, "Send Message", class: "btn btn-secondary" %>
<% end %>
With the above setup your create action could be updated to:
# app/controllers/messages_controller.rb
def create
#message = Message.new(message_params)
#message.sender_id = current_user
if #message.save?
flash[:success] = 'Message sent successfully'
redirect_to welcome_profile_path
else
render 'new'
end
end
Related
Hi I have an app that uses devise for authentication and devise invitable.
On sign up the user creates an account.
class Account < ApplicationRecord
belongs_to :user, class_name: "owner", foreign_key: "owner_id"
has_many :users, dependent: :destroy
has_many :clients, dependent: :destroy
end
The user signs up and is given the role admin by default on create!
class User < ApplicationRecord
has_merit
enum role: [:user, :tech, :admin, :manager]
has_one :account, foreign_key: 'owner_id'
accepts_nested_attributes_for :account
after_initialize :set_default_role, :if => :new_record?
def set_default_role
self.role ||= :admin
end
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :invitable, :registerable,
:recoverable, :rememberable, :validatable
end
I am confused on how I can manage the user has_one :account as owner (user signs up)and belongs_to: account as employee (user is invited)
Schema
create_table "accounts", force: :cascade do |t|
t.string "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "owner_id", null: false
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.integer "role"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "sash_id"
t.integer "level", default: 0
t.bigint "account_id"
t.index ["account_id"], name: "index_users_on_account_id"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
app/views/devise/registrations/new.html.erb
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :email,
required: true,
autofocus: true,
input_html: { autocomplete: "email" }%>
<%= f.simple_fields_for :accounts do |a| %>
<%= a.input :name %>
<% end %>
<%= f.input :password,
required: true,
hint: ("#{#minimum_password_length} characters minimum" if #minimum_password_length),
input_html: { autocomplete: "new-password" } %>
<%= f.input :password_confirmation,
required: true,
input_html: { autocomplete: "new-password" } %>
</div>
<div class="form-actions">
<%= f.button :submit, "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
would you recommend a join table account_users account:references user:references... or is there a simple way to do this?
I thought about an Admin Devise model but that makes login a bit of a pain.
You would do better by having Account as the parent and User as the child like so:
Account has_many Users
So what you could do is in your User model create a callback to check for the presence of an account and create one if it's blank.
before_validation :create_account_if_blank
def create_account_if_blank
if self.account.blank?
ApplicationRecord.transaction do
account = Account.create!(name: self.full_name)
some_other_thing = Something.create!(name: 'test')
end
end
end
Then when you create another user from your "Admin" account, just set the the current account from the controller.
You could even do something like this:
current_account.users.create(your parameters here)
Put the current_account function in your application controller.
The current_account function would look like this:
def current_account
return current_user.account
end
I think you can use STI instead to have Owner class and Employee class both inherit from User and role as inheritance_column, then you can make polymorphic relation between the roles and the account
class Employee < User
has_one :account, as: :accountable
end
class Owner < User
has_one :account, as: :accountable
end
# do the same with the other roles it gives you more flexibility to have different behaviour for every role than using only User class
Account < ApplicationRecord
belongs_to :accountable, polymorphic: true
end
Have a recipient and sender, both of the same class(Message) for a messaging system in rails. Want to set the params for both i.e. if user creates a message sender by default is the user_id and recipient will be the contact selected from the users contact list.
Currently the database is only receiving a user_id to the recipient_id column which is wrong and should be to sender_id column. Sender_id receives nothing.
After reading, some say not to amend the params as this is bad practice. So set a hidden field in the message view (like the body and title) yet this isn't pushing in to the database.
Two questions, is this process an appropriate rails practice? (ask this as new to rails) If not: can you advise another path or direction? If so: any ideas/thoughts why this isn't saving in to the database?
user model
class User < ActiveRecord::Base
has_many :messages, class_name: "Message", foreign_key: "recipient_id"
has_many :sent_messages, class_name: "Message", foreign_key: "sender_id"
has_many :contacts, dependent: :destroy
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
validates_presence_of :firstname, allow_blank: false
validates_presence_of :surname, allow_blank: false
end
message model
class Message < ActiveRecord::Base
belongs_to :sender, class_name: "User", foreign_key: "sender_id"
belongs_to :recipient, class_name: "User", foreign_key: "recipient_id"
validates_presence_of :body, :title
end
Messages controller
class MessagesController < ApplicationController
before_action :message, only: [:show]
before_action :authenticate_user!
def index
#messages = current_user.messages
end
def new
#message = Message.new
end
def create
current_user.messages.create(message_params)
redirect_to '/messages'
end
def show
end
private
def message_params
params.require(:message).permit(:title, :body, :sender_id, :recipient_id)
end
def message
#message = Message.find(params[:id])
end
end
message/new view
<%= form_for #message do |f| %>
<%= hidden_field_tag :sender_id, current_user.id %>
<%= f.text_field :title %>
<%= f.text_field :body %>
<%= f.submit %>
<% end %>
schema
ActiveRecord::Schema.define(version: 20160517131719) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "contacts", force: :cascade do |t|
t.string "firstname"
t.string "surname"
t.string "email"
t.integer "phone"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"
t.integer "user_id"
end
add_index "contacts", ["user_id"], name: "index_contacts_on_user_id", using: :btree
create_table "messages", force: :cascade do |t|
t.string "title"
t.text "body"
t.integer "sender_id"
t.integer "recipient_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "firstname"
t.string "surname"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
add_foreign_key "contacts", "users"
end
Try changing your form to this:
<%= form_for #message do |f| %>
<%= f.hidden_field :sender_id, value: current_user.id %>
<%= f.text_field :title %>
<%= f.text_field :body %>
<%= f.submit %>
<% end %>
Currently the database is only receiving a user_id to the recipient_id
column which is wrong and should be to sender_id column.
In your create action, you have current_user.messages.create(message_params). This creates a message record in the DB with the foreign key's(i.e, recipient_id in your case) value with the parent's(user) id. This is the reason, the recipient_id gets the value of user's id.
Sender_id receives nothing.
This is because the hidden_field set for sender_id is not wrapped with the form builder instance. You need to change
<%= hidden_field_tag :sender_id, current_user.id %>
to
<%= f.hidden_field :sender_id, current_user.id %>
I am unable to insert data in user_preferences table where as I am getting all the attributes in params. I tried inserting value from console by following way since association between User has_one user_preference and UserPreference belongs_to User:
user = User.find(1)
user.user_preferences.title = "MyTitle"
I am getting undefined method "title"
user_preference.rb
class UserPreference < ActiveRecord::Base
belongs_to :user
def self.bgcolor_options
[["Orange", "#FF3300"], ["Green", "#00FF00"], ["Blue", "#0000FF"], ["Pink", "#FF0066"], ["Yellow", "#FFFF00"], ["White", "#FFFFFF"]]
end
def self.font_options
[["Times New Roman", "Times New Roman"], ["Verdana", "Verdana"],["Arial", "Arial"],["sans-serif", "sans-serif"]]
end
end
user_preferences_controller.rb
class UserPreferencesController < ApplicationController
def new
#user_preference = UserPreference.new
end
def create
#user_preference = UserPreference.new(user_pref_params)
#user_preference.save unless user_signed_in?
render 'user_preferences/new'
end
def edit
end
def update
end
private
def user_pref_params
params.require(:user_preference).permit(:title, :bgcolor, :font, :description)
end
end
routes.rb
Rails.application.routes.draw do
resources :user_preferences
post "/user_preferences/new"
devise_for :users
devise_scope :user do
authenticated :user do
root :to => 'user_preferences#new', as: :authenticated_root
end
unauthenticated :user do
root :to => 'devise/registrations#new', as: :unauthenticated_root
end
end
user_preferences/new.html.erb
<%= form_for #user_preference, :url => { :action => "create" } do |u|%>
<div style="background-color:#{current_user.user_preference.bgcolor.nil? ? '#FFFFFF' : current_user.user_preference.bgcolor}">
<p>
<%= u.label :title %><br>
<%= u.text_field :title %>
</p>
<p>
<%= u.label :description %><br>
<%= u.text_field :description %>
</p>
<p> <%= u.label :back_ground_color %><br>
<%= u.select :bgcolor, options_for_select(UserPreference.bgcolor_options) %>
</p>
<p>
<%= u.label :font %><br>
<%= u.select :font, options_for_select(UserPreference.font_options) %>
</p>
<br >
<p>
<%= u.submit %>
</p>
<hr >
<div style="background: #{current_user.user_preferences.bgcolor};"></div>
<div style="background-color:#{current_user.user_preferences.font.nil? ? 'Arial' : current_user.font}">
This is the changes made in background
</div>
</div>
<% end %>
schema.rb
ActiveRecord::Schema.define(version: 20150422034042) do
create_table "user_preferences", force: :cascade do |t|
t.text "title"
t.string "font"
t.text "description"
t.string "bgcolor"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
Adding User.rb code
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
has_one :user_preference
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
You're accessing the wrong association on user:
user.user_preferences.title = "MyTitle"
user_preferences is a has_many association, and returns multiple objects. The error itself also mentions this (something like ActiveRecord_Associations_CollectionProxy).
Simply access the has_one association and it will work:
user.user_preference.title = "MyTitle"
for the console part its not a javascript if you want to set to relation you have to use a variabel to assign, and not to use user_preference(s) note the s and its has_one relation and it should be user_preference and in your User Model it should be
# User Model
has_one :user_preference
# Console
user = User.first
preferences = user.user_preference
preferences.title = "MyTitle"
preferences.save
user.reload.preferences.title # should be "MyTitle"
I am writing own blog in ruby on rails. I got stuck while getting user who creates articles on views. Basically I want to fetch username of user who creates article(post) in my blog application.
I have user, article tables where I have user_id in article table. I do not know how to fetch user who create article in application.Basically I want to display name (username) of user who create article on article/index.html page. I tried to get user name while creating article in article controller
def create
#article = Article.new(params[:article])
#article.user_id = current_user
#article.save
redirect_to article_path(#article)
but could not get.
Currently users_controller.rb is empty.
Do I need join between user and article table or is it possible with out join in rails. Please suggest me.
article/index.html.
<div class="">
<title> <h2> learning experience blog </h2></title>
</div>
<div style="margin: 0 0 20px; padding: 20px 20px 10px; background: none repeat scroll 0 0 #82b548 ;">
<% #articles.each do |article| %>
<div style=" border-bottom: none:border: 1px solid #666666;border-radius: 1px 1px 1px 1px;margin: 0 0 20px; padding: 20px 20px 10px;height:280px; background: none repeat scroll 0 0 #FFFFFF ">
<div style="color:#51702E"><h2><%= article.title %></h2></div>
<div style="color:#666666; margin-top:10px"> <%= article.created_at %></div>
<hr style="border: 1px solid #FA9300;">
<div style="margin-top:10px; color:"> <%= truncate(article.body, :length => 500, :separator => ' ') %></div>
<div style="margin-top:35px">
<% if current_user.try(:is_admin) %>
<%= link_to "edit",edit_article_path(article), :class => 'btn btn-warning btn' %>
<%= link_to "delete",article_path(article),:method => :delete,:confirm => 'Are you sure?',:class => 'btn btn-danger' %>
<% end %>
<%= link_to "view more...",article_path(article), :class => 'btn btn-primary' %>
</div>
</div>
<% end %>
<% if current_user.try(:is_admin) %>
<%= link_to "Create new Article", new_article_path, :class => 'btn btn-large btn-primary' %>
<% end %>
articles_controller.rb
class ArticlesController < ApplicationController
def index
#articles = Article.all
end
def show
#article = Article.find(params[:id])
end
def new
#article = Article.new
end
def create
#article = Article.new(params[:article])
#article.user_id = current_user.id
#article.save
redirect_to article_path(#article)
end
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to action: 'index'
end
def edit
#article = Article.find(params[:id])
end
def update
#article = Article.find(params[:id])
#article.update_attributes(params[:article])
flash.notice = "Article '#{#article.title}' Updated!"
redirect_to article_path(#article)
end
end
user.rb model
class User < ActiveRecord::Base
has_many :articles
has_many :comments
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :username, :email, :password, :password_confirmation, :remember_me
attr_accessible :title, :body
end
article_rb
class Article < ActiveRecord::Base
attr_accessible :title, :body
has_many :comments
belongs_to :user
end
schema.rb
# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20130406120152) do
create_table "articles", :force => true do |t|
t.string "title"
t.text "body"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "user_id"
end
create_table "comments", :force => true do |t|
t.text "content"
t.integer "user_id"
t.string "article_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "users", :force => true do |t|
t.string "email", :default => "", :null => false
t.string "encrypted_password", :default => "", :null => false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", :default => 0
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.boolean "is_admin"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "name"
t.string "username"
t.boolean "is_active"
end
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true
end
Please suggest me how to get user info who creates article.
I beleive you have the relationships defined in your model.
class User
has_many :articles
end
class Article
belongs_to :user
end
Now you could simply do
a = Article.find_by_id(1)
a.user # to get the user for Article
So based on Ryan Bates rails cast (http://railscasts.com/episodes/196-nested-model-form-revised) I am creating a nested form. The part of the rails application that I am trying to get to work ideally does the following:
Let a current user ask a question
Then provide an answer for that question afterwards
I managed to get everything working, except that when I try to submit the form once everything is filled out, I keep getting the following error:
undefined method `meter_id' for nil:NilClass
app/models/answer.rb:13:in `associate_with_meter_id'
app/controllers/questions_controller.rb:13:in `create'
I believe I know what is wrong, but I am not sure how to fix it. The meter_id is returning an undefined value, because it is not being passed the correct value. Here is the method that associates the meter_id (of answers) with the meter_id (of users):
def associate_with_meter_id
self.meter_id = user.meter_id
end
Here is a partial of my user model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me,
:home_size_sf, :meter_id, :avg_monthly_kwh, :discovery_score,
:questions_attributes, :answers_attributes
has_many :data_records, :foreign_key => :meter_id, :primary_key => :meter_id, :class_name => "DataRecord"
has_many :questions
has_many :answers
accepts_nested_attributes_for :questions, :answers
Here is the questions model
class Question < ActiveRecord::Base
attr_accessible :description, :taxonomy, :user_id, :answers_attributes
belongs_to :user
has_many :answers
accepts_nested_attributes_for :answers
validates :description, presence: { :on => :create }
validates :taxonomy, presence: { :on => :create }
def relevance_score
rand
end
end
Here is the questions controller
class QuestionsController < ApplicationController
respond_to :html, :json
def index
#question = current_user.questions.new
#questions = current_user.questions.all
end
def create
#question = current_user.questions.new(params[:question])
if !params[:update_button]
if #question.valid?
if params[:next_button] || !#question.save
render 'index'
elsif !params[:next_button] && params[:submit_button] && #question.save
flash[:success] = "Your question and answer have been saved."
respond_with #question, :location => questions_path
end
else
render 'index'
end
else
render 'index'
end
end
def next
#question = current_user.unanswered.first
#answer = Answer.new(:question => #question, :user => current_user)
respond_to do |format|
format.js
end
end
end
answers model
class Answer < ActiveRecord::Base
attr_accessible :value, :user_id, :meter_id, :question_id
belongs_to :user
belongs_to :question
validates :value, presence: true, :numericality => true
before_save :associate_with_meter_id
def associate_with_meter_id
self.meter_id = user.meter_id **(<-- line 13 from the error message)**
end
end
answers controller
class AnswersController < ApplicationController
respond_to :html, :json
def index
#answers = current_user.answers
end
def create
#answer = current_user.answers.create(params[:answer])
if #answer.save
flash[:notice] = "Thanks for for answer. Please continue with your input...."
respond_with #answer, :location => root_url
end
end
end
database schema
ActiveRecord::Schema.define(:version => 20120210184340) do
create_table "answers", :force => true do |t|
t.integer "meter_id"
t.integer "user_id"
t.integer "question_id"
t.float "value"
t.float "what_if_value"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "data_records", :force => true do |t|
t.datetime "timestamp"
t.float "value"
t.integer "meter_id"
t.string "status_code"
end
create_table "questions", :force => true do |t|
t.string "description"
t.string "taxonomy"
t.string "coeff"
t.float "rsquare", :default => 0.0
t.string "rank"
t.string "responses"
t.string "skips"
t.string "avganswer"
t.float "pval", :default => 0.0
t.float "quality", :default => 0.0
t.integer "user_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "setup_constants", :force => true do |t|
t.float "exp_model", :default => 0.0
t.float "exp_pval_const", :default => 0.0
end
create_table "users", :force => true do |t|
t.integer "meter_id"
t.float "home_size_sf", :default => 1000.0
t.text "notifications"
t.float "avg_monthly_kwh"
t.float "ee_score"
t.string "email", :default => "", :null => false
t.string "encrypted_password", :default => "", :null => false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", :default => 0
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true
end
Note:
In the answers model (above), the line:
self.meter_id = user.meter_id
Associates the meter_id of the answer model with the meter_id of the user model. I believe this is where the issue is. I tried changing the above line to:
self.meter_id = 2
And then everything worked fine, so it's obvious that the user.meter_id is undefined, so I'm not sure how to pass that value through the nested form? I tried using a hidden field but with no luck (the following is a nested fields_for :answers, within a form_for #questions):
<fieldset>
<%= f.label "Yes" %>
<%= f.radio_button :value, 1 %>
<%= f.label "No" %>
<%= f.radio_button :value, 0 %>
<%= f.hidden_field :user_id %>
<%= f.hidden_field :question_id %>
<%= f.hidden_field :meter_id %>
</fieldset>
First of all, you don't want to pass the current user in the view for security reasons. Instead, you want to do it from the controller.
A starting point (assuming you have current_user):
#answer = current_user.answers.create(params[:answer].merge(:user => current_user))
From there, it's up to you how to pass the user to the answer model. You could, however, use this:
self.meter_id = question.user.meter_id
Assuming that's appropriate.