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