lflores
lflores

Reputation: 3800

Rails - creating and editing in a different controller/model

I have a nested reviews model with a polymorphic association with majors, careers, and schools. I want users to review these majors, schools, and careers on their show page. In addition, I want them to see all the reviews they've made on their profile page.

I can get the reviews to show but I am having trouble with adding, editing, and deleting them because I want them to be able to do these actions when they see their review on the major, school, career, or their profile page.

Here are my routes:

resources :majors, :schools, :careers do 
  resources :reviews
end

Here are my associations:

Major.rb, School.rb, Career.rb

has_many :reviews, as :reviewable

Review.rb

belongs_to :user
belongs_to :reviewable, polymorphic: true

User.rb

has_many :reviews

Here is my reviews_controller.rb:

before_filter :reviewable

def index
  @reviews = @reviewable.reviews
  @major = Major.includes(:reviews => :user).find_by_slug(params[:id])
end

def show
  @review = @reviewable.reviews.find(params[:id])
end

def new
  @review = @reviewable.reviews.build
  @review.user = current_user
end

def edit
  @review = @reviewable.reviews.find(params[:id])
  raise(ActiveRecord::RecordNotFound, "Access Denied") if @review.user != current_user
end

def create
  @review = @reviewable.reviews.build(params[:review])
  @review.user = current_user
  @reviews = @reviewable.reviews
end

def destroy
  @review = @reviewable.reviews.find(params[:id])
  @review.destroy
  raise(ActiveRecord::RecordNotFound, "Access Denied") if @review.user != current_user
end

def reviewable
  @reviewable = if params[:major_id]
    Major.find_by_slug!(params[:major_id])
   elsif params[:school_id]
    School.find(params[:school_id])
   elsif params[:career_id]
    Career.find(params[:career_id])
  end
end

In order to create, view, and edit a review for a major, for instance, they will be doing it on the major show page. This is what I have on majors_controller.rb:

def show
  @reviews = Review.includes(:user)
  @reviews_most_liked = Review.order("created_at DESC").limit(4)
end

I'm trying to make it so they can add and edit from a modal window inside the major, school, and career show page. Here's what I have in the modal window:

<%= simple_form_for([@reviewable, @review]) do |f| %>
  <%= f.error_notification %>

  <div class="form-inputs">
    <%= f.input :review %>
  </div>

  <div class="form-actions">
    <%= f.button :submit %>
  </div>
<% end %>

Upvotes: 3

Views: 2307

Answers (1)

lflores
lflores

Reputation: 3800

I figured it out. The problem was with mapping the right instance variables with the correct action and controller. Most of instance variables were placed in my majors_controller.rb, school_controller.rb, and careers_controller.rb show action. This is what part of my majors_controller.rb show action - I was mistakenly placing them in the create action and delete action. But, once I sat and thought about it I realized it's all happening within the show page. Here's what my controller for my models look like:

def show
    @reviewable = @major
    @reviews = @reviewable.reviews #show reviews
    @reviews_most_liked = @reviewable.reviews.order("created_at DESC").limit(2)
    @reviews_most_liked_2 = @reviewable.reviews.order("created_at DESC").limit(2).offset(2)
    @review = @reviewable.reviews.build(params[:review]) #create a review
    @review.user = current_user #connect the created review to the user
end

Then in my majors show.html.erb page I was able to call the show method by calling the person who gave the review:

<%= review.user.profile_name %>

and the review itself:

<%= review.review %>

That displays the review. I then needed to create, edit and delete. In order to create I just had to get the instance variables correct. Once I got them correct in the right controller and under the correct action (majors controller show action) then in the modal window on the majors show page I called the form partial:

 <%= render 'reviews/form' %>

which looks like this:

<%= simple_form_for([@reviewable, @review]) do |f| %>
  <%= f.error_notification %>
  <div class="form-inputs">
    <%= f.input :review, :input_html => { :class => "span4", :rows => 10 }, 
                         label: false, 
                 placeholder: 'Help others by sharing what you\'ve learned as a major.' %>
  </div>
  <div class="modal-footer">
    <button class="btn cancel-modal-review" data-dismiss="modal" aria-hidden="true">Cancel</button>
    <%= f.submit 'Share My Review', :class => "submit-feedback" %>
  </div>
<% end %>

Upvotes: 2

Related Questions