AngularJS দিয়ে শুরু করা কঠিন নয়। ডকুমেন্টেশনটি সেখানকার সেরা কিছু এবং এর টিউটোরিয়ালগুলি যথেষ্ট সহজ৷
৷কিন্তু আপনি যখন প্রযুক্তির সমন্বয় শুরু করেন তখন জিনিসগুলি কঠিন হয়ে যায়৷৷
আপনি যদি সরাসরি জাভাস্ক্রিপ্টের পরিবর্তে CoffeeScript ব্যবহার করেন, তাহলে আপনি জানেন যে প্রি-প্রসেসিং উদ্বেগগুলি বিবেচনায় নিতে হবে - সেইসাথে সুস্পষ্ট সিনট্যাক্স পার্থক্য। এগুলি নিজেরাই ছোটখাটো সমস্যা, কিন্তু আপনি যদি রুবিকে রেল, জেসমিন এবং কর্মাকে মিশে ফেলেন? এটি আশ্চর্যজনকভাবে জটিল হয়ে ওঠে৷
এটি ঠিক সেই স্ট্যাক যা আমরা এই টিউটোরিয়ালে ব্যবহার করতে যাচ্ছি। এই কারণে নয় যে আমরা শাস্তির জন্য পেটুক, কিন্তু কারণ এই ধরনের সেটআপ আপনি বাস্তব জগতে দেখতে পাবেন৷
এই টিউটোরিয়ালটি অনুমান করে যে আপনি রেলের সাথে স্বাচ্ছন্দ্য বোধ করছেন, তবে অগত্যা অ্যাঙ্গুলারজেএস নয়৷
একটি বেস রেল অ্যাপ তৈরি করা
যেহেতু অনেক প্রযুক্তির স্তর জড়িত, আমি একটি সাধারণ অ্যাপ্লিকেশন তৈরি করতে যাচ্ছি যা সবেমাত্র কিছু করে না। আমরা রেস্তোরাঁগুলির জন্য CRUD কার্যকারিতা সেট আপ করব - আসলে, শুধুমাত্র CR অংশ৷ -ইউডি পাঠকের জন্য একটি অনুশীলন হিসাবে রেখে দেওয়া হয়েছে।;-)
আমরা অ্যাপ্লিকেশনটিকে কল করব রেস্তোরাঁ .
আমি এখানে PostgreSQL এবং RSpec ব্যবহার করছি, কিন্তু DBMS এবং সার্ভার-সাইড টেস্টিং ফ্রেমওয়ার্ক উল্লেখযোগ্য নয়। আপনি যা চান তা ব্যবহার করতে পারেন।
প্রাথমিক সেটআপ
প্রথমে প্রকল্প তৈরি করুন:
$ rails new restauranteur --database=postgresql --skip-test-unit
আপনি যদি Pow ব্যবহার করেন, তাহলে আপনার প্রোজেক্টটি Pow এ যোগ করুন:
$ ln -s /Users/jasonswett/projects/restauranteur ~/.pow/restauranteur
PostgreSQL ডাটাবেস ব্যবহারকারী তৈরি করুন:
$ createuser -P -s -e restauranteur
আপনার জেমফাইলে RSpec যোগ করুন:
# Gemfile
gem "rspec-rails", "~> 2.14.0"
RSpec ইনস্টল করুন:
$ bundle install
$ rails g rspec:install
ডাটাবেস তৈরি করুন:
$ rake db:create
রেস্তোরাঁর মডেল তৈরি করা হচ্ছে
এখন যেহেতু আমরা আমাদের প্রকল্প এবং ডাটাবেস তৈরি করেছি, আসুন আমাদের প্রথম সংস্থান তৈরি করি। রেস্তোরাঁর সম্পদের শুধুমাত্র একটি বৈশিষ্ট্য থাকবে:নাম , যা একটি স্ট্রিং।
$ rails generate scaffold restaurant name:string
এখন, এটি সম্পর্কে OCD হওয়ার জন্য, আমরা নিশ্চিত করব যে রেস্টুরেন্টের নামগুলি অনন্য।
# db/migrate/[timestamp]_create_restaurants.rb
class CreateRestaurants < ActiveRecord::Migration
def change
create_table :restaurants do |t|
t.string :name
t.timestamps
end
# Add the following line
add_index :restaurants, :name, unique: true
end
end
মাইগ্রেশন চালান:
$ rake db:migrate
আসুন আমরা অবৈধ রেস্তোরাঁ তৈরি করতে পারি না তা যাচাই করতে কিছু স্পেস যোগ করি। লক্ষ্য করুন যে অনন্য ব্যর্থতা কাঁচা ত্রুটি দেয়৷
require 'spec_helper'
describe Restaurant do
before do
@restaurant = Restaurant.new(name: "Momofuku")
end
subject { @restaurant }
it { should respond_to(:name) }
it { should be_valid }
describe "when name is not present" do
before { @restaurant.name = " " }
it { should_not be_valid }
end
describe "when name is already taken" do
before do
restaurant_with_same_name = @restaurant.dup
restaurant_with_same_name.name = @restaurant.name.upcase
restaurant_with_same_name.save
end
it { should_not be_valid }
end
end
এই ভ্যালিডেটরগুলিকে যোগ করলে স্পেক্স পাস হবে:
class Restaurant < ActiveRecord::Base
validates :name, presence: true, uniqueness: { case_sensitive: false }
end
আমরা এখন এগিয়ে যেতে ভালো।
AngularJS-কে মিশ্রণে নিয়ে আসা
আপনার উপর একবারে সবকিছু ফেলে দেওয়ার পরিবর্তে, আমি প্রথমে একটি AngularJS-Rails অ্যাপ্লিকেশনের সহজতম "হ্যালো, ওয়ার্ল্ড" সংস্করণ প্রদর্শন করতে চাই এবং তারপরে আমাদের রেস্টুরেন্ট CRUD কার্যকারিতা তৈরি করতে চাই।
আমাদের "হ্যালো, ওয়ার্ল্ড" পৃষ্ঠাটি কোনও নির্দিষ্ট রেল সংস্থানের সাথে আবদ্ধ হওয়া উচিত বা হওয়া উচিত এমন কোনও কারণ নেই৷ এই কারণে, আমরা একটি StaticPagesController
তৈরি করব আমাদের AngularJS হোম পেজ পরিবেশন করতে।
নিয়ন্ত্রক তৈরি করুন
$ rails generate controller static_pages index
আমাদের রুট রুট এই মুহূর্তে শুধুমাত্র "রেলগুলিতে স্বাগতম" পৃষ্ঠা। এটিকে index
-এ সেট করা যাক আমাদের নতুন StaticPagesController
-এর ক্রিয়া :
# config/routes.rb
Restauranteur::Application.routes.draw do
# Add the following line
root 'static_pages#index'
end
কৌণিক ডাউনলোড করুন
- আমাদের পরীক্ষাগুলি পরে সঠিকভাবে কাজ করার জন্য, আমাদের
angular-mocks.js
নামে একটি ফাইলের প্রয়োজন হবে . আমি মনে করি না যে কৌণিক নথিতে কোথাও এর উল্লেখ আছে, তবে এটি প্রয়োজনীয়৷ - AngularJS টিউটোরিয়ালে, ডক্সে লেটেস্ট ব্লিডিং-এজ সংস্করণের তালিকা করা হয়েছে, কিন্তু যদি আমি সঠিকভাবে মনে করি, আমার
angular.js
এর মধ্যে সামঞ্জস্যের সমস্যা ছিল। এবংangular-mocks.js
সর্বশেষ সংস্করণের জন্য। আমি জানি যে সংস্করণ 1.1.5 একসাথে কাজ করেছে, তাই যদিও এটি সর্বশেষ স্থিতিশীল সংস্করণ নয়, আমি এখানে তালিকাভুক্ত করছি সেই সংস্করণটি। অবশ্যই সময়ের সাথে সাথে সামঞ্জস্য পরিস্থিতির উন্নতি হবে।
ডাউনলোড করুন angular.js
এবং angular-mocks.js
code.angularjs.org থেকে ফাইলগুলিকে app/assets/javascripts
-এ সরান .
$ wget https://code.angularjs.org/1.1.5/angular.js \
https://code.angularjs.org/1.1.5/angular-mocks.js
$ mv angular* app/assets/javascripts
এটি সম্পদ পাইপলাইনে যোগ করুন
এখন আমরা আমাদের অ্যাপ্লিকেশনকে বলতে চাই AngularJS ফাইলের প্রয়োজন, এবং আমরা নিশ্চিত করতে চাই যে এটির উপর নির্ভরশীল অন্যান্য ফাইলের আগে এটি লোড হয়। (এই নির্ভরতাগুলি পরিচালনা করতে আমরা RequireJS-এর মতো কিছু ব্যবহার করতে পারি, এবং সম্ভবত এটিই আমি একটি উত্পাদন পণ্যে করব, কিন্তু এই টিউটোরিয়ালের উদ্দেশ্যে আমি প্রযুক্তির স্ট্যাকটিকে যতটা সম্ভব পাতলা রাখতে চাই।)
দ্রষ্টব্য: কৌণিক এবং টার্বোলিংক একে অপরের সাথে বিরোধ করতে পারে, তাই আমরা সেগুলিকে এখানে নিষ্ক্রিয় করি
// app/assets/javascripts/application.js
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
// Add the following two lines
//= require angular
//= require main
//= require_tree .
লেআউট সেট আপ করুন
৷আমরা ng-app এবং ng-view যোগ করব, যা আমাদের পৃষ্ঠায় একটি কৌণিক অ্যাপ আছে বলে ইঙ্গিত দেয়। এছাড়াও লক্ষ্য করুন যে Turbolinks এর উল্লেখ মুছে ফেলা হয়েছে।
<%= yield %>
একটি কৌণিক নিয়ন্ত্রক তৈরি করা
প্রথমে আমাদের কন্ট্রোলারের জন্য একটি ডিরেক্টরি তৈরি করা যাক। আপনি যা খুশি নাম দিতে পারেন।
$ mkdir -p app/assets/javascripts/angular/controllers
এখন কন্ট্রোলার ফাইল নিজেই তৈরি করা যাক। আমি এই কন্ট্রোলারটিকে "হোম কন্ট্রোলার" বলছি এবং অ্যাঙ্গুলার কনভেনশন হল আপনার কন্ট্রোলার ফাইলের নাম Ctrl
দিয়ে যুক্ত করা . এইভাবে আমাদের ফাইলের নাম হবেapp/assets/javascripts/angular/controllers/HomeCtrl.js.coffee
:
# app/assets/javascripts/angular/controllers/HomeCtrl.js.coffee
@restauranteur.controller 'HomeCtrl', ['$scope', ($scope) ->
# Notice how this controller body is empty
]
একটি কৌণিক রুট যোগ করুন
এখন আমরা আমাদের HomeCtrl
তৈরি করার জন্য একটি রাউটিং নির্দেশিকা যোগ করব আমাদের "ডিফল্ট পৃষ্ঠা।" এখানে আমি app/assets/javascripts/main.js.coffee
-এ আমার রাউটিং সংজ্ঞায়িত করছি , কিন্তু আবার আমি মনে করি না যে ফাইলের নাম গুরুত্বপূর্ণ।
# app/assets/javascripts/main.js.coffee
# This line is related to our Angular app, not to our
# HomeCtrl specifically. This is basically how we tell
# Angular about the existence of our application.
@restauranteur = angular.module('restauranteur', [])
# This routing directive tells Angular about the default
# route for our application. The term "otherwise" here
# might seem somewhat awkward, but it will make more
# sense as we add more routes to our application.
@restauranteur.config(['$routeProvider', ($routeProvider) ->
$routeProvider.
otherwise({
templateUrl: '../templates/home.html',
controller: 'HomeCtrl'
})
])
একটি কৌণিক টেমপ্লেট যোগ করুন
আমরা আমাদের কৌণিক টেমপ্লেটগুলি রাখার জন্য একটি জায়গাও চাইব। আমি আমার public/templates
-এ রাখার সিদ্ধান্ত নিয়েছি . আবার, আপনি যেখানে খুশি সেখানে রাখতে পারেন।
mkdir public/templates
যদি আমরা একটি ফাইল public/templates/home.html
তৈরি করি কিছু স্বেচ্ছাচারী বিষয়বস্তুর সাথে, আমাদের ব্রাউজারে এটি দেখতে সক্ষম হওয়া উচিত।
This is the home page.
এখন, আপনি যদি https://restauranteur.dev/
যান (বা https://localhost:3000/
আপনি যদি Pow ব্যবহার না করেন) এবং আপনার home.html
এর বিষয়বস্তু দেখতে হবে .
ডেটা বাইন্ডিংয়ের একটি উদাহরণ
এটা ধরনের আকর্ষণীয়, কিন্তু সম্ভবত খুব চিত্তাকর্ষক নয়। এর আসলে তারের জুড়ে কিছু পাঠান. আপনার app/assets/angular/controllers/HomeCtrl.js.coffee
সম্পাদনা করুন এই মত:
# app/assets/angular/controllers/HomeCtrl.js.coffee
@restauranteur.controller 'HomeCtrl', ['$scope', ($scope) ->
$scope.foo = 'bar'
]
এটি @foo = "bar"
বলার মত একরকম একটি রেল কন্ট্রোলারে। আমরা foo
প্লাগ করতে পারি এই মত ডবল-বন্ধনী সিনট্যাক্স ব্যবহার করে টেমপ্লেটে:
Value of "foo": {{foo}}
এবার বাস্তবে এটি করা হচ্ছে
আমরা ইতিমধ্যে একটি সাধারণ হ্যালো ওয়ার্ল্ড অ্যাপ তৈরি করেছি। একটি সম্পূর্ণ বিকশিত CRUD অ্যাপ্লিকেশন তৈরি করা খুব বেশি কঠিন নয়৷
৷ডাটাবেস বীজ করুন
আমাদের রেস্তোরাঁ CRUD এর সাথে কাজ করা একটু বেশি অর্থবহ হবে যদি আমরা ডাটাবেসের কিছু রেস্টুরেন্ট দিয়ে শুরু করি। এখানে একটি বীজ ফাইল আপনি ব্যবহার করতে পারেন।
# db/seeds.rb
Restaurant.create([
{ name: "The French Laundry" },
{ name: "Chez Panisse" },
{ name: "Bouchon" },
{ name: "Noma" },
{ name: "Taco Bell" },
])
rake db:seed
একটি রেস্টুরেন্ট সূচী পৃষ্ঠা তৈরি করা
প্রথমে রেস্টুরেন্টের জন্য একটি টেমপ্লেট ফোল্ডার তৈরি করা যাক:
mkdir public/templates/restaurants
প্রথম টেমপ্লেটটি আমরা তৈরি করব ইনডেক্স পেজ:
[index](/#)
* {{ restaurant.name }}
আমি এক মুহূর্তের মধ্যে ব্যাখ্যা করব এই জিনিসগুলোর মানে কি। প্রথমে কন্ট্রোলার তৈরি করা যাক:
# app/assets/javascripts/angular/controllers/RestaurantIndexCtrl.js.coffee
@restauranteur.controller 'RestaurantIndexCtrl', ['$scope', '$location', '$http', ($scope, $location, $http) ->
$scope.restaurants = []
$http.get('./restaurants.json').success((data) ->
$scope.restaurants = data
)
]
অবশেষে, আমরা আমাদের রাউটিং কনফিগারেশন সামঞ্জস্য করব:
# app/assets/javascripts/main.js.coffee
@restauranteur = angular.module('restauranteur', [])
@restauranteur.config(['$routeProvider', ($routeProvider) ->
$routeProvider.
when('/restaurants', {
templateUrl: '../templates/restaurants/index.html',
controller: 'RestaurantIndexCtrl'
}).
otherwise({
templateUrl: '../templates/home.html',
controller: 'HomeCtrl'
})
])
এখন, অবশেষে, আমরা URI /#/restaurants
-এ যেতে পারি এবং আমরা আমাদের রেস্টুরেন্টের তালিকা দেখতে সক্ষম হওয়া উচিত। আমরা এগিয়ে যাওয়ার আগে আসুন একটি পরীক্ষা যোগ করি।
আমাদের প্রথম পরীক্ষা যোগ করা হচ্ছে
JS পরীক্ষা ফোল্ডার যোগ করুন:
mkdir spec/javascripts
পরীক্ষা লিখুন:
# spec/javascripts/controllers_spec.js.coffee
describe "Restauranteur controllers", ->
beforeEach module("restauranteur")
describe "RestaurantIndexCtrl", ->
it "should set restaurants to an empty array", inject(($controller) ->
scope = {}
ctrl = $controller("RestaurantIndexCtrl",
$scope: scope
)
expect(scope.restaurants.length).toBe 0
)
কনফিগার যোগ করুন:
// spec/javascripts/restauranteur.conf.js
module.exports = function(config) {
config.set({
basePath: '../..',
frameworks: ['jasmine'],
autoWatch: true,
preprocessors: {
'**/*.coffee': 'coffee'
},
files: [
'app/assets/javascripts/angular.js',
'app/assets/javascripts/angular-mocks.js',
'app/assets/javascripts/main.js.coffee',
'app/assets/javascripts/angular/controllers/RestaurantIndexCtrl.js.coffee',
'app/assets/javascripts/angular/*',
'spec/javascripts/*_spec.js.coffee'
]
});
};
কর্ম ইনস্টল করুন এবং সার্ভার শুরু করুন:
sudo npm install -g karma
sudo npm install -g karma-ng-scenario
karma start spec/javascripts/restauranteur.conf.js
আপনি যদি https://localhost:9876/
যান , আমাদের পরীক্ষা চালানো হবে এবং সফল হবে. আপনি যদি পরীক্ষা ব্যর্থ দেখতে চান, তাহলে expect(scope.restaurants.length).toBe 0
পরিবর্তন করুন। toexpect(scope.restaurants.length).toBe 1
এবং আবার পরীক্ষা চালান।
আমরা এইমাত্র যোগ করেছি এই পরীক্ষার অর্থবহতা স্পষ্টতই সন্দেহজনক, কিন্তু এখানে আমার উদ্দেশ্য হল আপনার কৌণিক কোডটি কীভাবে একটি পরীক্ষার জোতাতে পাওয়া যায় তা খুঁজে বের করার কাজটি সংরক্ষণ করা। কিছু জিনিস আছে, যেমন CoffeeScript প্রিপ্রসেসর এবংangular-mocks.js
অন্তর্ভুক্তি যা সম্পূর্ণরূপে সুস্পষ্ট নয় এবং আমাকে ঠিক করতে কয়েক ঘন্টা মাথা ঘামাচ্ছে।
রেস্তোরাঁর পৃষ্ঠা তৈরি করা
এখন আমাদের রেস্টুরেন্ট সূচী টেমপ্লেটে একটি অস্থায়ী সমন্বয় করা যাক:
* {{restaurant.name}} ({{restaurant.id}})
আপনি যদি এখন /#/restaurants
আবার যান , আপনি লক্ষ্য করবেন যে রেস্তোরাঁর কোনোটিরই তাদের আইডি নেই। কেন তারা ফাঁকা?
আপনি যখন Rails 4 এ ভারা তৈরি করেন, এটি আপনাকে কিছু .jbuilder
দেয় ফাইল:
$ ls -1 app/views/restaurants/*.jbuilder
app/views/restaurants/index.json.jbuilder
app/views/restaurants/show.json.jbuilder
আপনি app/views/restaurants/index.json.jbuilder
খুললে , আপনি এটি দেখতে পাবেন:
# app/views/restaurants/index.json.jbuilder
json.array!(@restaurants) do |restaurant|
json.extract! restaurant, :name
json.url restaurant_url(restaurant, format: :json)
end
আপনি দেখতে পাচ্ছেন, এতে রয়েছে :name
কিন্তু :id
নয় . এটা যোগ করা যাক:
# app/views/restaurants/index.json.jbuilder
json.array!(@restaurants) do |restaurant|
json.extract! restaurant, :id, :name
json.url restaurant_url(restaurant, format: :json)
end
আপনি যদি ফাইলটি সংরক্ষণ করেন এবং /#/restaurants
রিফ্রেশ করেন , আপনার আইডি প্রদর্শিত হওয়া উচিত।
এখন টেমপ্লেটটিকে আগের মতই পরিবর্তন করা যাক:
[index](/#)
* {{ restaurant.name }}
আপনি হয়তো কিছু সময়ে লক্ষ্য করেছেন যে আমরা এই জিনিসগুলিকে viewRestaurant()
নামক কিছুতে নির্দেশ করছি কিন্তু আমরা আসলে viewRestaurant()
নামে কিছু সংজ্ঞায়িত করিনি . এখন এটা করা যাক:
# app/assets/javascripts/angular/controllers/RestaurantIndexCtrl.js.coffee
@restauranteur.controller 'RestaurantIndexCtrl', ['$scope', '$location', '$http', ($scope, $location, $http) ->
$scope.restaurants = []
$http.get('./restaurants.json').success((data) ->
$scope.restaurants = data
)
# Add the following lines
$scope.viewRestaurant = (id) ->
$location.url "/restaurants/#{id}"
]
রেলের কনভেনশন হল resource_name/:id
একটি "শো" পৃষ্ঠার মানচিত্র, এবং আমরা এখানে এটিই করব। আসুন একটি শো টেমপ্লেট, রুট এবং কন্ট্রোলার তৈরি করি।
# {{restaurant.name}}
# app/assets/javascripts/main.js.coffee
@restauranteur = angular.module('restauranteur', [])
@restauranteur.config(['$routeProvider', ($routeProvider) ->
$routeProvider.
when('/restaurants', {
templateUrl: '../templates/restaurants/index.html',
controller: 'RestaurantIndexCtrl'
}).
when('/restaurants/:id', {
templateUrl: '../templates/restaurants/show.html',
controller: 'RestaurantShowCtrl'
}).
otherwise({
templateUrl: '../templates/home.html',
controller: 'HomeCtrl'
})
])
# app/assets/javascripts/angular/controllers/RestaurantShowCtrl.js.coffee
@restauranteur.controller 'RestaurantShowCtrl', ['$scope', '$http', '$routeParams', ($scope, $http, $routeParams) ->
$http.get("./restaurants/#{$routeParams.id}.json").success((data) ->
$scope.restaurant = data
)
]
এখন আপনি যদি /#/restaurants
রিফ্রেশ করেন এবং একটি রেস্টুরেন্টে ক্লিক করুন, আপনি নিজেকে সেই রেস্টুরেন্টের শো পৃষ্ঠায় খুঁজে পাবেন। হ্যাঁ!
এটুকুই এখনকার জন্য
আমরা হয়ত বিশেষভাবে চিত্তাকর্ষক ফলাফল দেখতে পাইনি, কিন্তু আমি আশা করি আমি AngularJS কে Rails 4 এ প্লাগ করার জন্য আপনার কিছু সময় বাঁচিয়েছি। এর পরে আমি ইনটিং রিসোর্স দেখার সুপারিশ করতে পারি, যা CRUD কার্যকারিতা আরও শুষ্ক করতে সাহায্য করতে পারে।
আরো শিখতে আগ্রহী?
অ্যাডাম অ্যান্ডারসনের দুর্দান্ত পোস্টটি দেখুন, যার রেল 4.0 সিরিজে একটি অ্যাঙ্গুলারজেএস অ্যাপের বুটস্ট্র্যাপিং আমাকে অ্যাঙ্গুলারজেএস এবং রেলগুলির সাথে শুরু করতে সহায়তা করেছে। আপনি তার টিউটোরিয়ালটিও দেখতে পছন্দ করতে পারেন, কিন্তু এই টিউটোরিয়ালটি এই অর্থে ভিন্ন যে আমি আপনাকে সমস্ত বিবরণ _really_spoon-feed করার চেষ্টা করি, আপনার আগাছায় আটকে যাওয়ার সম্ভাবনা কমিয়ে দেয়।