Check form submitted values in ruby on rails - ruby

On my rails app I have a form on /addfiles where user can add file path in text boxes and this form is submitted to /remotefiles
I have created a route match '/remotefiles' => 'main#remotefiles'
and function in main controller
def remotefiles
render layout: false
end
and add remotefiles.html.haml in views/main
how can I show these submitted values on remotefiles, I think it can be done with render but not sure how can I use it to pass form values and show them on view.
Is there a way to check form data in ruby on rails just like php print_r function ?

Your form data is coming in via the params hash. The simplest way to respond with it would be
# MainController
def remotefiles
render json: params
end
If your form contained fields named foo and bar, you'll see those as well as some parameters Rails adds:
{
"foo": 1,
"bar": 2,
"controller": "Main",
"action": "remotefiles"
}
If you want to render them into a real template, write the HTML into app/views/main/remotefiles.html.erb. Rails will by default render a template matching your controller and action, or if you want a different one you can instruct Rails to render "path/to/other/template". Your template can access params too, but the more typical way to pass data into them is by setting instance variables in the controller.
# MainController
def remotefiles
#foo = params[:foo]
#bar = params[:bar]
end
# app/views/main/remotefiles.html.erb
<strong>Foo</strong> is <%= #foo %>
<strong>Bar</strong> is <%= #bar %>
Lastly, if you don't actually want to render the form data back to the browser, just inspect it during development, Rails.logger will print it into your server log.
# MainController
def remotefiles
Rails.logger.info(params[:foo], params[:bar])
end
You should read up on how Rails works - the getting started guides are very clear and helpful. Here's the one on rendering.

Related

How can I use views and layouts with Ruby and ERB (not Rails)?

How can I use views and layouts with Ruby and ERB (not Rails)?
Today i'm using this code to render my view:
def render(template_path, context = self)
template = File.read(template_path)
ERB.new(template).result(context.get_binding)
end
This works very well, but how can I implement the same function, but to render the template inside a layout? I want to call render_with_layout(template_path, context = self), and so that it will have a default layout.
Since you tagged it with Sinatra I assume that you us Sinatra.
By default you view is rendered in your default layout called layout.erb
get "/" do
erb :index
end
This renders your view index with the default layout.
If you need multiple layouts you can specify them.
get "/foo" do
erb :index, :layout => :nameofyourlayoutfile
end
* If you don't use Sinatra you may want to borrow the code from there.
If you use the Tilt gem (which I think is what Sinatra uses) you could do something like
template_layout = Tilt::ERBTemplate.new(layout)
template_layout.render {
Tilt::ERBTemplate.new(template).render(context.get_binding)
}
If you are using Sinatra so it has a good docimentation and one of the topics it's nested layouts (see Sinatra README)
Also good idea to use special default layout file (layout.haml or layout.erb in your view directory) This file will be always use to render others. This is example for layout.haml:
!!!5
%html
%head
##<LOADING CSS AND JS, TILE, DESC., KEYWORDS>
%body
=yield ## THE OTHER LAYOUTS WILL BE DISPALYED HERE
%footer
# FOOTER CONTENT
Thanks for all the answers!
I solved it finally by doing this, I hope someone else also can find this code useful:
def render_with_layout(template_path, context = self)
template = File.read(template_path)
render_layout do
ERB.new(template).result(context.get_binding)
end
end
def render_layout
layout = File.read('views/layouts/app.html.erb')
ERB.new(layout).result(binding)
end
And I call it like this:
def index
#books = Book.all
body = render_with_layout('views/books/index.html.erb')
[200, {}, [body]]
end
Then it will render my view, with the hardcoded (so far) layout..

Rendering partial that belongs to another controller

I've got a menu controller, which is set as my root controller in routes.rb. In my menu view, i try and render the _lights.slim partial with = render :partial => 'lights/lights' but i get the following error: undefined method `lights' for nil:NilClass
MenuController:
class MenuController < ApplicationController
def index
end
end
Menu View (index.slim)
ul.tabs.vertical data-tab=""
li.tab-title.active
a href="#panel1a" Tab 1
.tabs-content.vertical
#panel1a.content.active
= render :partial => 'lights/lights'
LightsController
class LightsController < ApplicationController
before_action :discover_lights
include LIFX
#client = LIFX::Client.lan
#client.discover!
3.times do
#client.lights.refresh
sleep (0.5)
puts "Found #{#client.lights.count} with labels #{#client.lights}"
end
def index
end
def new
end
def light_toggle
light = #client.lights.with_label(params[:label])
light.on? ? light.turn_off : light.turn_on
redirect_to '/'
end
private
def discover_lights
#client = LIFX::Client.lan
#client.discover!
end
end
Lights View (_lights.slim)
h1.subheader LIFX Lights
table.light-table
thead
tr
th Light
th Status
th Power On/Off
th Brightness
tbody
-#client.lights.map do |c|
tr
th #{c.label}
th #{c.power}
th =link_to 'Toggle', light_path(:label => c.label)
th #{c.color.brightness.round(2) * 100}%
end
Routes.rb
root 'menu#index'
get '/lights', to: 'lights#index'
get '/lights/:label', to: 'lights#light_toggle', as: 'light'
I know this is a no brainer, but i'm stuck as to what to do here. I'm thinking it must be an issue with the way that when Menu#Index is called, I never knows about my LightsController, and so #client.blablabla will never make sense. But how will I make my app know about my LightsController when the view is loaded as a partial
Partials
You must appreciate that Partials are not controller-dependent (being stored in a controllers' view directory does not tie them for use with that controller)
This means if you have the functionality to support the partial in another controller, you should be able to use it in different parts of your app
--
Error
This leads us to the identification of the problem you're receiving.
It's not the calling of the partial which causes an issue - it's how you're referring to the code inside it:
undefined method `lights' for nil:NilClass
The error is clearly that you're trying to call the lights method on an object / variable which doesn't exist. This is defined inside the partial itself here:
#client.lights.map do |c|
Therefore, you need to be able to pass the correct data to the partial, enabling it to load the #client object without being dependent on the controller
--
Fix
To do this, you may wish to consider using partial locals -
<%= render partial: "lights/lights", locals: {client: #client} %>
This means that every time you call the partial, you'll have to pass the #client object into the client local var, thus allowing the partial to run controller-independently.
Here's how you'd handle it in the partial itself:
#app/views/lights/_lights.slim
- client.lights.map do |c|

Rails helper for Haml

I have a bit of HAML code that gets repeated in something like 10 views and would like to put it into a helper of some kind. Doing a search here produced some interesting results but ultimately no answers, so:
In application_helper.rb I have this:
def pagination_helper(object)
haml_tag :div, :class => 'apple_pagination page_info' do
page_entries_info #book_formats
paginate #book_formats
end
end
In the view template I have this:
- pagination_helper(#book_formats)
If I try calling it with = to output something I get an error.
The above will not give me an error but it won't call the methods either. I get empty divs.
Ultimately the code I want to repeat is this:
.apple_pagination.page_info
= page_entries_info #book_formats
= paginate #book_formats
The code would be the same except the object would change and I send that from the view template. For example #book_formats would change to #dvds, etc.
The block passed to haml_tag doesn’t automatically get added to the output. You need to use haml_concat:
def pagination_helper(object)
haml_tag :div, :class => 'apple_pagination page_info' do
haml_concat(page_entries_info #book_formats)
haml_concat(paginate #book_formats)
end
end

Rails calling action from view

Hopefully have a simple question here but I cannot for the life of me seem to find the answer. Just started working with RoR but came from ASP MVC before. I am having an issue rendering partial views whose local variables are not necessarily tied to the variables of the main view. For instance, with a blog I am trying to render a sidebar that will link to the archive.
def sidebar
#blog_posts = Blog.all(:select => "created_at")
#post_months = #blog_posts.group_by { |m| m.created_at.beginning_of_month }
end
The partial view _sidebar is as follows:
<div class="archives">
<h4>Blog Archive</h4>
<% #post_months.sort.reverse.each do |month, posts| %>
<%= link_to "#{h month.strftime("%B %Y")}: #{posts.count}", archive_path(:timeframe => month) %>
<% end %>
</div>
The problem I am having is that if I simply do a render 'sidebar' within my main view the action does not seem to be called and #post_months is always nil. Is it possible to call the action directly from the view and simply have that render 'sidebar'? In ASP MVC I used to just make the sidebar a ChildActionOnly and Render.Action from the mainview, but in RoR I am completely clueless. Any help is appreciated!
I think what's happening here is that yout sidebar is being treated as a partial and your controller method is never being called. In that case I'd put the code currently contained in the sidebar controller method into either the ApplicationHelper module or the helper module of the current view, depending on whether or not you'd need to render the sidebar from other views.
You'd need to adapt the code a bit to work in a module. Rather than setting a session variable you should have the methods return the values you want.
Module SomeModule
def blog_posts
Blog.all :select => "created_at"
end
def post_months
blog_posts.group_by { |m| m.created_at.beginning_of_month }
end
end
Of course, that may very well need to be refactored and might not work as written, but that's the general idea I'd go with.
Good Luck.

Ruby Mixins and Instance variables

Is there a best practice way to pass params to mixed-in methods?
The class using the mixin could set up instance variables which mixed-in methods expect, or it could pass all necessary params as arguments to mixed-in methods.
The background to this is that we have a Rails controller which does publishing of content - but other controllers and even Models need to be able to "act as publshers" so I'm factoring the controllers methods into a Module which I'll mixin as needed.
Here, for example, is code from a Rails Controller which needs to "act as publisher" and it calls a mixed-in method question_xhtml()...
def preview
#person = Person.find params[:id]
#group = Group.find params[:parent_id]
#div = Division.find params[:div_id]
#format = 'xhtml'
#current_login = current_login
xhtml = person_xhtml() # CALL TO MIXED-IN METHOD
render :layout => false
end
Ultimately question_xhtml needs all that stuff! Is this approach reasonable, or would it be better to do
def preview
person = Person.find params[:id]
group = Group.find params[:parent_id]
div = Division.find params[:div_id]
format = 'xhtml'
xhtml = person_xhtml(person, group, div, format) # CALL TO MIXED-IN METHOD
render :layout => false
end
...or something else?
I think you should be able to do:
module ActAsPublisher
def person_xhtml
do_stuff_with(#person, #group, #div, #format, #current_login)
# eg. use instance variable directly in the module
end
end
class WhateverController < Application Controller
act_as_publisher
...
end
if you used script/generate plugin act_as_publisher.

Resources