Chris
Chris

Reputation: 8020

Calling method from view

I have a problem calling a method from my view switches/index.slim:

=link_to 'Switch 1', switch_toggle_path, class: 'button'

and the corresponding route:

get '/switches', to: 'switches#relay_toggle', as: 'switch_toggle'

and the controller:

class SwitchesController < ApplicationController

  include PiPiper
  before_action :init_pins

  def init_pins
    @relay1 = PiPiper::Pin.new(:pin => 18, :direction => :out)
    @relay2 = PiPiper::Pin.new(:pin => 27, :direction => :out)
  end

  def relay_toggle
    @relay1.read == 0 ? @relay1.update_value(1) : @relay1.update_value(0)
    redirect_to '/'
  end
end

I only need to instantiate the pins once, but obviously I'm doing this every time i call, relay_toggle now. How can I make sure that they only get instantiated once? Can I put them somewhere that gets, loaded with the application? And if I did that, how would I then reference the @relay objects in the controller?

Also, should i make use of the helpers instead of declaring this in the controller? If so, how? I'm a bit out of clue as to what to do.

So any help or direction would be greatly appreciated

Upvotes: 1

Views: 600

Answers (3)

Richard Peck
Richard Peck

Reputation: 76774

Controller

When you mentioned you didn't know whether your method should be stored in the controller or a helper, you need to appreciate the role of the MVC programming pattern in Rails:

enter image description here

The way Rails works (and remember, Rails is based on top of Ruby -- it's a gem in actuality), which means that if you want to use a particular method / file in your system, it has to adhere to the MVC programming pattern as detailed above.

--

So the answer to the question of whether you should use a controller method or a helper, you'd use a helper if it was intended to be loaded after your view. Controller methods collate the relative data from your Model - allowing you to display it in the view:

Request -> Router -> Controller/Action -> View -> Helper 

This is the way in which your controller sets up the item

--

Initializers

Can I put them somewhere that gets, loaded with the application?

You may put them in an initializer -

#config/initializers/your_initializer.rb
RELAY_ONE = PiPiper::Pin.new(:pin => 18, :direction => :out)
RELAY_TWO = PiPiper::Pin.new(:pin => 27, :direction => :out)

If you use the code above, it will create two constants which will allow you to call them throughout the application (them having been already initialized)

If you do the above, it will give you the ability to remove the declarations from your controller, and just use the constants instead (considering, of course, that you only want the two objects to be defined):

#app/controllers/switches_controller.rb
class SwitchesController < ApplicationController
  def relay_toggle
    RELAY_ONE.read == 0 ? RELAY_ONE.update_value(1) : RELAY_ONE.update_value(0)
    redirect_to '/'
  end
end

Upvotes: 3

ex0ns
ex0ns

Reputation: 1116

You could also use Class variable

class SwitchesController < ApplicationController

  include PiPiper
  @@relay1 = PiPiper::Pin.new(:pin => 18, :direction => :out)
  @@relay2 = PiPiper::Pin.new(:pin => 27, :direction => :out)

  def relay_toggle
    @@relay1.read == 0 ? @@relay1.update_value(1) : @@relay1.update_value(0)
    redirect_to '/'
  end
end

But i'm not sure that's what you want to do

Upvotes: 1

Alex Tatarnikov
Alex Tatarnikov

Reputation: 353

Yes, you can init it once on server start and app init, just add initializer and declare constants

# config/initializers/relay.rb
RelayOne = PiPiper::Pin.new(:pin => 18, :direction => :out)
RelayTwo = PiPiper::Pin.new(:pin => 27, :direction => :out)

# controller

def relay_toggle
  RelayOne.read == 0 ? RelayOne.update_value(1) : RelayOne.update_value(0)
  redirect_to '/'
end

Upvotes: 0

Related Questions