displaying multiple view files on a single page -Rails - ruby-on-rails

In my Rails plugin, i want to display multiple view files onto a single page.
Say i want to append some view after the index view.
i am using
<% render :partial => "show" %>
in my index.erb
It works fine. But for better design I want to do the same thing from controller.
So, if i write in my contoller inside the index action
render :partial => "show"
only the show file gets rendered on the page.
Cant I use multiple partials?
Any comments/suggestions, please?

Actually, it would be more 'true' to the MVC architecture if that logic remained in the view. I think the cleanest way to do this is to include the partials in your index view using render like you've already done.
As far as I'm aware, you cannot 'append' views/partials to one another from the controller.

When I did this I added my three show page view partials
_storethenameofparitalshowviewoptionindatabase1
_storethenameofparitalshowviewoptionindatabase2
_storethenameofparitalshowviewoptionindatabase3
to my orders controller. I did this by running a migration
rails generate migration AddChose_Parital_Show_View_ToListings ordershowviewpartialoption:string
and adding a collection select to my listing controller.
<div class="field">
<%= f.label :ordershowviewpartialoption %>
<%= f.select :WHAT THE USER SEES IN THE DROP DOWN MENU FOR PARTIAL SHOW VIEW OPTION 2, [['Tictactoe Game',
'storethenameofparitalshowviewoptionindatabase1'],
['WHAT THE USER SEES IN THE DROP DOWN MENU FOR PARTIAL SHOW VIEW OPTION 2',
'storethenameofparitalshowviewoptionindatabase2'],
['WHAT THE USER SEES IN THE DROP DOWN MENU FOR PARTIAL SHOW VIEW OPTION 3',
'storethenameofparitalshowviewoptionindatabase3']], {}, {class: "form-control"} %>
</div>
and don't forget in controllers\listings_controller.rb
change this...
def listing_params
params.require(:listing).permit(:AAA, :BBB, :CCC)
end
to this...
def listing_params
params.require(:listing).permit(:AAA, :BBB, :CCC, :ordershowviewpartialoption)
end
in models\order.rb I have
belongs_to :listings
in models\listing.rb I
have has_many :orders
in my orders\show.html.erb
<%= render #order.listing.ordershowviewpartialoption %>

Related

would it be ok to create an instantiate an object in another controller?

I have a controller for customer. In the new action, I redirect to another page, which belong to the pages controller
class CustomersController < ApplicationController
def new
redirect_to register_path
end
Would it be possible to create the object in the registration action like this?
class PagesController < ApplicationController
def registration
#customer = Customer.new
end
end
I believe the setup is something like this: you have models in your application for a Customer and, say, an Agent. Your website users register as either and the desire is to have a single HTML page (URL) with both options available. They choose which one they are and submit some fields, say name/email/password. To keep it simple, without bothering with JavaScript to hide things behind tabs, you have something like:
**Customer**
Name: ___________
Email: __________
Password: _______
[Submit]
**Agent**
Name: ___________
Email: __________
Password: _______
[Submit]
You have a few options here to avoid your guilty feeling in the Rails controllers:
Go heavy client-side JavaScript. Don't have the new actions on the controllers. The JavaScript creates the page elements. The create action becomes a JSON API endpoint, thereby avoiding the problem in the Ruby application. This is obviously a significant architectural deviation from where I think you are today.
Use a little bit of JavaScript to dynamically load the correct 'partial' into the DOM when the user switches between the options. Avoids the underlying problem in the question by effectively separating the 'pages' out to the two controllers. The Pages→registration action does not need to set any instance variables for the view. The JavaScript deals with the partial loading. (see 'link_to' and the 'remote' option)
Don't include both forms in the same HTML page, just default to one, say the Customer one, and provide a link to navigate to the Agent one, e.g. a link in a tab, or a plain link like "Not a Customer? Register as an Agent." In this scenario, you have a neat mapping to the Ruby MVC design, each of the pages are just the new action of its relevant controller. The downside is a page load to change between the two options. This is the simplest, plainest choice … if you can get the boss to agree to the UX. PS: if you are using turbolinks, then the 'feel' of this option in the browser will be not far from option (2).
Stick to your design
Keep in mind that you will have difficultly dealing with error conditions and messages with option (4). You can do it, but the code won't be simple or easy to maintain.
If option (4) is a must, one simplification can be the create actions on each of the controllers rendering their own new in case of an error. If you submit the 'Agent' form from your starting page, with errors, to the Agents→create action, that action finishes with a render 'new' to show the user the Agents→new page. No 'customer' form is visible. You could then add a sprinkle of option (3) in there with a "Not an Agent? Register as a Customer." link under the form. Doing this greatly simplifies your error handling.
Which then leads to a suggestion for your original problem. Cheat. Don't have an #customer instance variable for the new actions (or the registration action). Use partials for the customer and agent forms, and pass in a new object to form_for, e.g.
pages/registration.html.erb
<%= render 'customers/new_form' %>
<%= render 'agents/new_form' %>
customers/new.html.erb
<%= render 'customers/new_form' %>
customers/_new_form.html.erb
<% form_for Customer.new do |f| %>
<%# include the inputs shared with the edit action %>
<%= render 'fields', f %>
<%= f.submit %>
<% end %>
customers/_fields.html.erb
<%# 'f' is one of the locals passed to the partial %>
<% f.input_field :name %>
<% f.email_field :email %>
<% f.password_field :password %>
customers/edit.html.erb
<% form_form #customer do |f| %>
<%= render 'fields', f %>
<%= f.submit %>
<% end %>
… then you would follow the same pattern for:
agents/new.html.erb
agents/_new_form.html.erb
agents/_fields.html.erb
agents/edit.html.erb

How to use the parent class view in STI rails

I have a Class Meeting from which derives MeetingOnline and MeetingOnSite.
I want to be able to use the views of Meeting for both MeetingOnline and MeetingOnSite.
Now when i do <%= render #meetings %> it asks me for meeting_on_lines/_meeting_on_line_partial. But i want him to use instead meetings/_meeting since what i want to show is shared between the 2 derived models.
In my controller i have #meetings = Meeting.all simply.
Any clues on how to achieve this ?
Explicitly set the partial. By jsut using render #meetings rails is making an assumption about which partial to use
<%= render partial: "meetings/meeting", collection: #meetings %>

Button "New Item" in Rails 4

I have a page that works with various models.
One of the items is "Language", where I select the language and level. But I can only insert a single language. I wonder what the best way to insert a "New" button to add another language, even if the edit page (because even though I need to include in the edit page too)
I'm using accepts_nested_attributes_for and simple_form.
Have tried several solutions but could not find any similar tutorial with what I need.
When you mention you have a page which works with various models, you need to remember views != models. In rails, views are used to show data you have defined in your controllers.
When you ask about inserting a new button to add a new language, this will be entirely dependent on your interface, and how you wish it to work. A good example would be this:
#app/views/languages/_new_lang.html.erb
<%= form_for Language.new, url: language_path do |f| %>
<%= f.text_field :name %>
<%= f.submit "Create" %>
<% end %>
A better way to do this will be to use ajax & render a layout-less element on your page:
#app/views/controller/your_view.html.erb
<%= button_to "Test", new_language_path, remote: true, id: "test" %>
#app/controllers/languages_controller.rb
Class LanaguageController < ActiveRecord::Base
layout Proc.new { |controller| controller.request.xhr? ? false : "application" }
end
#app/assets/javascripts/application.js.erb
$(document).on("ajax:success", "#test", function(data) {
$(data).appendTo("body");
});
This will allow you to send the required data through to your system to create a new language. Can be improved, so if you want to use it please let me know in the comments

Rails: Render a specific partial (other than an object's default)

I want to render some child items with something other than their default partial (i.e., app/views/child_items/_child_item.html.erb). The default one was scaffolded and it isn't great for public viewing of something, but I still want to keep it for back-end management purposes.
This is what I'm going for inside the view of the parent item, assuming a partial defined in app/views/child_items/_alternate_partial.html.erb:
<%= render containing_object.child_items, :partial => 'child_items/alternate_partial' %>
But the child items still render with their default partial.
Try this one:
<%= render 'child_items/alternate_partial', :collection => containing_object.child_items %>

How to list instances of a model and have a form to create an instance on the same view?

i have a model named 'chapter' (whose only attributes are 'name' and 'course__id') which belongs to "course" (and a course has_many chapters). on the course 'Show' view, I list all chapters for that course. Easy.
I want to add a form at the end of the list so that a user can easily create a new chapter.
so in my controller, I've added this:
#newchapter=#course.chapters.build
and the form on the view looks like this:
<% form_for([#course,#newchapter]) do |c| -%>
<%= c.label :name, "New Chapter" %>: <%= c.text_field :name %>
<%= c.submit 'Create' %>
<% end %>
(for the sake of clarity: it is outside of the #course.chapters.each block)
Now, the problem is that #course.chapters.size is the actual number of chapters + the empty one i created in the controller.
Is there a way to loop through all #course.chapters except the last (empty) one? or is there a better practice (i.e. not create #newchapter or not like this)?
thanks,
Pierre
You don't want to use #course.chapters.build here because this does add an empty chapter to the course. Instead you'll want to use Chapter.new and set the :course option like this.
#newchapter = Chapter.new(:course => #course)
It may not even be necessary to specify :course here depending on how you are using #newchapter.

Resources