How to Embed Ruby.Rb File via Form in a Way That Ruby.Rb Would Be Executed and Results Visible in View

How do I embed ruby.rb file via form in a way that ruby.rb would be executed and results visible in view

A simple way to put a basic form up as a web site is Sinatra. The following is a web app in a single file, using Sinatra.

#!/usr/bin/env ruby
require 'sinatra'

get '/' do
erb :guess
end

post '/' do
@guess = params[:guess].to_i
if @guess == 10
@message = "Correct!"
else
@message = "Try again..."
end
erb :guess
end

__END__
@@ layout
<html>
<body>
<%= yield %>
</body>
</html>

@@ guess
<form action="" method="post">
<p>Guess a number: <input type="text" name="guess"/></p>
<p><%= @message %></p>
</form>

Install the sinatra gem and run the file. You'll see a message like

== Sinatra/1.3.3 has taken the stage on 4567

Then point your browser at http://localhost:4567/ and your app is online.

whenever gem schedule.rb file: doesn't recognize RAILS_ROOT variable

Whenever doesn't require or depend on Rails at all, so when it runs, RAILS_ROOT is not defined, however because whenever's schedule.rb is generally kept in /config/schedule.rb, we can make an assumption that it is in a rails project, and set our own RAILS_ROOT like this:

# in schedule.rb
RAILS_ROOT = File.dirname(__FILE__) + '/..'

Edit: in the case that you actually need Rails loaded, do this:

# in schedule.rb
# this will require config/environment and load your entire rails environment
require File.expand_path(File.dirname(__FILE__) + "/environment")

Rails - How to pass data between Rails controller and JavaScript Stimulus controller to dynamically change view

This sounds like plain old pagination.

If there could be thousands of movies you'd be generation markup/html for thousands of movies. With pagination you'd get get 3 records at a time. Could even use a turbo-frame to replace the next 3.

But if you really want to do what your thinking, you'd have hide all cards except for the first 3, then use stimulus to get the next or last three cards.

A test example

Controller

class TestController < ApplicationController
def index
@movies = Array.new(100) { |e| e = e + 1 }
end

Template using slim

.bg-white
div[data-controller="movies"]
- cnt = 0
button.btn[data-action="click->movies#last_set"] Last
button.btn[data-action="click->movies#next_set"] Next
- @movies.each do |m|
- if cnt < 3
div[data-movies-target="movie" class='block'] = "This is movie #{m}"
- cnt += 1
- else
div[data-movies-target="movie" class='hidden'] = "This is movie #{m}"

Stimulus Controller

import { Controller } from "@hotwired/stimulus"

// Connects to data-controller="movies"
export default class extends Controller {
static targets = ['movie']

connect() {
this.size = this.movieTargets.length
this.idx = 0
// this.idx points to the first current cards (3 for example)
}

next_set() {
let curr = this.idx
this.idx = curr + 3 // set new idx
if (this.idx > this.size) {this.idx = this.size - 3}
for (var i = curr; i <= curr + 2; i++) {
this.movieTargets[i].classList.add("hidden")
}
for (var i = this.idx; i <= this.idx + 2; i++) {
this.movieTargets[i].classList.remove("hidden")
}
// console.log(`idx = ${this.idx}`)
}

last_set() {
let curr = this.idx
this.idx = curr - 3 // set new idx
if (this.idx < 0 ) {this.idx = 0}
for (var i = curr; i <= curr + 2; i++) {
this.movieTargets[i].classList.add("hidden")
}
for (var i = this.idx; i <= this.idx + 2; i++) {
this.movieTargets[i].classList.remove("hidden")
}
// console.log(`idx = ${this.idx}`)
}

}

Just a rough example.

EDIT Not very good at javascript and cleaned up the stimulus controller, added variable number of elements to display and work with pages instead of elements.

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
static targets = ['perPage','movie','status','nextBtn','lastBtn']

connect() {
this.size = this.movieTargets.length
this.page = 0
this.perPage = Number(this.perPageTarget.innerHTML)
this.pages = Math.floor(this.size/this.perPage)
if ((this.size % this.perPage) > 0) {this.pages += 1}
this.setStatus()
// this.page points to the current set of cards (3 for example)
}

next_set() {
if (this.page == (this.pages - 1)) {return}
this.hide()
this.page += 1
this.show()
this.setStatus()
}

last_set() {
if (this.page == 0) {return}
this.hide()
this.page -= 1
this.show()
this.setStatus()
}

hide(){
let curr = this.page * this.perPage
let last = curr + this.perPage - 1
while(curr <= last){
if (curr >= 0 && curr < this.size) {
this.movieTargets[curr].classList.add("hidden")
}
curr++
}
}

show(){
let curr = this.page * this.perPage
let last = curr + this.perPage - 1
while(curr <= last){
if (curr >= 0 && curr < this.size) {
this.movieTargets[curr].classList.remove("hidden")
}
curr++
}
}

setStatus(){
this.statusTarget.innerHTML = `Page ${this.page + 1} of ${this.pages}`
if (this.page == 0) {
this.lastBtnTarget.classList.add('hidden')
}else{
this.lastBtnTarget.classList.remove('hidden')
}
if (this.page == this.pages) {
this.nextBtnTarget.classList.add('hidden')
}else{
this.nextBtnTarget.classList.remove('hidden')
}
}
}

search function not working - Ruby on rails

Instead of using 2 different methods for search, try combining both in index method. Your index method will now look as follows:

def index
if params[:search]
@availabilities = Availability.unmatched.search(search_params[:start_city])
else
@availabilities = Availability.unmatched
end
end

Change the form url to search_rides_path. This way search results will be rendered in same view upon form submission.

If else statements in .html.erb in views

Unless you can think of a way to re-write this as a helper method, you're basically stuck with it looking kind of ugly. That's just how ERB is, as it was intended to be a minimal way of injecting Ruby into an otherwise plain-text template, not as something necessarily streamlined or elegant.

The good news is a syntax-highlighting editor will usually make your <% ... %> ERB blocks look visually different from your HTML so that can dramatically improve readability.

It's also why other representations like HAML have been created where that syntax is a lot less cluttered:

- if some_condition_previusly_established_in_a_controller
.one 123
- else
.two something else

How can create records using input date and save the param using ROR?

There are some problems in the codes.

1. params are only accessible in controller, you wanted to read it in your model

There are many ways to pass params value to model, for example, you can add attr_accessor :dateadd to the model.
But I think a clearer way is to extract the behavior in :save_default_values into a new public method and call it in the controller.

2. params[:name] is an attribute in the model, you should use strong parameters to assign the attributes

3. it's apparently that dateuser is a column of user_jobs, isn't it?

We can use date_field to pick the date and also add this field into strong parameter.

4. After a record saved, that record is not new record any more since it has id value.

Try to use after_create or after_save on: :create. However, I don't use this callback in the code below, but it's just personal choice :)

# user_job.rb
class UserJob < ApplicationModel
# add new public method
def add_additional_jobs!(days)
(1..days).each do |n|
UserJob.create!(name: name, dateuser: dateuser + n.days)
end
end
end

# user_jobs_controller.rb
class UserJobsController < ApplicationController
def new
@user_job = UserJob.new
end

def create
UserJob.transaction do
@user_job = UserJob.create!(user_job_params)
if params[:dateadd].to_i > 0
@user_job.add_additional_jobs!(params[:dateadd].to_i)
end
end
end

private

def user_job_params
params.require(:user_job).permit(:name, :dateuser)
end
end

Then in the view

<%= form_with(model: user_job) do |form| %>
Name:<%= form.text_field :name %>
Date: <%= form.date_field :dateuser %>
Date added: <%= text_field_tag "dateadd", params[:dateadd].to_i %>
<%= form.submit %>
<% end %>

Convert working Ruby on Rails form to AJAX

You're on the right track, now you need to modify the def ping action with a respond_to block.

def ping
ping_host(params[:ip])
save_host(params[:ip])

respond_to do |format|
format.html { redirect_to tools_path } ## if you still want to have html
format.js
end
end

and create a file called view/tools/ping.js.erb where you have javascript that will be run and returned asynchronously

$("#output").html("<%= j @results %>"); 

The <%= %> block will be evaluated first and replaced with the output of that ruby code. Then this will be inserted into the #output div.

Calling a CoffeeScript function across all views (Ruby on Rails)

Try something like this?

scrollToError = ->
$('*[data-scroll-to-error="true"]').click ->
alertElement = $('.alert-danger:visible:first')

if alertElement.length > 0
$('html, body').animate {
scrollTop: alertElement.offset().top - 220
}, '1000'

# Run with turbolinks.
$(document).on 'page:change', scrollToError

and a submit button with the data-scroll-to-error attribute set.

<input type="submit" data-scroll-to-error="true" />

I find this statement of yours confusing:

I have the file included in our application.rb file in the config
folder, so that it can be called in any HTML file in the views section

Assuming this is a standard Rails project, you should have included the file containing the Coffeescript code in assets/javascripts/application.js (the manifest file), and since application.js is the JS file required in the layout (isn't it? :-/), this code would execute on all of your views. I don't see how config/application.rb is involved here.

Update: Adding more information.

If you're unsure about how to application.js file (a manifest file) is used, please take the time to go through Rails' official documentation about it (especially the section about manifests).

http://guides.rubyonrails.org/asset_pipeline.html#manifest-files-and-directives

In your case, you'll want to modify application.js to include:

...
//= require error
...

Basically, you list all the asset files that you want loaded along with all pages that use a layout (probably application.html.erb), and then mention only the manifest file the layout. That way, Rails can concatenate and minify to generate a single asset file. The default application. manifest files are automatically precompiled - so you don't need to manually add new assets to the precompile list.

The reason why I wrote the selector as *[data-scroll-to-error="true"] was personal preference - the code reads better to me that way. If you're sure that the ID submit is (and will be in future) applied only to elements that require scrolling to error, then it's fine to change the first selector to $('#submit').click ->



Related Topics



Leave a reply



Submit