Reputation: 8020
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
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:
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
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
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