Generating a migration using a custom rails generator - ruby-on-rails-3

I took some time to learn how rails generators works and I managed to create one that copies some files and changes others. I call it this way:
rails generate menu test
But I need to make it generate a migration too, to create a table and add fields to it, something like:
rails generate menu test content:text
The number of arguments may vary, but it is a given that it'll always have an ID and a title column.
How can I accomplish this?

If you want:
$ rails generate scaffold test content:text
then have a look this Rails guide. It provides information such as:
[...] notice that we are inheriting from Rails::Generators::NamedBase instead of Rails::Generators::Base. This means that our generator expects at least one argument, which will be the name of the initializer, and will be available in our code in the variable name.
We can see that by invoking the description of this new generator (don't forget to delete the old generator file):
$ rails generate initializer --help
Usage:
rails generate initializer NAME [options]

Related

Generating CRUD in symfony 4

After releasing Symfony 4.0, there is no support for SensioGeneratorBundle. hence the command php app/console generate:doctrine:crud is not available.
They suggest to use MakerBundle, but I could not find appropriate replacement for CRUD generation.
Could anyone help?
You can use the make command in Symfony4+ (and it's quite an improvement!), from the MakerBundle:
php bin/console make:crud
It'll prompt you for which entity you want the crud for. It generates a controller with index, new, update, view and delete methods in /src/controller, with matching templates in /templates.
Useful to know: If you run make:entity, and later run that command again and enter an existing entity, it responds with:
Your entity already exists! So let's add some new fields!
At the moment MakerBundle supports just a few core commands. You can see the list here. Unfortunately there's no CRUD generator. But there some discussion about it in the issues so you can follow what will be done.
If what you need is just a generator for boilerplate code and not a more structured solution like EasyAdminBundle you should consider creating your own maker.
Symfony4 (thanks to #jelle)
composer require symfony/maker-bundle --dev
composer require symfony/form symfony/validator symfony/twig-bundle symfony/orm-pack symfony/security-csrf
php bin\console make:crud
The class name of the entity to create CRUD (e.g. BravePuppy):
>
first install pre-req packages
composer require twig-bundle security-csrf
and then you can run
php bin/console make:crud
after that just enter your entity name which you want to curd
The class name of the entity to create CRUD (e.g. BlogPosts):
>

How can I use Smarty templates with A/B testing?

I am attempting to build a little modification in our code to allow easier A/B testing.
I'd like to know if I can somehow
have my regular code under the /templates directory
have any a/b code under /templates/_abtests/, but also follow the same hierarchy as the regular code. for example... an ab test can overwrite a file like '/templates/foo.tpl', and use instead '/templates/_abtests/testfoo/foo.tpl'
I tried changing the template directory when in a test. Right before calling the display method, I would check if a user is in a test, and if so, set up the template_dir accordingly. I'd assign an array with the 'ab' directory first, then the default. I am using Smarty2.
the problem with this is that it caches the first instance, and uses that as the template for the baseline and ab test case. ie: i have a parameter to force me into a test bucket, but the template is the same.
thoughts on how to achieve this? goal is to not have to add a bunch of template hooks (if/else) in the templates. and achieve this by simple template/file includes.
I believe that the solution to my problem could be to put templates into folders. ie: /templates/base/, /templates/test_foo/, etc.". then in my template_dir setting, set the array up based on what test we are in.
I had tried this with mobile/desktop before, and forgot about this solution.
I can extend the smarty_template class and override the display method to change the template_dir. adding the test directory first.

Receiving "Pending" notifications from running Rspec

I'm near the end of Chapter 5 on Hartl's Tutorial. In the previous section (5.4), I have created a user signup page. Now I am required to check that I have created the user signup static page correctly by running rspec:
$ bundle exec rspec spec/
and I get this notice:
Pending:
StaticPagesHelper add some examples to (or delete) /Users/kelvinyu/rails_projects/sample_app/spec/helpers/static_pages_helper_spec.rb
# No reason given
# ./spec/helpers/static_pages_helper_spec.rb:12
static_pages/help.html.erb sample
# No reason given
# ./spec/views/static_pages/help.html.erb_spec.rb:4
static_pages/home.html.erb add some examples to (or delete) /Users/kelvinyu/rails_projects/sample_app/spec/views/static_pages/home.html.erb_spec.rb
# No reason given
# ./spec/views/static_pages/home.html.erb_spec.rb:4
Finished in 0.28953 seconds
16 examples, 0 failures, 3 pending
Randomized with seed 27698
Not sure what this "Pending" status really means and if I have an error. If so, what is the best way to fix this? Please let me know if more information is needed.
Pending means that the example is not yet implemented or finished.
In your case it means you need 3 more examples to implement.
How can you mark examples as pending? Usually you just omit the block when defining example (via it method). Or you can use the pending method. More information you can find here.
Those are the just the tests that are auto-generated along with the spec files when you create a model or controller. They're basically just placeholders until you create your own tests.
You're safe to (and should) delete them.
In recent Rails, newly generated controller spec includes the skip command, which will pend the test too.

Rails 3: Choose and run a Mechanize script from inside Rails action.

My application scrapes information from various sites using Mechanize. Naturally, each site requires custom Mechanize code. Each site is stored in my database, including the url to scrape and the string name of an .rb file containing that site's Mechanize code. For this case, let's assume the scripts are available in the assets folder.
I would like to call http://example.com/site/:id, then have the show action dynamically choose which Mechanize script to run (say, #site.name + ".rb" ). The script will massage the data into a common model, so all sites can use the same show template.
I can't find a way to dynamically load a .rb script within an action and obtain the result. It may be easier to have the scripts return a JSON string, which I can parse before passing on to the template, but I can't see a solution for that either. Ideally, the script will run in the action's scope. The ugly solution is an enormous if-else chain (testing the site name to determine which code block to run), but there must be a better way.
Any suggestions would be greatly appreciated, as would any general solutions to running different code dependent upon the properties of database objects.
If you have all the code in your app already why are you eval'ing Ruby code?
Create classes like:
class GoogleSpider < Spider; end
class NewYorkTimesSpider < Spider; end
class SomeOtherSpider < Spider; end
And the site class will hold the class name that will be used, so you would be able to easily do something like this in your controller action:
def show
#site = Site.find(params[:id])
# name contains SomeOtherSpider
#process_output = #site.name.constantize.new.process
# do something with the output here
end
And then you don't need to mess around evaluating Ruby code, just call the class needed. You can even make them all singletons or keep them all in a hash for faster access.

Need guidance in creating Rails 3 Engine/Plugin/Gem

I need some help figuring out the best way to proceed with creating a Rails 3 engine(or plugin, and/or gem).
Apologies for the length of this question...here's part 1:
My company uses an email service provider to send all of our outbound customer emails. They have created a SOAP web service and I have incorporated it into a sample Rails 3 app. The goal of creating an app first was so that I could then take that code and turn it into a gem.
Here's some of the background: The SOAP service has 23 actions in all and, in creating my sample app, I grouped similar actions together. Some of these actions involve uploading/downloading mailing lists and HTML content via the SOAP WS and, as a result, there is a MySQL database with a few tables to store HTML content and lists as a sort of "staging area".
All in all, I have 5 models to contain the SOAP actions (they do not inherit from ActiveRecord::Base) and 3 models that interact with the MySQL database.
I also have a corresponding controller for each model and a view for each SOAP action that I used to help me test the actions as I implemented them.
So...I'm not sure where to go from here. My code needs a lot of DRY-ing up. For example, the WS requires that the user authentication info be sent in the envelope body of each request. So, that means each method in the model has the same auth info hard coded into it which is extremely repetitive; obviously I'd like for that to be cleaner. I also look back now through the code and see that the requests themselves are repetitive and could probably be consolidated.
All of that I think I can figure out on my own, but here is something that seems obvious but I can't figure out. How can I create methods that can be used in all of my models (thinking specifically of the user auth part of the equation).
Here's part 2:
My intention from the beginning has been to extract my code and package it into a gem incase any of my ESP's other clients could use it (plus I'll be using it in several different apps). However, I'd like for it to be very configurable. There should be a default minimal configuration (i.e. just models that wrap the SOAP actions) created just by adding the gem to a Gemfile. However, I'd also like for there to be some tools available (like generators or Rake tasks) to get a user started. What I have in mind is options to create migration files, models, controllers, or views (or the whole nine yards if they want).
So, here's where I'm stuck on knowing whether I should pursue the plugin or engine route. I read Jordan West's series on creating an engine and I really like the thought of that, but I'm not sure if that is the right route for me.
So if you've read this far and I haven't confused the hell out of you, I could use some guidance :)
Thanks
Let's answer your question in parts.
Part One
Ruby's flexibility means you can share code across all of your models extremely easily. Are they extending any sort of class? If they are, simply add the methods to the parent object like so:
class SOAPModel
def request(action, params)
# Request code goes in here
end
end
Then it's simply a case of calling request in your respective models. Alternatively, you could access this method statically with SOAPModel.request. It's really up to you. Otherwise, if (for some bizarre reason) you can't touch a parent object, you could define the methods dynamically:
[User, Post, Message, Comment, File].each do |model|
model.send :define_method, :request, proc { |action, params|
# Request code goes in here
}
end
It's Ruby, so there are tons of ways of doing it.
Part Two
Gems are more than flexible to handle your problem; both Rails and Rake are pretty smart and will look inside your gem (as long as it's in your environment file and Gemfile). Create a generators directory and a /name/name_generator.rb where name is the name of your generator. The just run rails g name and you're there. Same goes for Rake (tasks).
I hope that helps!