I don't know if I'm getting the whole documentation totally wrong but there is an issue I'm dealing with since two days and I just don't get what I'm doing wrong. I'm using fxruby to built a small GUI, and I need a progressbar within that. When I initialize it with no parameters its just ridiculously small, so I tried to use the barSize option (wich is responsible for the width, at least the documentation says so). This is my source code:
require 'fox16'
require 'pp'
include Fox
class Test < FXMainWindow
def initialize(app)
super(app, "Test")
hFrame1 = FXHorizontalFrame.new(self)
#progBar = FXProgressBar.new(hFrame1)
pp #progBar.barSize
#progBar.barSize=100
#progBar.setTotal(10)
#progBar.setProgress(5)
pp #progBar.barSize
def create
super
show(PLACEMENT_SCREEN)
end
end
end
FXApp.new do |app|
Test.new(app)
app.create
app.run
end
But this is what it looks like:
]1
So obviously the height gets changed. Obviously I also tried things like
:width => 150
in the constructor but it did not work at all. Seems like I'm just to stupid for fxruby. Could anyone point me to the right way please?
You need to learn about layout parameters. Try this modification of your Test class and I think you will know where to go from there:
class Test < FXMainWindow
def initialize(app)
super(app, "Test", :width => 200, :height => 100)
hFrame1 = FXHorizontalFrame.new(self, LAYOUT_FILL)
#progBar = FXProgressBar.new(hFrame1, :opts => LAYOUT_FILL_X)
pp #progBar.barSize
#progBar.barSize=10
#progBar.setTotal(10)
#progBar.setProgress(5)
pp #progBar.barSize
def create
super
show(PLACEMENT_SCREEN)
end
end
end
Related
I have a simple MySQL wrapper class which will run a query and return results.
class Rsql
def initialize(db)
#client = Mysql2::Client
#db = db
end
def execute_query()
client = #client.new(#db)
client.query("select 1")
end
end
I want to test some stuff involving the results of the query, but I don't want to actually connect to a database to get the results. I tried this test, but it doesn't work:
RSpec.describe Rsql do
it "does it" do
mock_database = double
rsql = Rsql.new(mock_database)
mock_mysql_client = double
allow(mock_mysql_client).to receive(:query).and_return({"1" => 1})
allow_any_instance_of(Mysql2::Client).to receive(:new).and_return(mock_mysql_client)
expect(rsql.execute_query).to eq({"1" => 1})
end
end
Replacing allow_any_instance_of() with allow() works. I was under the impression that allow_any_instance_of() was some kind of a global "pretend this class behaves in this way across the entire program" whereas allow() is for specific instances of a class.
Can someone explain this behavior to me? I'm new to Rspec, so I apologize if this answer is blatantly obvious. I tried searching for the answer, but I couldn't come up with the right search string to find one. Maybe I don't know enough to know when I've found it.
As of RSpec 3.3 , any_instance is deprecated and not recommended to use in your tests.
From the docs:
any_instance is the old way to stub or mock any instance of a class
but carries the baggage of a global monkey patch on all classes. Note
that we generally recommend against using this feature.
You should only need to use allow(some_obj) going forward and the documentation has some great examples (see here).
Such as:
RSpec.describe "receive_messages" do
it "configures return values for the provided messages" do
dbl = double("Some Collaborator")
allow(dbl).to receive_messages(:foo => 2, :bar => 3)
expect(dbl.foo).to eq(2)
expect(dbl.bar).to eq(3)
end
end
Edit, if you really want to use any_instance, do so like this:
(Mysql2::Client).allow_any_instance.to receive(:something)
Edit2, your exact stub doesn't work because you're not stubbing an instance, you're stubbing before the object is initialized. In that case you would do allow(Mysql2::Client).to receive(:new).
this Rsql class seems a service
class Rsql
def initialize(db)
#client = Mysql2::Client
#db = db
end
def execute_query()
client = #client.new(#db)
client.query("select 1")
end
end
lets create a test for it, now we should to test this function execute_query with subject ()
and to create clients in db we can use let! like this
let!(:client1) do
FactoryBot.create(...
with this we should not use double or something
require 'rails_helper'
RSpec.describe RsqlTest do
subject(:clients) do
Rsql.execute_query()
end
context 'select' do
let!(:client1) do
FactoryBot.create(...
end
it 'should return records' do
expect(clients).to include(client1)
end
end
end
I'm writing a horse race/bet game using Shoes and I was wondering how I would be able to change the GUI in different areas of code. When I run this, I get the horse on one application and then the race line on another application, but I want them both on the same application. Do I need to set the actual Shoes app as a variable itself?
class Horse
def initialize()
#puts "YOYOYOYO"
##number=i
Shoes.app{
#icon= image 'horsey.jpg'
#icon.left = 100
#icon.top = 50
}
end
def neigh()
#puts "Neighhhh"
end
def raceTime()
time=rand(100)%20
return time+10
end
end
class HorseIcon
def initialize(h)
#horse= h
#imageloc='horsey.jpg'
end
end
class Game
def initialize(h1, h2)
contestants=[h1, h2]
Shoes.app{
#icon= image 'raceline.jpg'
#icon.left = 100
#icon.top = 70
}
end
def race()
end
end
game= Game.new(1,2)
seabiscuit= Horse.new()
You are using two separate Shoes.app classes. I think that's your problem.
Judging by your code you seem to have a background in some other language, like Python.
I suggest you clone the Shoes git and look at 'Shoes/samples' directory and play around with it.
Or just look at this.
It will help you see what the code should look like.
PS : It will also give you some pointers toward Ruby style. You normally don't use {} for block when using multiple lines. You would use:
Shoes.app do
# code goes here
end
I am trying to use some functionality in ActiveModel but I'm having trouble making everything work. I've included my class file and the test I'm running.
The test is failing with:
': undefined method `attr_accessible
I really don't know why, since MassAssignmentSecurity will bring that in and it is in fact running. I've also tried to include all of ActiveModel as well but that's doesn't work either. It doesn't seem to matter if I use include or extend to bring in the MassAssignmentSecurity.
If I pass in some attributes in my test to exercise "assign_attributes" in the initialize, that fails as well. I'm fairly new to rails, so I'm hoping I'm just missing something really simple.
TIA.
Using rails 3.2.12
my_class.rb
class MyClass
include ActiveModel::MassAssignmentSecurity
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
extend ActiveSupport::Callbacks
attr_accessible :persisted, :creds
def initialize(attributes = nil, options = {})
#persisted = false
assign_attributes(attributes, options) if attributes
yield self if block_given?
end
end
my_class_spec.rb
require 'spec_helper'
describe MyClass do
before do
#testcase = MyClass.new
end
subject { #testcase }
it_should_behave_like "ActiveModel"
it { MyClass.should include(ActiveModel::MassAssignmentSecurity) }
it { should respond_to(:persisted) }
end
support/active_model.rb
shared_examples_for "ActiveModel" do
include ActiveModel::Lint::Tests
# to_s is to support ruby-1.9
ActiveModel::Lint::Tests.public_instance_methods.map{|m| m.to_s}.grep(/^test/).each do |m|
example m.gsub('_',' ') do
send m
end
end
def model
subject
end
end
Yikes! What a mess I was yesterday. Might as well answer my own question since I figured out my issues.
attr_accessible in MassAssignmentSecurity does not work like it does with ActiveRecord. It does not create getters and setters. You still have to use attr_accessor if you those created.
assign_attributes is a connivence function that someone wrote to wrap around mass_assignment_sanitizer and isn't something baked into in MassAssignment Security. An example implementation is below:
def assign_attributes(values, options = {})
sanitize_for_mass_assignment(values, options[:as]).each do |k, v|
send("#{k}=", v)
end
end
I'm writing something that is a bit like Facebook's shared link preview.
I would like to make it easily extendable for new sites by just dropping in a new file for each new site I want to write a custom parser for. I have the basic idea of the design pattern figured out but don't have enough experience with modules to nail the details. I'm sure there are plenty of examples of something like this in other projects.
The result should be something like this:
> require 'link'
=> true
> Link.new('http://youtube.com/foo').preview
=> {:title => 'Xxx', :description => 'Yyy', :embed => '<zzz/>' }
> Link.new('http://stackoverflow.com/bar').preview
=> {:title => 'Xyz', :description => 'Zyx' }
And the code would be something like this:
#parsers/youtube.rb
module YoutubeParser
url_match /(youtube\.com)|(youtu.be)\//
def preview
get_stuff_using youtube_api
end
end
#parsers/stackoverflow.rb
module SOFParser
url_match /stachoverflow.com\//
def preview
get_stuff
end
end
#link.rb
class Link
def initialize(url)
extend self with the module that has matching regexp
end
end
# url_processor.rb
class UrlProcessor
# registers url handler for given pattern
def self.register_url pattern, &block
#patterns ||= {}
#patterns[pattern] = block
end
def self.process_url url
_, handler = #patterns.find{|p, _| url =~ p}
if handler
handler.call(url)
else
{}
end
end
end
# plugins/so_plugin.rb
class SOPlugin
UrlProcessor.register_url /stackoverflow\.com/ do |url|
{:title => 'foo', :description => 'bar'}
end
end
# plugins/youtube_plugin.rb
class YoutubePlugin
UrlProcessor.register_url /youtube\.com/ do |url|
{:title => 'baz', :description => 'boo'}
end
end
p UrlProcessor.process_url 'http://www.stackoverflow.com/1234'
#=>{:title=>"foo", :description=>"bar"}
p UrlProcessor.process_url 'http://www.youtube.com/1234'
#=>{:title=>"baz", :description=>"boo"}
p UrlProcessor.process_url 'http://www.foobar.com/1234'
#=>{}
You just need to require every .rb from plugins directory.
If you're willing to take this approach you should probably scan the filed for the mathing string and then include the right one.
In the same situation I attempted a different approach. I'm extending the module with new methods, ##registering them so that I won't register two identically named methods. So far it works good, though the project I started is nowhere near leaving the specific domain of one tangled mess of a particular web-site.
This is the main file.
module Onigiri
extend self
##registry ||= {}
class OnigiriHandlerTaken < StandardError
def description
"There was an attempt to override registered handler. This usually indicates a bug in Onigiri."
end
end
def clean(data, *params)
dupe = Onigiri::Document.parse data
params.flatten.each do |method|
dupe = dupe.send(method) if ##registry[method]
end
dupe.to_html
end
class Document < Nokogiri::HTML::DocumentFragment
end
private
def register_handler(name)
unless ##registry[name]
##registry[name] = true
else
raise OnigiriHandlerTaken
end
end
end
And here's the extending file.
# encoding: utf-8
module Onigiri
register_handler :fix_backslash
class Document
def fix_backslash
dupe = dup
attrset = ['src', 'longdesc', 'href', 'action']
dupe.css("[#{attrset.join('], [')}]").each do |target|
attrset.each do |attr|
target[attr] = target[attr].gsub("\\", "/") if target[attr]
end
end
dupe
end
end
end
Another way I see is to use a set of different (but behaviorally indistinguishable) classes with a simple decision making mechanism to call a right one. A simple hash that holds class names and corresponding url_matcher would probably suffice.
Hope this helps.
#rspec test code
#room = FactoryGirl.build(:room)
#factory definition
factory :room do
length {10}
width {20}
end
#code implementation
class Room
attr_accessor :length, :width
def initialize(length,width)
#length = length
#width = width
end
end
Running rspec results in this error when trying to build the #room
ArgumentError:
wrong number of arguments (0 for 2)
Now it does. Tested on version 4.1:
FactoryGirl.define do
factory :room do
length 10
width 20
initialize_with { new(length, width) }
end
end
Reference: documentation
FactoryGirl does not currently support initializers with arguments. So it fails when it's trying to do Room.new when you run build.
One simple workaround for this might be to monkey-patch your classes in your test setup to get around this issue. It's not the ideal solution, but you'll be able to run your tests.
So you'd need to do either one of these (just in your test setup code):
class Room
def initialize(length = nil, width = nil)
...
end
end
or
class Room
def initialize
...
end
end
The issue is discussed here:
https://github.com/thoughtbot/factory_girl/issues/42
...and here:
https://github.com/thoughtbot/factory_girl/issues/19
What was useful for me, was enabling debug output for FactoryBot linting:
FactoryBot.lint verbose: true
see the documentation for the details