Hey all,
I'm having a pretty weird problem and am having trouble isolating the cause. I get the feeling its a simple solution, but I was hoping for a nudge in the right direction. I have the following models:
class User < ActiveRecord::Base
has_many :pnotes
class Pnote < ActiveRecord::Base
belongs_to :preport
belongs_to :user
class Preport < ActiveRecord::Base
has_many :pnotes, :dependent=>:destroy
The Pnote portion of my schema looks as so:
create_table "pnotes", :force => true do |t|
t.integer "preport_id"
t.integer "user_id"
t.text "content"
t.datetime "created_at"
t.datetime "updated_at"
end
I'm trying to display all of the Pnotes associate with a given Preport on the show page of the Preport
My Preport Controller has the following code for the show action:
def show
#board = Board.find(params[:board_id])
#preport = #board.preport
#pnotes = #preport.pnotes
#pnote=#preport.pnotes.build
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #preport }
end
end
So now in my show.html.erb in the Preports folder, I am trying to display a list of the Pnotes as such:
<ul>
<% #pnotes.each do |pnote| %>
<li><%= pnote.user.login %><span>-<%=pnote.content %></span></li>
<% end %>
</ul>
"login" is the standard field that came along with the Devise Authentication Gem.
However, this gives me the following error:
undefined method `login' for nil:NilClass
If I change the view to this:
<%= pnote.user%>-<%=pnote.content %>
I get :
#<User:0x106c25888>-Testing
, so it appears that it is identifying the associated user, but unable to grab its attributes.
Any advice would be greatly appreciated! I feel like there is a fairly small oversight going on here, but I am unable to distinguish from exactly where
Thanks!
Unless you're using a very old version of Devise that I'm not aware of, the User model wouldn't have a login attribute.
Try email instead.
Related
I need some advice on building a has many through relationship between USER, THING and EXTRA models.
My USER model is slightly modified inside Devise gem and is noted as Creator whereas other models belonging to USER receive :created_things form.
In my app, USERS create THINGS can later add EXTRAS to their THINGS.
I chose has many through because I want to have unique data on all three models and be able to call both THINGS and EXTRAS from the USER "CREATOR" model.
I have built this many different ways and after 10 years of solving my problems by reading stackoverflow, I am finally submitting this request for support! Thank you for your help.
I have tried creating user and extra references on the THING model and declaring nested attributes in the USER and THING model. I have tried several examples from stackoverflow inside the create and new methods but nothing seems to work.
class User < ApplicationRecord
has_many :created_things, class_name: Thing, foreign_key:
:creator_id, :dependent => :destroy
has_many :extras, through: :created_things
accepts_nested_attributes_for :extras, :reject_if => :all_blank,
allow_destroy: true
class Thing < ApplicationRecord
belongs_to :creator, class_name: User
has_many :extras
accepts_nested_attributes_for :extras, :reject_if => :all_blank,
allow_destroy: true
class Extra < ApplicationRecord
belongs_to :creator, class_name: User, inverse_of: :thing
belongs_to :created_things
Members Index.html.erb
<% if thing.extras.exists? %>
<% thing.extras.each do |extra| %>
<%= extra.title %> <%= link_to "[+]", edit_extra_path(extra) %>
<% end %>
<% else if thing.extras.empty? %>
<%= link_to "+1 EXTRA", new_extra_path(current_user) %>
<% end %>
<% end %>
class MembersController < ApplicationController
before_action :authenticate_user!
def index
#user = current_user
#created_extras = #user.extras
#created_things = #user.created_things
end
class ExtrasController < ApplicationController
def new
#extra = Extra.new
end
def create
#extra = current_user.extras.build(extra_params)
if #extra.save
I am able to create a new EXTRA but the :thing_id remains nul as it does not display when called on the show extra view. Therefore I am not surprised that when I return to the member index page that my thing.extras.exists? call is returning false and the created extra never displays under the THING view. My attempts to modify the extra controller have failed and I some of my reading sugested the extras controller is not necessary in this relationship so I am really at a loss on how this is built. I'm assuming I am missing something in new and create methods maybe in things or user controller? Perhaps I'm missing something in routes resources? Any advice is greatly appreciated. Thank you.
Ok, I figured it out. I really didn't need has many through for this model and I did a lot of testing of the syntax on each model.rb and in the end was able to figure it out from this stackoverflow . . .
[Passing parent model's id to child's new and create action on rails
Here are my the various parts of setting up a has many and belongs to relationship with nested attributes.
class Thing < ApplicationRecord
belongs_to :creator, class_name: User
has_many :extras, inverse_of: :thing, :dependent => :destroy
accepts_nested_attributes_for :extras, allow_destroy: true
class Extra < ApplicationRecord
belongs_to :thing, inverse_of: :extras
extras_controller.rb
class ExtrasController < ApplicationController
def new
#extra = Extra.new(thing_id: params[:thing_id])
end
def create
#user = current_user
#extra = Extra.new(extra_params)
#extra.user_id = #user.id
if #extra.save
flash[:success] = "You have added a new Extra!"
redirect_to #extra #extras_path later
else
flash[:danger] = "The form contains errors"
render :new
end
end
edit.html.erb things
<% if #thing.extras.exists? %>
<p>current extras associated with <%= #thing.title %>: </p>
<% #thing.extras.each do |extra| %>
<p><%= extra.title %> <%= link_to "[+]", edit_extra_path(extra) %>
/ <%= link_to "[-]", extra_path(extra), method: :delete %> </p>
<% end %>
<% end %>
<%= link_to "+1 EXTRA", new_extra_path(thing_id: #thing.id) %>
<%= render 'things/form' %>
I have a select box on a form to select the type of category for a project:
<%= f.select(:category, collection_select(:project_category, :cat_id, #project_category, :id, :cat_name)) %>
It should populate from the project_categories table.
The migration looks like this:
class CreateProjectCategories < ActiveRecord::Migration
def change
create_table :project_categories do |t|
t.string :category_name
t.text :cat_desc
t.date :created_on
t.datetime :updated_at
end
end
end
My project.rb model deines has_one :category and the projectCategory.rb model defines belongs_to :project.
My project_categories table is populated with data. I got the syntax from the Rails Guides, but it's not working.
Any help?
Ok, I had the wrong syntax. The final code looks like this:
<%= collection_select(:project_categories, :id, Project_Category.all, :id, :category_name) %>
Essentially the syntax should be defined like this: WARNING: PSEUDO-CODE!!
<%= collection_select(:database_table, :lookup_value, Model_Name.all, :returned_numeric_value, :returned_text_value_based_on_numeric_value) %>
Don't know why the API docs couldn't have just said so...
The Problem:
I am getting an error message when submitting my form that says:
ActiveModel::MassAssignmentSecurity::Error in AdmissionRecordsController#create
Can't mass-assign protected attributes: admission_record
My Setup:
I am using Rails 3.2.3, with extra gems including Cocoon 1.0.14 and Simple_Form 2.0.2
The View:
My app/views/admission_records/_form.html.haml looks like:
= simple_form_for [#admission, #record] do |f|
= f.simple_fields_for :vital_signs, #record.vital_signs.build do |vs|
= render :partial => "vital_sign_fields", :locals => { :f => vs }
= link_to_add_association "Add Vital Signs", f, :vital_signs
= f.submit
And my app/views/admission_records/_vital_sign_fields.html.haml looks like:
.nested-fields
= f.label :sbp
= f.text_field :sbp
...
= link_to_remove_association "Remove Vital Sign"
What I am basically trying to do is that I have a resource called AdmissionRecord nested within another resource called PatientAdmission (route.rb shown below). I have another resource called VitalSign which I want to be able to create via a nested form (using cocoon and simple_form) when creating the AdmissionRecord
My config/routes.rb file looks like:
resources :patient_admissions do
resources :admission_records
end
The Models:
My app/models/patient_admission.rb looks like:
class PatientAdmission < ActiveRecord::Base
has_many :admission_records, :dependent => :destroy
end
My app/models/admission_record.rb looks like:
class AdmissionRecord < ActiveRecord::Base
belongs_to :patient_admission
has_many :vital_signs, :dependent => :destroy
accepts_nested_attributes_for :vital_signs, :rejects_if => :all_blank, :allow_destroy => true
attr_accessible :vital_signs_attributes
end
And my app/models/vital_sign.rb looks like:
class VitalSign < ActiveRecord::Base
belongs_to :admission_record
attr_accessible # just fields that appear in the form
end
The Controller:
The new and create methods in my AdmissionRecordsController looks like:
before_filter do
#admission = PatientAdmission.find(params[:patient_admission_id])
end
def new
#record = #admission.admission_records.build
end
def create
#record = #admission.admission_records.build(params[:admission_record])
#vital_sign = #record.vital_signs.build(params[:vital_signs])
#vital_sign.save
if #record.save
# Flash success and redirect to the right place
else
# Flash error and render :new
end
end
The Plea:
Please help me find where I'm going wrong. I've googled for hours and have looked at other examples and source code for demo apps such as those found in cocoon_simple_form_demo, but still can't seem to fix this error. If there's any other piece of information needed to debug this problem, please let me know. Thanks!
Okay I just had this problem and fixed it by entering one line of code in the belongs_to model.
# patient_admission.rb
Class PatientAdmission < ActiveRecord::Base
attr_accessible :admission_record_attributes
accepts_nested_attributes_for :admission_record
...
end
Here is another solution to it :)
I am a rails newbie. I am trying to implement acts-as-taggable-on on my sample app. I am able to enter multiple tags using tag_list but facing issues searching them.
This is what I got.
I used scaffold User to generate the controller & model.
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.text :tags
t.timestamps
end
end
end
My User Model is
class User < ActiveRecord::Base
serialize :tags
acts_as_taggable_on :tags
scope :by_join_date, order("created_at DESC")
end
My User controller
Class UsersController < ApplicationController
def index
#users = User.all
#search = User.tagged_with("Tag11")
end
...
...
...
end
I also did not make any changes to class ActsAsTaggableOnMigration < ActiveRecord::Migration after installing the gem.
In my view I replaced :tags with :tag_list in my _form, index & show html files
<div class="field">
<%= f.label :tags %><br />
<%= f.text_field :tag_list %>
</div>
This is what I get in the browser
Could you please help me understand where I am making a mistake?
Thank you.
I'm guessing (because you haven't provided the code from your other view yet) but:
when you do #search = User.tagged_with("Tag11") what is getting returned is not the tag names, but the actual tag objects. If you have: <%= #search %> in your view, it won't work. You'll need something like:
<%= #search.map(&:name).join(', ') %>
or similar.
I'm a complete rails noob, so there's probably something very simple I'm missing here. I have these little tweet-type things called microposts, and I want each micropost to have a release date set by the user. My form looks ok and doesn't show any errors in the browser when I create a new micropost, but the release date isn't being saved in the database. In my form to create a new micropost, I have this:
<div class="field">
<%= f.label :release_date %>
<%= f.text_field :release_date, :size => 10 %>
</div>
In my database schema, I have this:
create_table "microposts", :force => true do |t|
t.string "content"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "release_date"
end
I made the release_date attribute accessible in my Micropost model like so:
attr_accessible :content, :release_date
And my create method in my Micropost controller looks like this:
def create
#micropost = current_user.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "New event created."
redirect_to root_path
else
render 'pages/home'
end
end
Everything else saves just fine. It's only the release date that seems to be ignored. This is just a wild guess, but is rails ok with something like 10/25/2011 being saved as a datetime? Or is that supposed to be saved as a string and then parsed into a proper datetime format?
There's a lot of info missing here to evaluate. The params hash probably doesn't have the value, or it isn't hashed in a way expected by rails.
In your User model, do you have:
accepts_nested_attributes_for :microposts
Also, you'll want to look up tutorials on form_for and fields_for in rails.
Likely the format you are entering the date in isn't getting cast as a datetime properly:
def Micropost < ActiveRecord::Base
before_validation_on_create :convert_release_date_to_datetime
private
def convert_release_date_to_datetime
self.release_date = Time.parse(release_date)
end
end