Why does Pagy return nil in Sinatra? - ruby

#pagy is returning nil in my view (#<NoMethodError: undefined method 'pages' for nil:NilClass>).
It works as expected in the console:
> #pagy.pages
=> 25
> pagy_nav(#pagy)
=> "<nav class=\"pagy-nav pagination\"...
I've added the Pagy includes in the Folders Controller:
class FoldersController < ApplicationController
include Pagy::Backend
get '/folder/:permalink' do
#pagy, #pagination = pagy(Article.all)
end
helpers do
include Pagy::Frontend
end
end
I'm calling it in the Folder's Show View:
<%= pagy_nav(#pagy) if #pagy.pages > 1 %>
Any ideas why #pagy is returning nil inside the view?
Any advice on using Pagy in a Sinatra app?

#pagy needs to be called before your erb call.
Like this:
#pagy, #articles = pagy(#articles.order(position: :desc), items: 50)
erb :'folders/show_folder'
Not like this:
erb :'folders/show_folder'
#pagy, #articles = pagy(#articles.order(position: :desc), items: 50)

Related

Konacha adds 'iframe' to image urls that have the src attribute set programmatically

I have just managed to get Konacha running for my client side integration tests.
Konacha runs the ember application in an iframe for testing. In my app, I create img elements programmatically based on user actions. When I set the 'src' attribute the resulting url that is used to fetch the image file from the server has the '/iframe' part added to it like so:
http://0.0.0.0:3500/iframe/assets/regensberg/regensberg_1.jpg
Which gives a 404 (Not Found)
The code does run correctly when I serve it from a regular rails development server
rails s
The correct url should read:
http://0.0.0.0:3500/assets/regensberg/regensberg_1.jpg
Any ideas why it is doing this an how to get around it?
* Edit *
Looking into the Konacha code I find the routes defined in konacha/config/routes.rb
Konacha::Engine.routes.draw do
get '/iframe/*name' => 'specs#iframe', :format => false, :as => :iframe
root :to => 'specs#parent'
get '*path' => 'specs#parent', :format => false
end
We see that this request gets passed to the iframe method in the specs controller.
konacha/app/controllers/konacha/specs_ controller.rb shows us where the 404 message comes from.
module Konacha
class SpecsController < ActionController::Base
rescue_from Konacha::Spec::NotFound do
render :text => "Not found", :status => 404
end
def parent
#run_mode = params.fetch(:mode, Konacha.mode).to_s.inquiry
#specs = Konacha::Spec.all(params[:path])
end
def iframe
#spec = Konacha::Spec.find_by_name(params[:name])
#stylesheets = Konacha::Engine.config.konacha.stylesheets
end
end
end
Looking into the model, we see where the Spec::NotFound comes from:
module Konacha
class Spec
class NotFound < StandardError
end
def self.all(path = nil)
paths = Konacha.spec_paths
paths = ENV["SPEC"].split(",") if ENV["SPEC"]
paths = paths.map { |p| new(p) }
if path.present?
paths = paths.select { |s| s.path.starts_with?(path) }.presence or raise NotFound
end
paths
end
def self.find_by_name(name)
all.find { |s| s.asset_name == name } or raise NotFound
end
attr_accessor :path
def initialize(path)
#path = path
end
def asset_name
path.sub(/(\.js|\.coffee).*/, '')
end
end
end
With the above info, we see why we get the error message instead of the image file when we send the get request to the path that includes 'iframe'. So, why does the URL include 'iframe'?
Looking into the parent view code:
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>Konacha Tests</title>
<%= stylesheet_link_tag "konacha", :debug => false %>
<%= javascript_include_tag "mocha", "konacha/parent", :debug => false %>
<%= javascript_include_tag("konacha/runner", :debug => false) if #run_mode.runner? %>
</head>
<body>
<% #specs.each do |spec| %>
<%= content_tag :iframe, "", :src => iframe_path(spec.asset_name), :class => "test-context", "data-path" => spec.path %>
<% end %>
<div id="mocha"></div>
</body>
</html>
we see that the src for the iframe is the iframe path, which from the route above should be:
0.0.0.0:3500/iframe/#{spec.assetName}
I set the img src paramter like this:
img.src = "assets/" + filename
the browser prepends "0.0.0.0:3500/iframe/" to this before making the request. This seems to be causing the real trouble. How to prevent the iframe from including this part in the base URL?
* Finish Edit *
By the way, can someone with a high-enough karma(>1500) create a Konacha tag?
assets/dir/filename.jpg is a relative path; it is interpreted relative to the base URL of the page, which is http://0.0.0.0:3500/iframe/, producing http://0.0.0.0:3500/iframe/assets/dir/filename.jpg. You'll want to use the absolute path /assets/dir/filename.jpg instead, with a leading slash.

Variable in View is always nil

I am new to ruby. I created a new action in controller where I set variable test1
def tsload
#test1 = '00:00'
respond_to do |format|
format.html {
render :template => 'tsload'
}
end
end
But in my View the value of variable test1 is always nil. It seems that it is undefined.
<p>Test</p>
<% if #test1.nil? %>
<p>nil</p>
<% end %>
I do not understand what is wrong. In older actions in my controller everything works OK. Can anyone please help me?
This is line from my routes.rb
match 'wktime/tsload', :to => 'wktime#tsload', :via => [:get]

Render a complex nested form with preopulated values from AJAX in Rails 3.2

I'm building a web application that needs a somewhat complex form to function.
I have five models: Grid, Row, Value, VariableGroup and Variable (these are not the actual names but useful for reference).
A Grid has many rows, and a Row has many values. Also, a Grid belongs to a VariableGroup, which is a sort of a model that groups many variables for their grandchildren.
A Variable, of course, belongs to a VariableGroup, and the key here, is that a Value belongs to a Variable as well.
The models:
class Grid < ActiveRecord::Base
belongs_to :variable_group
has_many :rows
accepts_nested_attributes_for :rows, :allow_destroy => true
end
class Row < ActiveRecord::Base
belongs_to :grid
has_many :values
accepts_nested_attributes_for :values, :allow_destroy => true
end
class Value < ActiveRecord::Base
belongs_to :variable
belongs_to :row
end
class Variable < ActiveRecord::Base
belongs_to :variable_group
end
class VariableGroup < ActiveRecord::Base
has_many :variables
has_many :grids
end
The expected behavior is as follows to create a new Grid:
The user must select a VariableGroup from a dropdown select. This select has a jQuery handler for .change, that must instantiate a nested Row model, which in turn instantiates as many Value models as Variables exist in the Grid's selected VariableGroup.
This is the grid form:
= simple_form_for #grid, :html => {:class => 'form-horizontal' } do |f|
= f.input :name
= f.association :variable_group_id
.rows_and_values_container
= f.simple_fields_for :rows do |p|
= render 'rows_fields', :f => p
= f.submit
And this is the attached listener:
$('document').ready(function(){
$('#grid_variable_group_id').change(function(){
$.ajax({url: '/grids/load_variables_in_values',
data: 'selected=' + this.value,
dataType: 'script'})
});
});
And this is the load_variables_in_values action:
def load_variables_in_values
#grid = Grid.new
row = #grid.rows.build
#variables = Variable.where(:variable_group_id => params["selected"])
#variables.each do |variable|
value = row.values.build
value.variable_id = variable.id
end
# render :partial => "test_data_sets_fields"
respond_to do |format|
format.js
end
end
The respond_to block yields the control to a js.erb view that should load the following partial, but I'm stuck here as I don't know where and how to handle the loading of the partial and its sub-partials:
#rows_fields partial
= f.input :name
= f.input :grid_id #Should be hidden
= f.simple_fields_for :test_data_values do |p|
= render 'values_fields', :f => p
#values_fields partial
= f.input :value
= f.input :row_id #Should be hidden
= f.input :variable_id #Auto-assigned
I think I'm 80% there, but I don't know how to load the partials with its corresponding values with the data that I process in the custom controller action that was called via AJAX.
I know this is a mile long post, so thanks in advance if you got ºhere.
Rendering a partial from the custom controller action instead of using a respond_to block worked.
I just had to hard-code the scope of the form (reading the source of the auto generated form and using its structure as a string, together with a random value, and it worked.
You could try this:
respond_to do |format|
format.js { render :partial => "rows_fields" }
end
With the same thing for value_fields (or stick them together). Sorry if I misunderstood your question though...kinda sleepy.

Multiple Contact Forms - Rails 3

I am relative newbie to all this, so sorry if this sounds mad!
I have used this tutorial: http://www.railsmine.net/2010/03/rails-3-action-mailer-example.html
And I have a new contact form working great.
The controller is at app/controllers/support_controller.rb
class SupportsController < ApplicationController
def new
# id is required to deal with form
#support = Support.new(:id => 1)
end
def create
#support = Support.new(params[:support])
if #support.save
redirect_to('/', :notice => "Support was successfully sent.")
else
flash[:alert] = "You must fill all fields."
render 'new'
end
end
end
And the model at /app/models/support.rb
class Support
include ActiveModel::Validations
validates_presence_of :email, :sender_name, :support_type, :content
# to deal with form, you must have an id attribute
attr_accessor :id, :email, :sender_name, :support_type, :content
def initialize(attributes = {})
attributes.each do |key, value|
self.send("#{key}=", value)
end
#attributes = attributes
end
def read_attribute_for_validation(key)
#attributes[key]
end
def to_key
end
def save
if self.valid?
Notifier.support_notification(self).deliver!
return true
end
return false
end
end
The views however only work in views/supports/new.html.rb (rendered - views/supports/_form.html.erb)
So I can call the Model / Controller from localhost:3000/support/new but if I try and render the same form in another view from the root directory e.g. app/view/contact.html.erb I get:
undefined method `model_name' for NilClass:Class
I think this is because it is calling the support model away from the supports directory.
Do I have to create an instance on #support so it can be called? If so what is the best way of doing that? I think I am nearly there. I just want the contact form on multiple pages not just in suppport/new
Thanks
Charlie
Yes, you would need to create a #support variable in each action you wish to render your form.
Another option would be to refactor the form to take a parameter, that way you're a bit more flexible. For example, from your view:
<%= render :partial => "supports/form", :locals => {:support => #support} %>
Now, instead of referring to #support in your _form.html.erb, you'd refer to simply support as it's a local_assign.
Yet another option would be to refactor the form a little further, and worry about creating the actual form tag outside of the partial.
Such as:
app/views/supports/new.html.erb
<%= form_for #support do |form| %>
<%= render :partial => "suppports/form", :object => form %>
<% end %>
app/views/supports/_form.html.erb
<%= form.text_field :foo %>
<%= form.text_field :bar %>
...
In this case, when you render a partial with the object option, you will get a local variable in your partial with the same name as the partial. You maintain a little bit more flexibility in the path of your form, but can still render the meat of what a Support object is inside of the form while remaining consistent across your app.
To clarify, you could use this somewhere else by doing something like:
app/views/foos/_create_foo_support.html.erb
<%= form_for #foo.support do |form| %>
<%= render :partial => "supports/form", :object => form %>
<% end %>
You have to pass #support object wherever you use your contact form. It's working in SupportsController#new because you initialize the variable there. In all other places where you want to use the form, you'll have to do the same.

Form behavior posting nested resource

I am using Ruby on Rails 3 and I would like to change its conventional behavior on posting a form in order to post from a signup action to the create action instead that from the new action. That is, I would like to use the signup action instead of the (conventional) new action in my User controller and trigger the create action to save my model data that contains nested resources.
In my /config/routes.rb file I have:
resources :users do
collection do
get 'signup'
end
resource :profile
end
In my /app/controllers/users_controller.rb I have
class UsersController < ApplicationController
def signup
#signup_user = User.new(params[:user])
#signup_user.build_profile # NOTE: Nested resource
...
end
def create
...
#signup_user.save
respond_to do |format|
format.html { render :action => :signup } # signup.html.erb
end
end
end
In my /app/views/users/signup.html.erb file I have
<%= form_for #signup_user do |f| %>
...
<% end %>
My problem is that if I submit the above form, I will be redirected to the index action of the user controller and not to the create action I expect. It seams that the form posts only to the index action.
How can I solve the problem?
I tryed to use the following
<%= form_for( :user, #signup_user, :url => { :controller => "users", :action => "create" }, :html => { :method => :post } do |f| %>
but I have still the problem: I am redirected to the index action.
SOLUTION
The problem did seam to be in the routers.rb. The correct code was
resources :users do
collection do
get 'signup'
post 'create'
end
resource :profile
end

Resources