associations - Rails - How to show attribute of parent object -
i making app rails 4.
i trying understand how work associations , show attributes associated models. i'm struggling grasp concepts.
i have project model , project_invitations model.
the associations are:
projects has many project invitations project invitations belong project in project_invitation show, trying display project attributes project creator attributes (stored in user profiles table).
i getting stuck.
in project_invitation show, have:
you're invited participate in <%= project_invitation.project.title %> i have tried:
you're invited participate in <%= @project_invitation.project.title %> when try ^^ error:
undefined method `title' nil:nilclass in project table, have attribute called :title.
i want project invitation show show name of project invitee has been invited.
what's wrong way i've tried it?
my project_invitations controller has following (generated scaffold):
class projectinvitationscontroller < applicationcontroller before_action :set_project_invitation, only: [:show, :edit, :update, :destroy] # /project_invitations # /project_invitations.json def index @project_invitations = projectinvitation.all end # /project_invitations/1 # /project_invitations/1.json def show end # /project_invitations/new def new @project_invitation = projectinvitation.new end # /project_invitations/1/edit def edit end # post /project_invitations # post /project_invitations.json def create @project_invitation = projectinvitation.new(project_invitation_params) respond_to |format| if @project_invitation.save format.html { redirect_to @project_invitation, notice: 'project invitation created.' } format.json { render action: 'show', status: :created, location: @project_invitation } else format.html { render action: 'new' } format.json { render json: @project_invitation.errors, status: :unprocessable_entity } end end end # patch/put /project_invitations/1 # patch/put /project_invitations/1.json def update respond_to |format| if @project_invitation.update(project_invitation_params) format.html { redirect_to @project_invitation, notice: 'project invitation updated.' } format.json { head :no_content } else format.html { render action: 'edit' } format.json { render json: @project_invitation.errors, status: :unprocessable_entity } end end end # delete /project_invitations/1 # delete /project_invitations/1.json def destroy @project_invitation.destroy respond_to |format| format.html { redirect_to project_invitations_url } format.json { head :no_content } end end private # use callbacks share common setup or constraints between actions. def set_project_invitation @project_invitation = projectinvitation.find(params[:id]) end # never trust parameters scary internet, allow white list through. def project_invitation_params if can? :create, project, params[:project_invitation].permit(:comment, :expiry_date, :draft, :course_credit) elsif can? :read, projectinvitation params[:project_invitation].permit(:student_accepted, :sponsor_accepted) end end end the project_invitation model has:
class projectinvitation < activerecord::base belongs_to :project belongs_to :user end the project model has:
class project < activerecord::base include rolemodel #belongs_to :students, through: :courses, counter_cache: true has_many :project_questions, dependent: :destroy#, through: :projects accepts_nested_attributes_for :project_questions has_one :sweep accepts_nested_attributes_for :sweep has_one :educator_project_comment has_many :project_student_eois belongs_to :educator has_many :project_invitations has_one :video accepts_nested_attributes_for :video has_one :finalise, through: :sweep has_many :observations has_one :approval_request belongs_to :industry belongs_to :course has_and_belongs_to_many :users belongs_to :creator, class_name: 'user' has_many :profiles, through: :industry mount_uploader :hero_image, avataruploader mount_uploader :link_to_video_proposal, videouploader end in project_invitiatons show page, have:
<div class="containerfluid"> <%= render 'static/deviselinks'%> <div class="row"> <div class="col-md-10 col-md-offset-1"> <h1 class="header-project" style="margin-bottom:10%">you're invited participate in <%= @project_invitation.project.try(:title) %></h1> </div> </div> <div class="row"> <div class="col-md-6 col-md-offset-1"> <div class="row"> <div class="col-md-12" style="padding:5%"> <div class="invitebody"> <%= @project_invitation.comment %> </div> </div> </div> <div class="row"> <div class="col-md-8 col-md-offset-2" style="padding:5%"> <div class="invitebody"> if you'd participate in project, reply <%= @project_invitation.expiry_date.try(:strftime, '%d %b %y') %> <br> <%= render 'rsvp' %> </div> </div> </div> </div> <div class="col-md-3 col-md-offset-1" style="padding: 10%"> <div class="row"> <div class="col-md-12"> <% if @creator_profile.image.present? %> <%= image_tag (@creator_profile.image.profile) %> <% else %> <div class="generaltext">image tbc</div> <% end %> </div> </div> <div class="row"> <div class="col-md-12"> <%= "#{@creator_profile.title} #{@creator.first_name} #{@creator.last_name}" %> </div> </div> <div class="row"> <div class="col-md-12"> <%= image_tag (@project.hero_image.thumb) %> </div> </div> <div class="row"> <div class="col-md-12"> <%= @project.title %> </div> </div> </div> </div> <div class="formminor"> <%= link_to 'back', project_invitations_path %> </div> </div> i put 'try' before 'title' because having other issues saving new invitation. wanted see if problem. expecting next error of same kind , flagging problem 'comment'. jumped on , raised error as:
undefined method `image' nil:nilclass that's strange me because i'm asking if there 1 present. also, code comes after question comment , doesn't seem have problem there.
this bit confusing.
undefined method `title' nil:nilclass
this means variable you're trying access not exist.
ruby treats nil objects nilclass, when call method on type of object, ruby thinks you're trying call method doesn't exist. it's not method issue lack of variable.
associations
here's code i'd expect see:
#app/models/project.rb class project < activerecord::base has_many :invitations end #app/models/invitation.rb class invitation < activerecord::base belongs_to :user belongs_to :project delegate :title, to: :project, prefix: true #-> prevents "law of demeter" end you can read law of demeter here.
i know model projectinvitations; have rule make model names succinct possible - helps clarity throughout app.
this allow call following:
#app/controllers/invitations_controller.rb class invitationscontroller < applicationcontroller def index @invitations = invitation.all end def new @invitation = invitation.new end def create @invitation = invitation.new invitation_params @invitation.save end def show @invitation = invitation.find params[:id] end private def invitation_params params.require(:invitation).permit(:user,:project) end end views (fix)
because haven't explained view you're calling erroneous variable inside, i'll have speculate:
#app/views/invitations/index.html.erb <% @invitations.each |invitation| %> <%= invitation.project_title %> <% end %> #app/views/invitations/show.html.erb <%= @invitation.project_title %> the key know view you're calling, , @variable have available. guess you're trying call @project_invitations variable in view it's not defined.
model
as aside, shouldn't have many associations in 1 model.
you can - there's no rule against - problem specification end creating small functionality 1 single purpose.
the best systems dry (don't repeat yourself) - reuse functionality time , time again.
for example...
has_one :educator_project_comment this changed following:
has_many :comments def educators type = "educator" end end you'd able have sti table setup comments, type column denoting dependent model you're calling (in case "educator").
Comments
Post a Comment